我是 C 的新手,在这里遇到了一些麻烦我试图解析一个 html 文件并计算文件中 p-tags 的数量。我正在使用不同大小的 block ,大小由用户输入。但是当大小跳到 200 时,我得到了错误的 p-tags 数量。我使用 recv 函数接收文件并使用缓冲区的内容来计算所述 p-tags。
count = recv(s, buf, sizeof buf, 0);
for(int i=0; i<chunk; i++)
{
if(buf[i]=='<')
if(buf[i+1]=='p')
if(buf[i+2]=='>')
pcount++;>*/
}
当 block 大小为 200 时,它应该返回 13 个 p-tags 但它返回了 15。
最佳答案
有几个问题。大概是chunk
是缓冲区的大小。现在,如果 recv
成功它将返回接收到的字节数。您应该使用 this 计数而不是 chunk
用于限制循环。否则你会为失败的 recv
运行循环操作,它会计算缓冲区中存在的任何垃圾。
第二个问题当然是 <p>
标记实际上可能位于 2 个 block 的边界上。
第三个是您可能越界读取缓冲区 - 即使 buf[i]
有效并不意味着 buf[i + 2]
是。
最简单,但也许不是最正确的解决方案是使用 fdopen
在 socket 上,然后是 fgetc()
,或将整个主体读入缓冲区。让我们使用 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;
}
}
这将在不同的 block 大小上正常工作,并且不会解决缓冲区越界的问题。不过,作为一个并发症,它看起来确实比 fdopen
复杂得多。一个,即使它仍然缺少外循环!
关于c - 如何在流套接字字节流中查找特定字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54741715/