2016-07-24 4 views
0

Я пытаюсь написать простую функцию, которая преобразует число в строку относительно заданного формата, что-то вроде этого:Функции в C с типом данными неизвестных входного

char * write_number(const char *format, void *number) { 
    char mystring[50]; 
    sprintf(mystring, format, number); 
    return mystring; 
} 

Единственная проблема заключается в что это работает с целым типом данных, но не с типом данных float/double. Есть ли способ сделать эту работу независимо от типа данных.

Спасибо!

Дополнение к первоначальному вопросу:

Спасибо за ваши предложения. Мне не удалось заставить его работать, вот полный пример того, что я пытаюсь получить.

#include <stdio.h> 

void write_number(const char *format, void *number) { 
    char mystring[50]; 
    sprintf(mystring, format, *number); 
    printf("%s\n", mystring); 
} 

int main(void) { 
    int a = 10; 
    float b = 20; 
    double c = 40; 

    write_number("int: %03d", &a); 
    write_number("float: %6.2f", &b); 
    write_number("double: %6.2f", &c); 

    return 0; 
} 
+2

Нет, и эта функция в любом случае нарушена: она возвращает адрес локальной переменной. – melpomene

+0

Да, это правда, функция не работает из-за неправильного оператора return. Но почему это работает с целым типом данных? –

+0

добавить это: printf ("void * =% d, int =% d, float =% d, double =% d", sizeof (void *), sizeof (int), sizeof (float), sizeof (double)) , я предполагаю, что вы получите 4, 4, 8, 8 (assumin g float не работает), или если float работает, вы получите 4, 4, 4, 8. – Alex

ответ

0

Строка формата для sprintf определяет тип данных, например, "%i" отпечатков и целые и "%f" отпечатков с плавающей точкой - значит, вы должны изменить формат строку в зависимости от типа данных.

Обратите также внимание на то, что функция не гарантирована для работы с ints, так как она возвращает указатель на локальную переменную mystring, это исчезнет из области действия, когда функция вернется и может быть перезаписана в любое время другим значением, поэтому возвращаемый указатель будет указывать на некоторое случайное значение, а не на строку.

-1

sprintf уже заботится о типах своих аргументов; вам просто нужно убедиться, что строка формата, которую вы передаете ей, соответствует ее аргументам. Например, "%f", 3.125f для форматирования float, "%d", 12 для форматирования целого числа со знаком, "%e", 3.125 для форматирования плавания с двойной точностью. Попробуйте прочитать this.

Ваша функция не будет работать в любом случае, поскольку ошибки компиляции скажут вам. mystring объявлен как локальная переменная в стеке, поэтому она перестанет существовать, когда ваша функция вернется.

Кроме того, вы пропускание адреса из number в sprintf вместо его значения. Чтобы передать значение, вам необходимо разыменования это так: sprintf(mystring, format, *number);

Вы функция может работать с целочисленного типа, потому что указатели являются неотъемлемой частью, так что если вы назвали write_number("%d\n", 55), вы бы передавая указатель на адрес памяти 55, который sprintf будет интерпретироваться как целое число из-за %d. Если ваши int s и void * s не были одинакового размера, это не сработало бы.

Чтобы действительно передать указатель вместо междунар литого указателя сделать что-то вроде этого:

char *str; 
float num = 8.375f; 
str = write_number("%f", &num); 
+0

Итак, если я назову его как write_number («% f», 1.0f), это не сработает? (Я знаю, что это не так, я уже пробовал это). Есть ли способ заставить его работать, поскольку sprintf преобразует тип данных в отношении данного формата? Не обращайте внимания на заявление о возврате, я знаю, что это неправильно и как его исправить. –

+0

@Marko Ну, скорее всего, он будет работать с литой, потому что поплавки обычно имеют тот же размер, что и ints и указатели. Но на самом деле вам нужно объявить float в другом месте и передать указатель на него. – nebuch

+0

Я пытаюсь написать функцию для микроконтроллера dsPIC, поэтому типы данных int и float не имеют одинакового размера. Хорошо, похоже, что это не может работать вообще. Я надеялся, что функция sprintf преобразует сам тип данных в отношении данного формата. –

0

Для вызывающего кода использовать адрес локальных переменной mystring[] является неопределенного поведения.

«Почему это работает с целым типом данных?"

Неопределенное поведение не означает, что код„не будет работать“. Это не означает, что, если он работает в настоящее время (с целым), он будет работать завтра. Это означает, что поведение не определен

Смежные вопросы