【问题标题】:Why is fscanf changing values of structure without explicitly being told to?为什么 fscanf 在没有明确告知的情况下更改结构的值?
【发布时间】:2015-01-24 17:20:09
【问题描述】:

我正在尝试将文本文件读入 c 中的结构,但在我的 fscanf() 循环的最后一次迭代中,它更改了存储在结构的第一部分和第二部分中的数字和文本。

调试显示此行为是由while fscanf() 循环引起的。尽管更改输入字符串的大小阻止了数字的更改,但第一行 PMs.Party[0] 上的字符串仍然从 = Labour 更改为 r。这是我的代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>

void PartyPwr( int Runs, int Time[12], char Prty[12][15]);

struct Data
{
    char *Name[12][15];
    int StrtMnth[12];
    int StrtYr[12];
    int EndMnth[12];
    int EndYr[12];
    char Party[12][15]; // if this is 13 20 it runs without numbers changing.
    int TimePwr[12];
};

int main(void)
{
    int Max=0;
    int i=0;
    FILE *PriMins;
    struct Data PMs;
    if ((PriMins=fopen("PM.txt", "r")) == NULL)
    {
        printf("Error: PM.txt cannot be read.");
        system("pause");
        return(1);
    }
    while(fscanf(PriMins, "%s %d %d %d %d %s", &PMs.Name[Max], &PMs.StrtMnth[Max], &PMs.StrtYr[Max], &PMs.EndMnth[Max], &PMs.EndYr[Max], &PMs.Party[Max]) > 0)
    {
        PMs.TimePwr[Max]=((PMs.EndMnth[Max] +(PMs.EndYr[Max]*12)) - (PMs.StrtMnth[Max] + (PMs.StrtYr[Max]*12)));
        printf("%s %d Total term %d\n",PMs.Name[Max], PMs.EndMnth[Max],PMs.TimePwr[Max]);
        printf("Max val, %d bug check %d, %d, Party %s\n",Max, PMs.TimePwr[0], PMs.TimePwr[1], PMs.Party[0]);
        Max++;
    }
    //PartyPwr(Max, PMs.TimePwr, PMs.Party);
    //printf("%d, %d", PMs.TimePwr[0], PMs.TimePwr[1]);
    fclose(PriMins);
    system("pause");
    return(0);
}

void PartyPwr( int Runs , int Time[12], char Prty[12][15])
    int i=0;
    int LabPwr=0;
    int ConPwr=0;
    for (i=0;i<Runs;i++)
    {
        printf("%s\n", Prty[i]);
        if (strcmp(Prty[i],"Labour")==0)
        {
            LabPwr=(LabPwr+Time[i]);
        }
        if (strcmp(Prty[i],"Conservative")==0)
        {
            ConPwr=(ConPwr+Time[i]);
        }
        if ((strcmp(Prty[i],"Conservative")!=0) && (strcmp(Prty[i],"Labour")!=0))
        {
            printf("An invalid party was present in the list.");
        }

    }
    printf ("Total Labour time in power: %d\nTotal Conservative time in power: %d\n", LabPwr, ConPwr);
}

这是程序的文本文件。

Attlee        7   1945  10  1951 Labour
Churchill    11   1951   5  1955 Conservative
Eden          6   1955  12  1956 Conservative
Macmillan     1   1957  10  1963 Conservative
Douglas-Home 11   1963  10  1964 Conservative
Wilson       11   1964   5  1970 Labour
Heath         6   1970   2  1974 Conservative
Wilson        3   1974   3  1976 Labour
Callaghan     4   1976   4  1979 Labour
Thatcher      5   1979  11  1990 Conservative
Major        12   1990   4  1997 Conservative
Blair         5   1997   6  2007 Labour
Brown         6   2007   5  2010 Labour

编辑:我刚刚发现如果 Data 中每个变量的大小都增加一,代码运行时没有任何问题。我认为这是某种溢出?

编辑 2:特别是如果 EndYr[13] 而不是 [12] 问题就解决了。

【问题讨论】:

  • 你真的想要char *Name[12][15];吗?或者应该是char Name[12][15];
  • 好点实际上我认为这是我要动态分配长度时留下的。
  • 如果我将所有变量的大小增加 1,则代码运行良好。所以我在某种意义上已经修复了它,但不知道为什么。
  • 您的文本文件似乎有 13 行,但您的所有数组只有 12 个元素。这很像溢出。
  • 我认为您的 edit2 不应该工作。您应该增加所有这些

标签: c file-io data-structures scanf


【解决方案1】:

单词Conservative 是 12 个字符,但您必须考虑每个 C 字符串末尾的空字符 '\0'。

这就是为什么当您将 13 个字符数组用于 Party 字段时您的代码可以正常工作的原因。

你应该做什么

在 scanf 格式说明符中指定 Party 字段的最大长度。例如,如果您为派对字段保留 12 个字符数组:

fscanf(PriMins, "%s %d %d %d %d %11s", &PMs.Name[Max], &PMs.StrtMnth[Max], &PMs.StrtYr[Max], &PMs.EndMnth[Max], &PMs.EndYr[Max], &PMs.Party[Max])

【讨论】:

    【解决方案2】:

    您正在从文件中读取 13 条记录,并且只有空间可以存储其中的 12 条,因为所有数据项的大小均为 12。如果将大小增加 1,则有足够的空间容纳所有 13 条记录

    struct Data
    {
       char Name[13][15];
       int StrtMnth[13];
       int StrtYr[13];
       int EndMnth[13];
       int EndYr[13];
       char Party[13][15]; 
       int TimePwr[13];
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-07
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多