我已经开始编写一个程序,用于读取和存储团队信息并将其存储在结构中,重新排序并打印结果。
首先,我正在尝试阅读团队名称并将其存储在结构中的成员中,然后阅读团队成绩并将其存储在其他成员中。
但是,只要我调试文件,它就会崩溃。它甚至没有正确启动。我收到此错误
PA2.exe中0xFEFEFEFE处的未处理异常:0xC0000005访问 违规执行地点0xFEFEFEFE。
我已经回溯到足以弄清楚它是在while循环中的某个地方但却无法弄清楚它有什么问题。
我正在使用visual studio 2012,当我构建它时我没有错误。
#include "stdafx.h"
#include "string.h"
#include <stdio.h>
struct team
{
char name[20];
int no_games;
int points;
int goals_scored;
int goals_let;
};
int main(void)
{
FILE *input2a;
FILE *input2b;
int error1;
int error2;
int i;
char team1_name[20];
char team2_name[20];
int team1_goals;
int team2_goals;
struct team teamlist[20];
error1 = fopen_s(&input2a, "C:\\Users\\New PC\\Desktop\\input2a.dat", "r");
i = 0;
while (i < 20)
{
i ++;
fscanf_s(input2a, "%s", teamlist[i].name);
}
error2 = fopen_s(&input2b, "C:\\Users\\New PC\\Desktop\\input2b.dat", "r");
while (fscanf_s(input2b, "%s %d %s %d", team1_name, &team1_goals, team2_name, &team2_goals) !=EOF)
{
if (team1_goals < 0)
{
printf("Team %s has negative goals - Invalid entry\n", team1_name);
}
else if (team2_goals < 0)
{
printf("Team %s has negative goals - Invalid entry\n", team2_name);
}
else
{
}
}
return 0;
}
答案 0 :(得分:5)
从仅查看while循环:你写入内存越界。
struct team teamlist[20];
而在此期间:
i = 0;
while (i < 20)
{
i ++;
fscanf_s(input2a, "%s", teamlist[i].name);
}
所以你在i=19
时输入while并将其增加到20
,这使得它超出了数组的范围。
答案 1 :(得分:3)
问题在这里(见我的评论):
i = 0;
while (i < 20)
{
i ++; // was 19, become 20, but maximal allowed value is 19
fscanf_s(input2a, "%s", teamlist[i].name);
}
此问题的名称是ABW(数组边界写入)。这意味着,您的程序在数组外部写入(它发生在i==19
时,因此循环i < 20
的条件得到满足,但是在它之后你会增加它:i++
)。要修复它,你只需要交换这个循环体的两行:
{
fscanf_s(input2a, "%s", teamlist[i].name);
i++;
}
更好更简单的是在这里使用for
循环:
for (i = 0; i < 20; i++)
fscanf_s(input2a, "%s", teamlist[i].name);
最后修复:现在仍然可能出现ABW错误。原因很简单:teamlist[i].name
的大小为20.因此,如果输入文件包含长行,则程序将在此数组外写入。要解决此问题,您可以通过这种方式扩展"%s
(我们在这里&#34; 19&#34;而不是&#34; 20&#34;因为最后一个字符是'\0'
):
for (i = 0; i < 20; i++)
fscanf_s(input2a, "%19s", teamlist[i].name);
关于fscanf_s()
还有一件事:这个函数应该返回成功匹配和分配的输入项的数量。因此,在第二个循环中,最好检查它是否返回4
。
<强>更新强>
如果没有任何反应,请打开documentation:
与scanf和wscanf不同,scanf_s和wscanf_s需要缓冲区大小 要为c,C,s,S或string类型的所有输入参数指定 包含在[]中的控件集。缓冲区大小以字符为单位 在指针指向后立即作为附加参数传递 缓冲区或变量。例如,如果您正在读取字符串,则 该字符串的缓冲区大小传递如下:
char s[10];
scanf_s("%9s", s, _countof(s)); // buffer size is 10, width specification is 9
所以在你的情况下,第一个循环应该以这种方式纠正:
for (i = 0; i < 20; i++)
fscanf_s(input2a, "%19s", teamlist[i].name, _countof(teamlist[i].name));
你需要在第二个循环中为fscanf_s
的下一次调用提供相同的修复,因为该调用中有两个"%s"
。