I'm struggling with importing lines from a text file into a C program. Below is the text I'm trying to import:
1000|Larry Normal|CELL|3048005191
1001|Shelly Nopers|CELL|3048005191
1002|Shelly Schnats|HOME|3649155831
1003|Terry Crews|HOME|3932281123
Delimited by | and with spaces in names.
Here's the code I'm using below:
FILE* patientFile = NULL;
int patientNum;
char patientName[15];
char phoneDescription[5];
char phoneNumber[11];
patientFile = fopen("patientData.txt", "r");
if (patientFile != NULL)
{
while (fscanf(patientFile, "%d|s|%4s|s\n", &patientNum, patientName, phoneDescription, phoneNumber ) != EOF)
{
printf("%d %s %s %s\n", patientNum, patientName, phoneDescription, phoneNumber);
}
fclose(patientFile);
}
else
{
printf("Failed to open patients file\n");
}
While the file can be read, I'm getting this as my output:
1024 Larry ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
Repeating forever. Can anyone offer insight for where I'm going wrong?
CodePudding user response:
"%s"
insufficient to read a name
"s"
will only read and save "Larry"
of "Larry Normal"
. Instead use "14s[^|]"
to read to a "|"
.
Code checks against only 1 undesired return value
As fscanf()
may return values other than EOF
and 4
, rather than check against one of the undesired return values, check against the desired one.
// while (fscanf(patientFile, "%d|s|%4s|s\n", ...) != EOF)
while (fscanf(patientFile, "%d|s|%4s|s\n", ...) == 4)
Advanced: Better end-of-line detection via fgets()
"%d"
, "%s"
ignore and consume leading white-space including '\n'
. Better to read a line into a buffer and then parse.
// "%d|s|%4s|s\n"
#define LINE_SIZE (11 1 14 1 4 1 10 1 1)
char buf[LINE_SIZE * 2]; // Do not be stingy on potential line sizes.
while (fgets(buf, sizeof buf, patientFile) &&
sscanf(buf, "%d|[^|]|%4[^|]|[^\n]",
&patientNum, patientName, phoneDescription, phoneNumber) == 4) {
printf("%d %s %s %s\n", patientNum, patientName, phoneDescription, phoneNumber);
}
Robust code would also check for trailing text after the phone number, excessive long lines, etc.
Perhaps also start checking for acceptable text like "[^0-9#*]"
instead of "[^\n]"
for the phone number. See also longest possible worldwide phone number.
CodePudding user response:
Try this pattern "%d|%[^|]|%[^|]|%s\n"
instead. [^|]
means read all characters till the |
. %s
will not work cuz |
is not white-space.