C Введите значение из .txt в структуру

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

Я НЕ могу распечатать значения, поэтому я могу проверить, правильно ли они отсканированы, прежде чем продолжить работу в программе.

У меня разные значения в структуре:

struct knyga
{
    char vardas[10];
    char pavadinimas[50];
    int metai;
    double kaina;
};

И это моя функция чтения:

void Skaitymas(struct knyga arr_knyga[]){
FILE *fp;

fp = fopen("duomenys.txt", "r");
int skaicius;
int txt;
txt = fgetc(fp);

while((txt = fgetc(fp)) != EOF){
    if (txt == '\n') skaicius++;
        txt = fgetc(fp);
}
printf("%d", skaicius);

fp = fopen("duomenys.txt", "r");


for(int i = 0; i < skaicius; i++){
    fscanf(fp, "%s %s %d %lf", arr_knyga[i].vardas, arr_knyga[i].pavadinimas, &arr_knyga[i].metai, &arr_knyga[i].kaina);
 }
fclose(fp);

}

Обновлено:

Это содержимое моего текстового файла:

Onute Knyga 1999 12.12
Petras Knygute 2001 9.99

Обновлено еще раз:

Моя основная функция:

int main() {
    
    
    struct knyga arr_knyga[10];
    
    Skaitymas(arr_knyga);
    
    return 0;
}

Используйте int txt; while((txt = fgetc(fp)) != EOF) { if (txt == '\n') skaicius++; } Большинство функций библиотеки C используют int, а не char для символа.

Weather Vane 20.12.2020 15:44

@WeatherVane спасибо за подсказку, но после того, как я попытаюсь напечатать «skaicius», который должен быть равен 2, потому что это количество строк, которые у меня есть в моем текстовом файле, вместо этого он дает 1.

Upsice 20.12.2020 15:51

Если вы хотите проанализировать значения из fp, вы должны использовать fscanf вместо scanf. Проверьте код возврата fscanf (см. документацию) и используйте feof и ferror впоследствии, чтобы узнать, достигнут ли конец файла или произошла ошибка. Вам не нужно сначала считать строки.

Bodo 20.12.2020 15:52

Пожалуйста, покажите содержимое входного файла в вашем вопросе. Если вы изменили свою программу, как было предложено в комментарии, пожалуйста, отредактируйте свой вопрос и добавьте измененный код и соответствующий вывод.

Bodo 20.12.2020 15:53

Добавлено содержимое файла .txt и отредактирована функция void по рекомендации. @Бодо

Upsice 20.12.2020 15:59

Последняя строка входного файла заканчивается на '\n'? Пожалуйста, покажите вывод od -c duomenys.txt

Bodo 20.12.2020 16:05

Покажите, как вы вызываете Skaitymas и как определяется массив. Функция Skaitymas не знает размер массива и не может проверить возможный доступ за его пределы.

Bodo 20.12.2020 16:07

@Bodo Входной файл точно такой, как я его вставил. Добавил и мою основную функцию. Я предполагаю, что struct knyga arr_knyga[10]; будет иметь максимум 11 строк.

Upsice 20.12.2020 16:11

@Upsice Проблема в том, что «точно так, как вы ее вставили» не говорит, заканчивается ли последняя строка символом новой строки или нет. Вот почему я предложил команду, которая прояснила бы это. Если вы объявляете массив как arr_knyga[10], ваша функция Skaitymas не должна пытаться сохранить более 10 записей данных.

Bodo 20.12.2020 16:22
Почему в Python есть оператор &quot;pass&quot;?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
10
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ты слишком часто звонишь txt = fgetc(fp);. Два вхождения этой строки должны быть удалены.

Особенно в цикле у вас есть один вызов fgetc, который проверяется на '\n', и второй вызов, который не проверяется, поэтому существует вероятность 50%/50%, что '\n' не будет засчитан.

Вы забыли инициализировать переменную счетчика.

С этой версией подсчет будет правильным:

void Skaitymas(struct knyga arr_knyga[]){
    FILE *fp;

    fp = fopen("duomenys.txt", "r");
    int skaicius = 0;
    int txt;

    while((txt = fgetc(fp)) != EOF){
        if (txt == '\n') skaicius++;
    }
    printf("%d", skaicius);

    fclose(fp);
}

Но было бы лучше опустить подсчет строк и определить условие конца файла в цикле fscanf.

void Skaitymas(struct knyga arr_knyga[]){
    FILE *fp;

    fp = fopen("duomenys.txt", "r");
    int skaicius = 0;
    int rc;

    while(1)
    {
        rc = fscanf(fp, "%s %s %d %lf", arr_knyga[skaicius].vardas, arr_knyga[skaicius].pavadinimas, &arr_knyga[skaicius].metai, &arr_knyga[skaicius].kaina);
        if (rc == 4)
        {
           skaicius++;
        }
        else
        {
            break;
        }
    }
    if (!feof(fp))
    {
        fprintf(stderr, "error reading file or wrong data after line %d\n", skaicius);
    }
    else
    {
        printf("%d", skaicius);
    }
    fclose(fp);
}

Другие вопросы по теме