【发布时间】:2016-01-21 18:28:06
【问题描述】:
我正在尝试使用fgets 和sscanf 解析这个简单的配置文件:
# configuration file for client
[user]
ID 34DV4gx7
NAME Somebody
我编写了以下脚本来解析它,其中 sscanf 最初似乎可以正确提取变量,然后由于某种未知原因将它们混合在一起:
int main (void)
{
FILE *conf;
char *confname = "client.conf";
char buf[256], tmp[256];
char id[8];
char name[12];
char token[40];
size_t i, count = 0, valid = 0, len = sizeof token;
if ((conf = fopen (confname, "r")) == NULL)
{
fprintf (stderr, "Failed to open configuration file %s\n", confname);
return 1;
}
memset (id, 0, sizeof id);
memset (name, 0, sizeof name);
memset (token, 0, sizeof token);
while (!feof (conf))
{
memset (buf, 0, sizeof buf);
memset (tmp, 0, sizeof tmp);
if (fgets (buf, sizeof buf, conf) == NULL) continue;
if (buf[0] == '#' || buf[0] == '[') continue;
if (sscanf (buf, "ID %s", tmp) == 1)
{
strncpy (id, tmp, sizeof id);
id[strlen (id)] = '\0';
printf ("id: %s[%d]\n", id, strlen (id));
valid++;
continue;
}
else if (sscanf (buf, "NAME %s", tmp) == 1)
{
strncpy (name, tmp, sizeof name);
name[strlen (name)] = '\0';
printf ("name: %s[%d]\n", name, strlen (name));
valid++;
continue;
}
}
fclose (conf);
printf ("id: %s\n", id);
printf ("name: %s\n", name);
if (valid != 2) return 2;
for (i = 0; i < strlen (id) && count < len; i++) token[count++] = id[i];
token[count++] = ':';
for (i = 0; i < strlen (name) && count < len; i++) token[count++] = name[i];
token[count] = '\0';
printf ("token: %s\n", token);
return 0;
}
结果:
id: 34DV4gx7[8]
name: Somebody[8]
id: 34DV4gx7Somebody
name: Somebody
token: 34DV4gx7Somebody:Somebody
预期:
id: 34DV4gx7[8]
name: Somebody[8]
id: 34DV4gx7
name: Somebody
token: 34DV4gx7:Somebody
我尝试了很多方法来找出导致这种行为的原因,但一无所获,我认为可能是 id 和 name 变量不是以空结尾的,所以我在末尾手动添加了 \0,然后我认为可能是buf 在循环中被覆盖,所以我使用 memset 重置它并重置所有 char 数组并检查所有内容的长度,但我看不出出了什么问题。任何帮助将不胜感激。
【问题讨论】:
-
第一步:
while (!feof (conf))-->while (fgets (buf, sizeof buf, conf)) -
第二步
id[strlen (id)] = '\0';-->id[sizeof id - 1] = '\0' -
请注意,
name[strlen (name)] = '\0';没有做任何有用的事情。strlen读取name直到找到'\0',即使它比数组长。然后你将刚刚找到的'\0'设置为'\0'。 -
@chux 我很确定你的两个 cmets 实际上是他问题的答案。你应该发布它们。
-
感谢 chux 和 Zan 的 cmets,但输出仍然相同