读取String中的fscanf问题

我正在读一个.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); 

这允许我读入没有空格的字符串。 但是当我得到一个带有空格的“名字”时它不起作用。

这有一个问题:

 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在其格式说明符(空格,换行符或制表符)中找到空格时,它会消耗尽可能多的空格(即,您可以认为它消耗了与正则表达式匹配的最长字符串[ \t\n]* ) 。

最后,您还应指定最大长度以避免缓冲区溢出。 您可以通过将缓冲区长度放在%[之间[ 。 例如,如果ap->name是256个字符的缓冲区,则应该这样做:

 result = fscanf(fp, "%255[^\n]%*c", ap->name); 

这适用于静态分配的数组; 遗憾的是,如果数组在运行时具有动态大小,那么将缓冲区大小传递给fscanf并不容易。 您必须使用sprintf创建格式字符串,例如:

 char format[256]; snprintf(format, sizeof(format), "%%%d[^\n]%%*c", buffer_size - 1); result = fscanf(fp, format, ap->name); 

Jumm写道:

如果我在fscanf的位置使用fgets,我会在变量中得到“\ n”。

这是一个更容易解决的问题,所以顺其自然:

 fgets( ap->name, MAX, fp ) ; nlptr = strrchr ( ap->name, '\n' ) ; if( nlptr != 0 ) { *nlptr = '\0' ; } 

我不确定你的意思是[^ \ n]假设工作。 []是一个修饰符,表示“接受一个字符, 除了该块内的任何字符”。 ^反转条件。 带有fscanf的%s只读取,直到遇到分隔符。 对于包含空格和换行符的字符串,请改为使用fgets和sscanf的组合,并指定长度限制。

没有这样的东西,我收集到你试图在fscanf函数中暗示一个不存在的正则表达式,不是我所知道的,也不是我在任何地方看过它 – 启发我这一点。

读取字符串的格式说明符是%s ,可能需要这样做, %s\n将获取换行符。

但是对于皮特而言,不要使用Clifford上面的答案所规定的标准旧的gets家庭function因为这是缓冲区溢出发生的地方,并且被用于1990年代的臭名昭着的蠕虫 – 莫里斯蠕虫,更具体地说是fingerd守护进程中使用的打电话gets那造成混乱。 幸运的是,现在已经修补了。 此外,许多程序员已经深入研究了不使用该function的心态。

甚至微软也采用了一系列函数的安全版本,它指定了一个参数来代表缓冲区的长度。

编辑我的坏 – 我没有意识到Clifford确实指定了输入的最大长度……哎呀! 抱歉! 克利福德的答案是对的! 所以+1来克利福德的回答。

谢谢尼尔指出我的错误……

希望这会有所帮助,最好的问候,汤姆。

我发现了问题。

正如Paul Tomblin所说,我在上面的领域有一个额外的新线条。 所以使用tommieb75说我用过的:

 result = fscanf(fp, "%s\n", ap->code); result = fscanf(fp, "%[^\n]s", ap->name); 

这固定了!

谢谢你的帮助。