#c
Вопрос:
Эти вопросы касаются моей домашней работы.
Эту тему нужно использовать, как:
#define GENERIC_MAX(type)
type type##_max(type x, type y)
{
return x > y ? x : y;
}
Суть вопроса в том, чтобы заставить этот код работать нормально:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Результат операции выглядит следующим образом:
i=5.2000
j=3
И этот код-мой текущий прогресс, но есть проблемы:
#include <stdio.h>
#define printname(n) printf(#n);
#define GenerateShowValueFunc(type)
type showValue_##type(type x)
{
printname(x);
printf("=%dn", x);
return 0;
}
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Я не знаю, как изменить вывод с помощью типа, и я не знаю, как отобразить имя переменной. ОАО
Это оригинальное описание задачи: Пожалуйста, обратитесь к ShowValue.c ниже:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
С помощью [GenerateShowValueFunc(double)] и [GenerateShowValueFunc(int)] эти две строки вызова макросов могут помочь нам сгенерировать функции [showValue_double( double )] и [showValue_int( int )], а также в вызываемой функции main (). Результат выполнения этой программы выглядит следующим образом:
i=5.2000
j=3
Пожалуйста, вставьте код, определяющий макрос GenerateShowValueFunc, в соответствующее место в программе ShowValue.c, чтобы эта программа могла скомпилироваться и работать бесперебойно.
Комментарии:
1. Язык C не обеспечивает поддержку, которая облегчает работу с типами в общем виде. Это не очень хорошее домашнее задание для вводного курса C. Как называется этот курс? Вы можете создать некоторый код с гибким типом, используя
_Generic
. Если это так, то курс должен был рассказать об_Generic
этом ; от вас не ожидали бы, что вам придется открывать его для выполнения задания.2. Возможно, домашнее задание состоит в том , чтобы просто создать
GENERIC_MAX
макрос , и вы должны продемонстрировать и протестировать этот макрос, используя определенный отдельный код дляint
, аdouble
не написав общий код для демонстрации и тестирования?3. Возможно, вам понадобится еще один макрос, который принимает имя переменной для отображения и использует его с оператором строковой обработки.
4. Это неразумное использование макроса IMO. Почему они учат этому, когда ни один профессиональный разработчик не счел бы это каким-либо образом «нормальным».
5. @ОАО «Армали»
Ответ №1:
Быстрым и грязным решением было бы:
type showValue_##type(type x)
{
const char* double_fmt = "=%fn";
const char* int_fmt = "=%dn";
printname(x);
printf(type##_fmt, x);
return 0;
}
Компилятор оптимизирует переменную, которая не используется, поэтому это не повлияет на производительность. Но это может привести к предупреждениям «переменная не используется». Вы можете добавить операторы null, например (void)double_fmt;
, чтобы заставить его замолчать.
В любом случае, все это очень хрупко и подвержено ошибкам, никогда не рекомендовалось писать макросы, подобные этим. И это не то, как вы занимаетесь общим программированием в современном C. Вы можете научить своего учителя этому, показав им следующий пример:
#include <stdio.h>
void double_show (double d)
{
printf("%fn", d);
}
void int_show (int i)
{
printf("%dn", i);
}
#define show(x) _Generic((x),
double: double_show,
int: int_show) (x) // the x here is the parameter passed to the function
int main()
{
double i = 5.2;
int j = 3;
show(i);
show(j);
}
При этом используется современное стандартное ключевое слово C11/C17 _Generic
, которое может проверять типы во время компиляции. Макрос выбирает соответствующую функцию для вызова, и она типобезопасна. Вызывающему абоненту не нужно беспокоиться о том, какую функцию «показать» вызывать, и о том, что они передают правильный тип.
Комментарии:
1. Я думаю, что реализация макроса для охвата
GenerateShowValueFunc(double)
иGenerateShowValueFunc(int)
является важной частью задания. Но это может быть только мое чтение.2. В противном случае это решение произвело на меня впечатление функцией, о которой я раньше не знал.
Ответ №2:
Без изменения показанного C-кода (т. Е. Только выполнение макросов), что я считаю обязательным требованием, следующий код имеет требуемый вывод:
#include <stdio.h>
#define showValue_double(input)
showValueFunc_double(#input"=%.4fn" , input)
#define showValue_int(input)
showValueFunc_int(#input"=%dn" , input)
#define GenerateShowValueFunc(type)
void showValueFunc_##type(const char format[], type input)
{
printf(format, input);
}
/* ... macro magic above; */
/* unchangeable code below ... */
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Выход:
i=5.2000
j=3
Обратите внимание, что я создал что-то вроде таблицы поиска для спецификаторов формата для конкретного типа. Т. Е. для каждого типа, который будет поддерживаться, вам нужно добавить макрос #define showValue_ ...
. Это также необходимо для ввода имени переменной в выходные данные.
При этом используется тот факт, что две «строки» объединяются компиляторами C, т. Е. "A""B"
Это то же самое, что "AB"
. Где "A"
находится результат #input
.
Остальное, т. е. требуемое определение функции, очень похоже на пример, приведенный учителем, с использованием ##
оператора.
Обратите внимание, это в том случае, если имя переменной должно быть правильно указано в выходных данных.
Без i =
этого было бы проще и элегантнее использовать сгенерированные функции БЕЗ showValue_double(i);
явных макросов. Т. е. сгенерированные функции составляют 1:1, из чего вызываются main()
. Я думаю, что это может быть то, о чем на самом деле спрашивают. Дайте мне знать, если вам нужна эта версия.
Комментарии:
1. Я сделал что-то похожее на ваше
#define printname(n) printf(#n);
, но использование printf внутри на самом деле не работает…2. Я пробовал это много раз, и это не сработало.
3. Я думаю, что ваш ответ ближе всего к вопросу.
4. Я тоже так думаю (неудивительно…). Но для обучения за пределами задания я рекомендую также изучить другие ответы.