fscanf函数中无法识别管道字符

时间:2014-12-20 03:59:58

标签: c

使用c,我试图读取一个文件,其中每个变量由管道字符分隔。我尝试了以下

fscanf(fp, "%s[|], %s[|], \n", str1, str2);

括号内的字符是垂直线:管道符。 它可以在字符\上方的许多键盘上找到。

传入的字符串不会在管道字符上拆分,整个字符串都在str1中 我做错了什么,我该如何解决?

3 个答案:

答案 0 :(得分:3)

采用scanf格式,%s表示"匹配任何字符序列,不包括空格",所以我的猜测是您的文件不包含任何空格。

要匹配单个 | ,您只需在格式中插入 | ,因为在scanf格式中除了空白和匹配自己。 (包括 [。)但是,每种格式都独立于任何其他格式,因此%s|并不意味着"匹配任何字符串直到 | &#34 ;.这意味着"匹配任何不包括空格的字符串,然后是 | "。

如果要匹配任何不包含 | 的字符串,则需要%[^|]。请注意,与任何其他格式说明符一样,它以开头;没有,它将匹配文字字符串[^|]

scanf和朋友一样,您需要考虑缓冲区溢出。关于始终使用最大宽度有很多建议,但是如果你有一个与Posix 2008兼容的标准库(与任何非常古老的glibc一样),那么你可以使用m限定符来获取scanf为您分配适当大小的内存区域。为了使用它,你需要提供一个指向缓冲区指针的指针的地址,而不是缓冲区指针,你必须记住在你完成时释放()提供的缓冲区指针用它,以避免泄漏记忆。例如,您可能会这样做:

int main() {
  char* str1;
  char* str2;
  // Processing loop
  for (;;) {
    str1 = str2 = NULL; // Be safe
    // This reads the variable before the first | into str1 and the rest
    // of the line into str2. %*c will skip over the newline character.
    int rc = scanf("%m[^|]|%m[^\n]%*c", &str1, &str2);
    if (rc == EOF) break;
    if (rc != 2) {
      // Handle error
      printf("Found %d values\n", rc);
    } else {
      // Do something with the strings
      printf("s1=%s\ns2=%s\n", str1, str2);
    }
    // Free the allocated buffers
    free(str1); free(str2);
  }
  return 0;
}

最后,一些建议:总是检查scanf的返回值(如上所述)。这将告诉你有多少模式匹配;如果它小于模式的数量,你就会知道出了什么问题。

答案 1 :(得分:2)

只有出现 OP希望扫描格式为'\n'的行。
这个答案专为阅读线而设计。

阅读第一行时,最好以fgets()

开头
char buf[4096];
if (fgets(buf, sizeof buf, fp) == NULL) {
  Handle_EOForIOError();
}

然后扫描它。可以使用strtok(),简单代码或sscanf()。使用sscanf(),使用宽度限制和"%n"来测试结束。

char str1[100];
char str2[100];
int n = 0;
sscanf(buf, "%99[^|]|,%99[^|]|, %n", str1, str2, &n);
// n will only have a non-zero if the entire format matched
if (n == 0 || buf[n] != '\0') {
  Handle_scan_failure();
}

为什么fscanf(fp, "%s[|], %s[|], \n", str1, str2);遇到麻烦

OP似乎是混合格式说明符"%[...]""%s"

"%s"将跳过前导空格,然后扫描非空格。不幸的是,它可以继续使用可用空间,最好使用限制:char s1[100]; ... "%99s" ...

[|]"只会计算3 char "[|]"。 Likle OP希望匹配单个|

" \n"与单个空格不匹配,然后与单个'\n'匹配。相反,两个casue scanf()都做同样的事情:跳过任意数量的空格。

答案 2 :(得分:1)

您只需删除[]之前和之后的|

   `fscanf(fp, "%s |, %s |, \n", str1, str2);`

现在内容将存储在str1和str2中。 因为[|]它将作为整体的分隔符。如果文件中存在[|]分隔符,它将读取字符串。 如果输入文件中没有空格,您可以使用

   `fscanf(fp, "%[^|] |, %[^|] \n", str1, str2));`

它将获取字符串直到|,而在读取下一个字符串时,起始字符将为|所以条件是假的,所以你必须指定|在阅读下一个字符串之前。