[英]2nd fgets returns segmentation fault after reading 192/200 lines of text from file
I'm trying to read in 200 lines of text from a text file and store values on each line into a structure.我正在尝试从文本文件中读取 200 行文本,并将每行的值存储到一个结构中。 This is only a snippet of the part that's not working.
这只是不工作部分的一小部分。 In the entire code, I ask the user if they wish to read a different text file.
在整个代码中,我询问用户是否希望读取不同的文本文件。 It works perfectly the first time but when the user says yes to reading a different file, it only reads in and stores the first 192 lines of the 200 lines of the text file, then returns a segfault.
它第一次完美运行,但是当用户说是读取不同的文件时,它只读取并存储文本文件的 200 行中的前 192 行,然后返回一个段错误。
I tried printing out random letters in various parts throughout the code to determine which line returned the segfault and (from what I've found), it's the while condition with gets inside and I can't figure out why it's giving a segfault.我尝试在整个代码的各个部分打印出随机字母,以确定哪一行返回了段错误,并且(根据我发现的内容),这是进入内部的 while 条件,我无法弄清楚为什么它会给出段错误。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[]) {
FILE *f1;
int i = 0;
struct pNames popNames;
char fileName[20];
char maleSNumber[20];
char femaleSNumber[20];
char string[200];
fileName[0] = '\0';
sprintf(fileName, "%d", popNames.year);
strcat(fileName, "Names.txt");
if ((f1 = fopen(fileName, "r")) != NULL) {
while (fgets(string, 200, f1) != NULL) {
sscanf(string, "%d %s %s %s %s",
&popNames.rank[i],
popNames.maleName[i], maleSNumber,
popNames.femaleName[i], femaleSNumber);
printf("%d %s %s %s %s\n",
popNames.rank[i],
popNames.maleName[i], maleSNumber,
popNames.femaleName[i], femaleSNumber);
removeCommas(maleSNumber);
removeCommas(femaleSNumber);
popNames.maleNumber[i] = atoi(maleSNumber);
popNames.femaleNumber[i] = atoi(femaleSNumber);
i++;
}
} else {
printf("Cannot open %s\n", fileName);
return (-1);
}
}
Struct Definition:结构定义:
#define MAXLENGTH 20
#define ROWS 200
/* Struct definitions */
struct pNames {
int year;
int rank[ROWS];
char maleName[ROWS][MAXLENGTH];
int maleNumber[ROWS];
char femaleName[ROWS][MAXLENGTH];
int femaleNumber[ROWS];
};
The definition for removeCommas()
: removeCommas()
的定义:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int removeCommas(char *num) {
int i;
int newNum = 0;
char *pointer;
pointer = strchr(num, ',');
while (pointer != NULL) {
i = (int)(pointer - num);
strcpy(&num[i], &num[i + 1]);
newNum += 1;
pointer = strchr(num, ',');
}
return (newNum);
}
It's supposed to read, store parts of each line, and print out all 200 lines of the text file but it's only working for the first 192 lines (the second time you use it, when the user asks to change text files).它应该读取、存储每行的部分内容并打印出文本文件的所有 200 行,但它仅适用于前 192 行(第二次使用它时,当用户要求更改文本文件时)。 The format of 1 text line is supposed to be:
1个文本行的格式应该是:
[rank][maleName][numMaleNameOccurences][femaleName][numFemaleNameOccurences]
(ex. 1 John 89,950 Mary 91,668
) (例如
1 John 89,950 Mary 91,668
)
I understand you only posted fragments of your code, but here are some visible problems:我了解您只发布了代码片段,但这里有一些明显的问题:
snprintf
instead of sprintf
and strcat
snprintf
而不是sprintf
和strcat
popNames.year
is uninitialized when you compute the filenamepopNames.year
未初始化fgets
fgets
sscanf()
sscanf()
的返回值%s
fields in sscanf()
.sscanf()
中%s
字段的最大字符数。i
before parsing file contents into the i
-th entry of the arrays, you will get undefined behavior if the file is unexpectedly largei
个条目之前测试i
的值,如果文件异常大,您将获得未定义的行为Your removeCommas()
has undefined behavior because you call strcpy
with overlapping strings.您的
removeCommas()
具有未定义的行为,因为您使用重叠字符串调用strcpy
。 It is unlikely to be the cause of your segfault, but here is a simplified and corrected version:这不太可能是您的段错误的原因,但这里有一个简化和更正的版本:
int removeCommas(char *num) {
int newNum = 0;
char *p = num;
while ((*num = *p++) != '\0') {
if (*num != ',')
num++;
else
newNum++;
}
return newNum;
}
Here is a modified version of the main()
function:这是
main()
function 的修改版本:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *f1;
int i;
struct pNames popNames;
char fileName[20];
char maleSNumber[20];
char femaleSNumber[20];
char string[200];
snprintf(fileName, sizeof fileName, "%dNames.txt", popNames.year);
if ((f1 = fopen(fileName, "r")) == NULL) {
printf("Cannot open %s\n", fileName);
return -1;
}
i = 0;
while (i < 200 && fgets(string, sizeof string, f1) != NULL) {
if (sscanf(string, "%d %19s %19s %19s %19s",
&popNames.rank[i],
popNames.maleName[i], maleSNumber,
popNames.femaleName[i], femaleSNumber) != 5) {
printf("invalid input: %s", string);
continue;
}
printf("%d %s %s %s %s\n",
popNames.rank[i],
popNames.maleName[i], maleSNumber,
popNames.femaleName[i], femaleSNumber);
removeCommas(maleSNumber);
removeCommas(femaleSNumber);
popNames.maleNumber[i] = atoi(maleSNumber);
popNames.femaleNumber[i] = atoi(femaleSNumber);
i++;
}
fclose(f1);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.