为什么fscanf在没有明确告知的情况下改变结构的值?

时间:2014-11-26 11:36:21

标签: c file-io data-structures scanf

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

调试显示此行为是由while fscanf()循环引起的。虽然更改字符串输入的大小会阻止更改数字,但第一行PMs.Party[0]上的字符串仍然从= 人工更改为 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中每个变量的大小增加1,则代码运行时没有任何问题。我认为这是某种溢出?

编辑2:特别是如果EndYr [13] 而不是 [12] ,问题就会消除。

2 个答案:

答案 0 :(得分:2)

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

这就是为什么你的代码在Party字段使用13个字符数组时有效。

你应该做什么

指定scanf格式说明符中Party字段的最大长度。例如,如果为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])

答案 1 :(得分:0)

您正在从文件中读取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];
};