在C中读取一行,标记化并赋值给struct
在C中读取一行,标记化并赋值给struct,c,string,C,String,line是fgets'd,在循环中运行,而循环中带有计数器n,d是一个具有两个字符数组的结构,p和q。基本上,用几句话,我想读一行,把它分成两个字符串,一个直到第一个空格,另一个和行的其余部分。我随后清理(\n从文件变成“0”)。代码是有效的,但是有没有更惯用的方法呢?我在“不知不觉”中遇到了什么错误 编辑:q可能包含空格 谢谢。您可以随时使用: sscanf(line, "%s %s", d[n].p, d[n].q); 假设您想要放入p和q中的内容不包含空格,并且p和q保证足够大以容纳令牌
line
是fgets'd,在循环中运行,而循环中带有计数器n
,d
是一个具有两个字符数组的结构,p
和q
。基本上,用几句话,我想读一行,把它分成两个字符串,一个直到第一个空格,另一个和行的其余部分。我随后清理(\n
从文件变成“0”)。代码是有效的,但是有没有更惯用的方法呢?我在“不知不觉”中遇到了什么错误
编辑:q
可能包含空格
谢谢。您可以随时使用:
sscanf(line, "%s %s", d[n].p, d[n].q);
假设您想要放入p和q中的内容不包含空格,并且p和q保证足够大以容纳令牌(包括零终止)
scanf函数是危险的,但正确使用时非常有用
scanf("%s %[^\n]", d[n].p, d[n].q);
%[…]
指令类似于%s
,但它不匹配非空白字符,而是匹配括号内的字符,或者匹配除括号内字符以外的所有字符(如果^
为前导字符)
您应该检查返回值以查看是否实际输入了q
;如果“行的其余部分”实际上为空,则这与代码的行为有些不同。(或者如果行以空格开头。)这只能通过纯指针算法来完成。假设行
包含当前行:
char *p = line;
char *part1, *part2;
while (*p && *p != ' ') {
p++;
}
if (*p == ' ') {
*p++ = '\0';
part1 = strdup(line);
part2 = strdup(p);
if (!part1 || !part2) {
/* insufficient memory */
}
} else {
/* line doesn't contain a space */
}
基本上,您扫描字符串直到第一次出现空格,然后用空字符替换空格以指示第一部分的结尾(strdup
需要知道停止的位置),并将指针向前移动一步以获取字符串的其余部分
要使代码看起来更干净,但调用函数的开销更大,可以使用strchr()
而不是while
循环:
char *p = strchr(line, ' ');
char *part1, *part2;
if (p) {
*p++ = '\0';
part1 = strdup(line);
part2 = strdup(p);
}
我会写的代码和你的差不多。一些调整:
- 您无法从
strncpy
中获得任何信息。在这里,请使用memcpy
- 使用
strcspn
也无法从中获得任何信息,请使用strchr
- 避免扫描字符串的部分两次
因此:
然后检查需要匹配的scanf手册页,而不是最后的%s。formatstring中的空格将被忽略,“%s%s”相当于“%s%s”strcspn
和strlen
返回size\u t
,而不是int
。在这里使用错误的类型99%都是无害的,但这是一个坏习惯,因为每隔一段时间就会导致漏洞。@R:Fixed。还有“5”更多。strdup不是c标准,如果单词用“\t”分隔,你该怎么办?可以使用其他空格strpbrk(行“\t”)
,而strdup
是POSIX标准的一部分,它使它得到广泛支持。formatstring中的空格将被忽略,“%s%[^\n]”相当于“%s%[^\n]”
char *p = strchr(line, ' ');
char *part1, *part2;
if (p) {
*p++ = '\0';
part1 = strdup(line);
part2 = strdup(p);
}
char *spc = strchr(line, ' ');
memcpy(d[n].p, line, spc - line);
d[n].p[spc - line] = '\0';
spc++;
char *end = strchr(spc, '\n');
if (end)
{
memcpy(d[n].q, spc, end - spc);
d[n].q[end - spc] = '\0';
}
else
strcpy(d[n].q, spc);
n++;