使用c,我试图读取一个文件,其中每个变量由管道字符分隔。我尝试了以下
fscanf(fp, "%s[|], %s[|], \n", str1, str2);
括号内的字符是垂直线:管道符。
它可以在字符\
上方的许多键盘上找到。
传入的字符串不会在管道字符上拆分,整个字符串都在str1
中
我做错了什么,我该如何解决?
答案 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));`
它将获取字符串直到|,而在读取下一个字符串时,起始字符将为|所以条件是假的,所以你必须指定|在阅读下一个字符串之前。