我是C语言的新手,在这里遇到了一些麻烦,我试图通过html文件解析并计算文件中p-tag的数量。我正在使用不同大小的块,大小由用户输入。但是,当大小跳到200时,我得到的p标签数量错误。我使用recv函数来接收文件,并且正在使用缓冲区的内容来计数所述p标签。
username
当块大小为200时,它应该返回13个p标签,但返回15个。
答案 0 :(得分:3)
有几个问题。大概chunk
是缓冲区的大小。现在,如果recv
成功,它将返回接收到的字节数。您应该使用 this 计数而不是chunk
来限制循环。否则,您甚至会为失败的recv
操作运行循环,它将计算缓冲区中存在的任何垃圾。
第二个问题当然是<p>
标签实际上可能位于2个块的边界上。
第三个问题是,您可能正在越界读取缓冲区-即使buf[i]
有效并不意味着buf[i + 2]
是有效的。
最简单的,但可能不是最正确的解决方案是在套接字上使用fdopen
,然后使用fgetc()
,或读取整个主体< / em>放入缓冲区。让我们使用fdopen
:
FILE *f = fdopen(s, "r+b");
size_t pcount = 0;
int c = 0;
while (c != EOF)
{
if ((c = fgetc(f)) == '<'
&& (c = fgetc(f)) == 'p'
&& (c = fgetc(f)) == '>')
{
pcount += 1;
}
}
在这里,我们将套接字包装到<stdio.h>
FILE
中; fgetc
返回文件中的下一个字符,并且&&
短路;最后一个fgetc
的返回值也被捕获在c
中;如果返回值是EOF
,则循环会中断,并且pcount
将包含正确的标记计数。
如果您不能使用fdopen
,则可以为套接字编写自己的缓冲逻辑,甚至可以创建一个模拟函数,一次调用recv
一个字节...
或者您可以使用状态机:
int pstate = 0;
ssize_t count = recv(s, buf, sizeof buf, 0);
// TODO: add error checking...
for (ssize_t i = 0; i < count; i++)
{
if (buf[i] == '<') {
pstate = 1;
}
else if (pstate == 1 && buf[i] == 'p') {
pstate = 2;
}
else if (pstate == 2 && buf[i] == '>') {
pcount += 1;
pstate = 0;
}
else {
// if any other character is found,
// or any of these characters was in wrong position
// then reset the state
pstate = 0;
}
}
这将在不同的块大小上正常工作,并且不会超出缓冲区的范围。复杂的是,尽管它仍然缺少外部循环,但与fdopen
相比,它确实要复杂得多!