I'm trying to read in 200 lines of text from a text file and store values on each line into a structure. 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.
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.
#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()
:
#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). The format of 1 text line is supposed to be:
[rank][maleName][numMaleNameOccurences][femaleName][numFemaleNameOccurences]
(ex. 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
popNames.year
is uninitialized when you compute the filenamefgets
sscanf()
%s
fields in sscanf()
.i
before parsing file contents into the i
-th entry of the arrays, you will get undefined behavior if the file is unexpectedly largeYour removeCommas()
has undefined behavior because you call strcpy
with overlapping strings. 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:
#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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.