Почему эта программа не работает? - PullRequest
0 голосов
/ 10 мая 2018

Когда я работал над языком программирования C , я хотел создать небольшую программу для пересмотра этих предыдущих пунктов знаний. И это программа, с которой, похоже, есть некоторые проблемы.

Предполагается, что эта программа собирает информацию с ввода и печатает ее в файле "reg.txt" в формате.

Однако после ввода первой строки и нажатия клавиши ввода программа завершается, но я не могу понять, что с ней не так.

#include <stdio.h>

int main()
{
    FILE *fp;
    struct profile
    {
        char *name;
        char *surname;
        int year;
        int month;
        int day;
    } people[10];
    int temp;
    int i = 0;
    char *line;


    fp = fopen("reg.txt", "a");
    while (fgets(line, 256, stdin)
    {
        sscanf(line, "%s %s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
        ++i;
    }
    temp = i-1;

    for (i = 0; i <= temp; ++i)
        fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);

    fclose(fp);
    return 0;
}

Я принял совет Ed Heal , и я хотел проверить возвращаемое значение 'sscanf'. Что странно, так это то, что программа не доходит до части printf. Я думал, могут быть какие-то проблемы с циклом?

#include <stdio.h>

int main()
{
    FILE *fp;
    void filecopy(FILE *, FILE *);
    struct profile
    {
        char *name;
        char *surname;
        int year;
        int month;
        int day;
    } people[10];
    int temp;
    int i = 0;
    char *line;
    int j;


    fp = fopen("reg.txt", "a");
    while (fgets(line, 256, stdin) != NULL)
    {
        j = sscanf(line, "%s %s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
        ++i;
    }
    temp = i-1;

    //for (i = 0; i <= temp; ++i)
    //  fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);

    printf("%d",j);
    fclose(fp);
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Даже после того, как line выделил память, вы должны получить segfault на sscanf, когда он попытается записать в people[0].name и people[0].surname, потому что эти указатели будут неопределенными.

Вам необходимо выделить память для этих строк, статически или динамически (с помощью malloc).

Печать выписок из журнала также может немного помочь в понимании.

#include <stdio.h>

int main()
{
    FILE *fp;
    typedef struct
    {
        char name[64];
        char surname[64];
        int year;
        int month;
        int day;
    } profile;
    profile people[10];

    int temp;
    int i = 0;
    char line[512];

    printf("Starting profile line parser...\n");
    printf("Please enter up to 10 people in the format: (name surname year/month/day)\n");
    printf("Enter EOF to exit. (Linux: CTRL+D     Windows CTRL+Z)\n");
    fp = fopen("reg.txt", "a");
    while (gets(line) != NULL)
    {
        sscanf(line, "%63s %63s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
        ++i;
    }
    printf("Processed %d lines.\n", i);
    temp = i-1;
    for (i = 0; i <= temp; ++i)
    {
        fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
    }

    fclose(fp);
    printf("Done with profile line parser...\n");
    return 0;
}

РЕДАКТИРОВАТЬ: Потому что get устарела, вот альтернатива fgets. Дальнейшее чтение по get: Почему функция gets настолько опасна, что ее не следует использовать?

EDIT: также добавлена ​​защита переполнения буфера в chux. Дальнейшее чтение о предотвращении переполнения буфера с помощью scanf: Считать не более чем размер строки с помощью функции scanf ()

#include <stdio.h>

int main()
{
    FILE *fp;
    typedef struct
    {
        char name[64];
        char surname[64];
        int year;
        int month;
        int day;
    } profile;
    profile people[10];

    int temp;
    int i = 0;
    char line[512];

    printf("Starting profile line parser...\n");
    printf("Please enter up to 10 people in the format: (name surname year/month/day)\n");
    printf("Enter EOF to exit. (Linux: CTRL+D     Windows CTRL+Z)\n");
    fp = fopen("reg.txt", "a");
    while (fgets(line, 512, stdin) != NULL)
    {
        sscanf(line, "%63s %63s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
        ++i;
    }
    printf("Processed %d lines.\n", i);
    temp = i-1;
    for (i = 0; i <= temp; ++i)
    {
        fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
    }
    printf("Done with profile line parser...\n");
    fclose(fp);
    return 0;
}
0 голосов
/ 10 мая 2018

Вам необходимо выделить память перед использованием line с gets

#include <stdio.h>

int main()
{
    FILE *fp;
    struct profile
    {
        char *name;
        char *surname;
        int year;
        int month;
        int day;
    };
    struct profile people[10];
    int temp;
    int i = 0;
    char line[256]; //you can also do dynamic allocation by using malloc

    fp = fopen("reg.txt", "a");
   // while (gets(line) != NULL) //use fgets instead gets
    while( fgets(line, 256, stdin) ) //specify required buffer len
    {
        sscanf(line, "%s %s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
        ++i;
    }
    temp = i-1;

    for (i = 0; i <= temp; ++i)
        fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);

    fclose(fp);
    return 0;
}
...