将结构保存到文本文件并将其下载回stdout的C问题

时间:2019-04-17 11:48:41

标签: c

嘿,我的代码项目遇到问题,我尝试创建一个与奥林匹克奖牌保持一致的项目。我在创建包含结构并由用户命名的文本文件时遇到问题。我也有下载结构的问题。

问题:我遇到一个问题,即要创建一个由用户命名的包含结构的文本文件,然后将其下载回stdout。我不知道如何修复我的功能才能正确执行此操作。现在我的函数save_file甚至无法生成该文件。

输入以下内容的示例:

加拿大

美国

美国2 1 1

M加拿大0 0 1

美国1 3 1

M美国-1 0 0

L

W枚奖牌

Q

我已经这样定义了我的结构:

typedef struct Olympia
    {
        char* country;
        int gold;
        int silver;
        int bronze;
    }Olympia;

然后我有一个添加国家/地区的功能

int add_country(struct Olympia* data, char* str, int i)
{
    if (str[0] == '\0') //checking that input is correct
    {
        printf("Error! Try again!\n");
    }

    else
    {
        data[i].country = malloc(strlen(str) + 2);  //allocating memory for country name
        strcpy(data[i].country, str);   //adding country to database
        data[i].gold = 0;   //setting medals to zero
        data[i].silver = 0;
        data[i].bronze = 0;
        i++;
    }
    return i;
}

接下来,我将奖牌添加到每个国家/地区

int update_medals(struct Olympia* data, char* str, int add_gold, int add_silver, int add_bronze, int i)
{
    int a = 0;
    int b = 0;

    if (str[0] == '\0') //checking that input is correct
    {
        printf("Error! Try again!");
    }

    else
    {
        while (a < i)
        {
            if (strcmp(data[a].country, str) == 0)  //adding medals to right country
            {
                data[a].gold = data[a].gold + add_gold;
                data[a].silver = data[a].silver + add_silver;
                data[a].bronze = data[a].bronze + add_bronze;
                b++;
            }
            a++;
        }

        if (b == 0) //and if the country didn't participate to the olympics
        {
            printf("This country isn't in the Olympics! Try Again!\n");
        }
    }
}

接下来有打印功能

int print_data(struct Olympia* data, int i)
{
    for (int a = 0; a < i; a++)
    {
        printf("%s %d %d %d\n", data[a].country, data[a].gold, data[a].silver, data[a].bronze);
    }
}

然后有两个功能不起作用。我该怎么办?

Olympia *save_file(Olympia* data, const char* filename, int i)
{
    if (strlen(filename) > 100)
    {
        printf("Filename is too long: Maxium lenght for filename is 100 characters");
        return data;
    }

    char name[100];
    int ret = sscanf(filename, "W %s", name);
    if (ret != 1)
    {
        printf("Error! Try again!");
        return data;
    }


    FILE* file = fopen(name, "w");
    if (!file)
    {
        printf("Error saving file! Try again");
        return data;
    }

    int a = 0;
    while (data[a].country[0] != 0)
    {
        fprintf(file, "%s %d %d %d\n", data[a].country, data[a].gold, data[a].silver, data[a].bronze);
        a++;
    }

    fclose(file);
    return 0;
}

int load_file(struct Olympia* data, char* filename, int i)
{
    int a = 0;

    FILE* file = fopen(filename, "r");
    if (!file)
    {
        printf("Error opening file! Try again");
    }

    struct Olympia* arr = malloc(sizeof(Olympia));

    while (fscanf(file, "%s %d %d %d", data[a].country, data[a].gold, data[a].silver, data[a].bronze))
    {
        i++;
        a++;
        arr = realloc(arr, sizeof(Olympia) * (i + 2));
    }
    arr[a].country[0] = 0;
    fclose(file);
    return arr;
}

主要功能

int main(void)
{
    char command;
    int gold = 0;
    int silver = 0;
    int bronze = 0;
    int i = 0;

    char* line = (char*)malloc((100) * sizeof(char)); //allocating memory for one stdin line
    char* countryname = (char*)malloc(20 * sizeof(char)); // allocating memory for country name
    char* filename = (char*)malloc(100 * sizeof(char));
    struct Olympia* countrydata = malloc(sizeof(struct Olympia) * 1); //allocating memory for structure

    line = fgets(line, 100, stdin);

    while(1)
    {
        sscanf(line, "%c %s %d %d %d", &command, countryname, &gold, &silver, &bronze);

        switch (command)
        {
            case 'A':

                i = add_country(countrydata, countryname, i);
                countrydata = realloc(countrydata, sizeof(struct Olympia) * (i + 1));
                break;

            case 'M':

                update_medals(countrydata, countryname, gold, silver, bronze, i);
                break;

            case 'L':

                print_data(countrydata, i);
                break;

            case 'W':

                save_file(countrydata, filename, i);
                break;

            case 'O':

                i = load_file(countrydata,filename, i);
                break;

            case 'Q':

                free(line);
                free(countryname);
                free(countrydata);
                return(EXIT_SUCCESS);
        }

        line = fgets(line, 100, stdin);

        if (line == NULL)
        {
            free(line);
            free(countryname);
            free(countrydata);
            return(EXIT_SUCCESS);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您在未设置save_file(countrydata, filename, i);的情况下呼叫filename。更改为save_file(countrydata, line, i);,因为无论出于何种原因,您都希望命令字符W位于名称之前。

然后save_file()中的条件while (data[a].country[0] != 0)不可用,因为最后一个元素之后的数据元素未初始化。请改用while (a < i)