我正在使用fscanf
和fprintf
。
我尝试用\t
分隔每行的字符串,并按如下方式阅读:
fscanf(fp,"%d\t%s\t%s",&t->num,&t->string1,&t->string2);
文件内容:
1[TAB]string1[TAB]some string[NEWLINE]
无法正常阅读。如果我printf("%d %s %s",t->num,t->string1,t->string2)
我得到了:
1 string1 some
我也收到了这个编译警告:
warning: format specifies type 'char *' but the argument has type 'char (*)[15]' [-Wformat]
如何在不使用二进制r / w的情况下解决此问题?
答案 0 :(得分:3)
我猜测"some string"
中的空格是问题所在。使用fscanf()
读取字符串的%s
在第一个空白字符处停止。要包含空格,请使用以下内容:
fscanf(fp, "%d\t%[^\n\t]\t%[^\n\t]", &t->num, &t->string1, &t->string2);
另请参阅a reference page for fscanf()
和/或another StackOverflow thread on reading tab-delimited items in C。
[编辑回应您的编辑:您似乎也对您传入fscanf()
的参数有疑问。您需要发布t->string1
的声明,但看起来string1
是一个字符数组,因此您应该从&
中删除fscanf()
调用...]
答案 1 :(得分:3)
%s
转换规范在第一个空格处停止读取,制表符和空格都计为空格。
如果您想阅读一系列非标签页,可以使用'扫描集'转换说明符:
if (fscanf(fp, "%d\t%[^\t\n]\t%[^\t\n]", &t->num, t->string1, t->string2) != 3)
...oops - format error in input data...
(我很遗憾从字符串参数中省略&
是正确的。)问题已被编辑;我赢了。删除&
是必要的,以避免编译器警告!
这仍然没有达到预期效果。如果第二个字段的开头有空格,则它们将被格式字符串中的\t
吃掉。格式字符串中的任何空格都会占用输入中的任何空白区域(包括换行符)。在输入中没有空格的字符之前,%[^\t]
转换规范才会开始。我还假设您希望您的输入受到换行限制。如果您愿意,可以省略\n
个字符。
请注意,我检查了fscanf()
解释了3个字段。错误检查您的输入非常重要。
如果你真的想要控制,你应该用fgets()
阅读整行,然后使用sscanf()
来解析数据。
关于
fgets()
和sscanf()
;你能扩展一下它将如何给予更多控制吗?
假设输入数据已写入
1234
a string with spaces
another string
分散在多条线上。使用原始fscanf()
,这将是可接受的输入,即使它分布在9行输入上。使用fgets()
,您可以读取一行,然后使用sscanf()
进行分析,您就会知道第一行的格式不正确。然后,您可以决定如何处理它。
此外,由于mafso在comment中调用了我,我们应该通过限制扫描设置匹配的字符串大小来确保没有缓冲区溢出。
if (fscanf(fp, "%d\t%14[^\t\n]\t%14[^\t\n]", &t->num, t->string1, t->string2) != 3)
...oops - format error in input data...
我正在使用有关char (*)[15]
的错误消息来推断14是正确使用的数字。请注意,与printf()
不同,您无法通过*
符号指定尺寸(在scanf()
- 系列中,*
强调分配),因此您必须创建格式正确的尺寸。此外,您指定的大小是终止空字节之前的字符数,因此如果数组大小为15,则您在格式字符串中指定的大小为14,如图所示。