我正在读一个.txt文件。我正在使用fscanf来获取格式化的数据。 我遇到问题的那条线是:
result = fscanf(fp, "%s", ap->name);
这是好的,直到我有一个空格的名字,例如:St Ives 所以我用这个来读取空白区域:
result = fscanf(fp, "%[^\n]s", ap->name);
然而,当我尝试读取第一个名字(没有空白区域)时,它只是不起作用并且弄乱了其他的fscanf。
但我使用[^ \ n]它在我正在使用的不同文件中正常工作。不确定发生了什么。
如果我在fscanf的位置使用fgets,我会在变量中得到“\ n”。
编辑//
好的,如果我使用:
result = fscanf(fp, "%s", ap->name);
result = fscanf(fp, "%[^\n]s", ap->name);
这允许我读入没有空格的字符串。但是当我得到一个带有空格的“名字”时,它就不起作用了。
答案 0 :(得分:12)
这有一个问题:
result = fscanf(fp, "%[^\n]s", ap->name);
您的格式说明符末尾有一个额外的s
。整个格式说明符应该只是%[^\n]
,它表示“读取一个字符串,该字符串由不是换行符的字符组成”。额外的s
不是格式说明符的一部分,因此它被解释为文字:“从输入中读取下一个字符;如果它是”s“,则继续,否则失败。”
额外的s
实际上并没有伤害到你。您确切知道输入的下一个字符:换行符。它不匹配,输入处理在那里停止,但它并不重要,因为它是格式说明符的结尾。但是,如果你在同一格式字符串之后有其他格式说明符,这会导致问题。
真正的问题是你没有使用换行符:你只是读取到换行符的所有字符,而不是换行符本身。要解决这个问题,你应该这样做:
result = fscanf(fp, "%[^\n]%*c", ap->name);
%*c
说明符表示要读取字符(c
),但不要将其分配给任何变量(*
)。如果省略了*
,则必须传递fscanf()
另一个包含指向字符(char*
)的指针的参数,然后它将存储它所读取的结果字符。
您也可以使用%[^\n]\n
,但也可以在换行符之后的任何空格中读取,这可能不是您想要的。当fscanf
在其格式说明符(空格,换行符或制表符)中找到空格时,它会消耗尽可能多的空格(即您可以认为它消耗了与正则表达式匹配的最长字符串{{1} })。
最后,您还应指定最大长度以避免缓冲区溢出。您可以通过将缓冲区长度放在[ \t\n]*
和%
之间来实现。例如,如果[
是256个字符的缓冲区,则应该执行以下操作:
ap->name
这适用于静态分配的数组;遗憾的是,如果数组在运行时具有动态大小,那么将缓冲区大小传递给result = fscanf(fp, "%255[^\n]%*c", ap->name);
并不容易。您必须使用fscanf
创建格式字符串,例如:
sprintf
答案 1 :(得分:2)
Jumm写道:
如果我在fscanf的位置使用fgets,我会在变量中得到“\ n”。
这是一个更容易解决的问题,所以请继续使用:
fgets( ap->name, MAX, fp ) ;
nlptr = strrchr ( ap->name, '\n' ) ;
if( nlptr != 0 )
{
*nlptr = '\0' ;
}
答案 2 :(得分:0)
我不确定你的意思[^ \ n]是否可以起作用。 []是一个修饰符,表示“接受一个字符,除了该块内的任何字符”。 ^
反转条件。使用fscanf的%s仅在读取分隔符时才会读取。对于包含空格和换行符的字符串,请改为使用fgets和sscanf的组合,并指定长度限制。
答案 3 :(得分:0)
没有我收集的这样的东西你试图在fscanf
函数中暗示一个不存在的正则表达式,不是我所知道的,也不是我在任何地方看过它 - 启发我这一点。
读取字符串的格式说明符是%s
,可能需要这样做,%s\n
将获取换行符。
但是对于皮特而言,不要使用Clifford上面的答案所规定的标准旧gets
家族函数,因为这是缓冲区溢出发生的地方,并用于1990年代臭名昭着的蠕虫病毒 - 莫里斯蠕虫,更具体地说是fingerd
守护进程,曾经叫gets
导致混乱。幸运的是,现在已经修补了。此外,许多程序员已经深入研究了不使用该功能的心态。
即使Microsoft采用了gets
系列函数的安全版本,也指定了一个参数来指示缓冲区的长度。
修改强> 我的坏 - 我没有意识到Clifford确实指定了输入的最大长度......哎呀!抱歉!克利福德的答案是对的!所以+1来克利福德的答案。
感谢Neil指出我的错误......
希望这有帮助, 最好的祝福, 汤姆。
答案 4 :(得分:-1)
我发现了问题。
正如Paul Tomblin所说,我在上面的领域有一个额外的新线字符。所以使用tommieb75所说的我用过:
result = fscanf(fp, "%s\n", ap->code);
result = fscanf(fp, "%[^\n]s", ap->name);
这就解决了!
感谢您的帮助。