fprintf() в csv-файл на языке Си с помощью указателя

#c #pointers #struct

Вопрос:

У меня есть структура, определенная следующим образом

 typedef struct{
    int id;
    char* name;
    float percentage;
}student_t;
 

И есть функция, которая должна печатать элемент структуры в этом формате

 "id, name, percentagen"
 

Но функция учитывает void* val_ref //struct ptr, void* fp
Как мне заставить это работать? Функция выглядит следующим образом (заданные параметры не могут быть изменены)

 void printStudentInfo(void* val_ref, void* fp)
{
    if (val_ref != NULL)
    {
        fprintf(fp, "%d,%s,%.2f", val_ref->id, val_ref->name, val_ref->percentage);
    }
}
 

Но я не могу скомпилировать, в нем написано предупреждение: задержка недействительна*
ошибка указателя: запрос элемента «идентификатор» в чем-то, что не является структурой или объединением
ошибка: запрос элемента «имя» в чем-то, что не является структурой или объединением
ошибка: запрос элемента «процент» в чем-то, что не является структурой или объединением

Нужно ли мне приводить тип для параметра val_ref?

Комментарии:

1. Да, вы должны напечатать указатель на пустоту обратно. Или просто измените прототип функции, чтобы student_t* FILE* вместо 2 параметров принимать a и a void* . Почему для начала требуются указатели на пустоту? Является ли это заданной функцией?

2. @LouisCloete да, это заданная функция , я не могу изменять параметры, Но также, когда я делаю типизацию student_t* val_ref , компилятор сказал бы мне, что redeclare as a different kind of symbol and previous defined in function parameter

3. Здесь бессмысленно использовать указатели void, просто используйте соответствующие типы указателей.

4. val_ref->id, val_ref->name, val_ref->percentage -> ((student_t*)val_ref)->id, ((student_t*)val_ref)->name, ((student_t*)val_ref)->percentage

5. Я согласен с @Jabberwocky. В чем был вопрос? Единственный способ, которым указатели на пустоту имеют смысл, — это если они должны быть «универсальными», имея возможность использовать более одного типа структуры и более одного типа дескриптора вывода и выводить универсальную структуру в общий дескриптор вывода.

Ответ №1:

fprintf(fp, "%d,%s,%.2f", val_ref->id, val_ref->name, val_ref->percentage); Здесь вам нужно привести val_ref к типу указателя, которым он на самом деле является: (student_t *)val_ref а затем выбрать элемент структуры, например ((student_t*)val_ref)->id .

Когда у вас есть a void* , ваша программа не знает фактического типа данных, на который вы указываете. Следовательно, незаконно пытаться привлечь участника. При использовании приведения вы явно говорите, что val_ref это указывает на a student_t , и вы знаете, что делаете, когда просите конкретного участника.

Тем не менее, нет необходимости приводить fp , потому что функция fprintf имеет первый аргумент, как FILE * и в ее сигнатуре:

int fprintf(FILE *stream, const char *format, ...);

Таким образом, даже если вы передадите a void * в качестве первого параметра, локальная переменная stream будет определена как a FILE * , и именно с этим работает функция.

Комментарии:

1. Спасибо за ваш ответ, нужно ли мне вводить текст в if заявлении?

2. @AlexHu Нет. Сравнение a void * с NULL хорошо определено.

3. Благодарен за ответ