首页 > 解决方案 > 如何从 C 中的缓冲区末尾重新读取几个字符?

问题描述

我正在使用缓冲区来临时存储文件中的某些字节数据(字符)。我只想找出文件中是否存在特定单词。比方说,我正在搜索一个单词“Apple”,并将文件中的一个字符串存储到缓冲区中,该缓冲区的前半部分“App”位于缓冲区末尾,“le”位于下一个缓冲区中。我只是想确保不会错过这些单词 我可以做些什么来重新读取缓冲区末尾的特定长度。如何修改以下代码?

while(feof(fptr)==0){
    char * result;
    char line[100];
    result = fgets( line, sizeof( line ), fptr );

    if ( result == NULL ){
        break;
    }

    line[strcspn( line, "\n" ) ] = '\0';
    token = strtok(line," \t,:;\'\"\?!-_|\\><~@#$%^&*()+{}[].=1234567890");

    while( token != NULL ) {
        printf( " %s\n", token );
        if(strcasecmp(token,word)==0){
            count++; //counts the number of occurrence of the word 
        }
        token = strtok(NULL," \t,:;\'\"\?!-_|\\><~@#$%^&*()+{}[].=1234567890");
    }
}

标签: cfilebuffer

解决方案


您不一定可以重新读取数据 - 如果您正在读取您可以查找的文件,但如果您正在从管道读取,那么您不能,并且您希望您的程序在可能的情况下同时使用两者。

但是,您已经在缓冲区中拥有该数据。因此,您可以只使用已有的副本,并将其移动到缓冲区的开头:

char line[100]; // declare this outside the loop since we need to keep using the same variable

// start it off full of spaces: (or any other symbol you aren't searching for)
memset(line, ' ', 99);
line[99] = '\0';

在循环:

// Let's say you're looking for 5 letters ("Apple") so you want a 5-letter overlap.
// Note: we know the buffer has at least 5 valid letters in it, because we always keep that many in it.
memmove(line, line + strlen(line) - 5, 5);
result = fgets( line + 5, sizeof( line ) - 5, fptr );

我们在做什么?

我们将前一个缓冲区的末尾移回起点,然后读取更多输入以填充缓冲区的其余部分。


Input data: "hello world this is a testerino and here's some more text\n" and we've already read some of it.

Before memmove:
+---------------------------------------------+
|hello world this is a testerino\0djflhashdasa| <- line (the part after the \0 could be gibberish)
+---------------------------------------------+
                           ^^^^^ what we are copying
After memmove:
+---------------------------------------------+
|erino world this is a testerino\0djflhashdasa| <- line
+---------------------------------------------+
 ^^^^^ where we copy it to

After fgets:
+---------------------------------------------+
|erino and here's more text\n\0no\0djlhashdasa| <- line
+---------------------------------------------+
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ what we ask fgets to read
      ^^^^^^^^^^^^^^^^^^^^^^^^^ what it actually read

And repeat

(注意:\n 和 \0 实际上并不占用两个字节,我只是以这种方式显示它们以用于说明目的)

注意:这并不能完全解决问题!如果您正在搜索“Apple”,并且您阅读了“crabApple”并且缓冲区恰好在“Apple”之后结束,那么您会将“Apple”移回开头,然后将其检测为一个单词。此外,如果您阅读“Apple”然后缓冲区结束,您可能会检测到两次(移动之前和移动之后)。


推荐阅读