简体   繁体   English

fscanf 分隔符 - 接受空格、字符限制

[英]fscanf delimiters - accepting spaces, character limit

I'm struggling with importing lines from a text file into a C program.我正在努力将文本文件中的行导入 C 程序。 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|%14s|%4s|%10s\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:虽然可以读取文件,但我得到的是我的 output:


1024 Larry  ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry  ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry  ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry  ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
1024 Larry  ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠

Repeating forever.永远重复。 Can anyone offer insight for where I'm going wrong?任何人都可以提供有关我要去哪里的见解吗?

"%s" insufficient to read a name "%s"不足以读取名称

"%14s" will only read and save "Larry" of "Larry Normal" . "%14s"只会读取和保存"Larry" "Larry Normal" Instead use "14s[^|]" to read to a "|"而是使用"14s[^|]"来读取"|" . .

Code checks against only 1 undesired return value仅针对 1 个不需要的返回值进行代码检查

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.由于fscanf()可能返回EOF4以外的值,而不是检查不需要的返回值之一,而是检查所需的值。

 // while (fscanf(patientFile, "%d|%14s|%4s|%10s\n", ...) != EOF)
 while (fscanf(patientFile, "%d|%14s|%4s|%10s\n", ...) == 4)

Advanced: Better end-of-line detection via fgets()高级:通过fgets()进行更好的行尾检测

"%d" , "%s" ignore and consume leading white-space including '\n' . "%d""%s"忽略并消耗前导空格,包括'\n' Better to read a line into a buffer and then parse.最好将一行读入缓冲区然后解析。

// "%d|%14s|%4s|%10s\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|%14[^|]|%4[^|]|%10[^\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 "%10[^0-9#*]" instead of "%10[^\n]" for the phone number.也许还开始检查可接受的文本,如"%10[^0-9#*]"而不是电话号码的"%10[^\n]" See also longest possible worldwide phone number .另请参阅可能的最长全球电话号码

Try this pattern "%d|%[^|]|%[^|]|%s\n" instead.请尝试使用此模式"%d|%[^|]|%[^|]|%s\n" [^|] means read all characters till the | [^|]表示读取所有字符直到| . . %s will not work cuz | %s不会工作因为| is not white-space.不是空白。

Ref: https://cplusplus.com/reference/cstdio/fscanf/参考: https://cplusplus.com/reference/cstdio/fscanf/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM