在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++;