在复制 wc 命令的 C 程序中使用两个缓冲区

using two buffers in C program that replicates the wc command

我有以下代码模拟来自 linux 的 wc 命令。我需要使用尺寸为 4096 的缓冲区,但由于某种原因,当我执行此代码时,我得到以下结果:

0 0 0 wcfile

即使文件不为空,我也得到 0 行、字和字节。 我使用的代码如下:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define LUNG_BUF 4096

int main(int argc, char** argv)
{
int bytes = 0;
int words = 0;
int newLine = 0;

char buffer[LUNG_BUF];
enum states { WHITESPACE, WORD };
int state = WHITESPACE; 
 if ( argc !=2 )
 {
     printf( "Nu ati introdu snumele  fisierului\n%s", argv[0]);
 }
 else{
     FILE *file = fopen( argv[1], "r");

   if(file == 0){
      printf("can not find :%s\n",argv[1]);
   }
   else{
            char *thefile = argv[1];

       while (read(fileno(file),buffer,LUNG_BUF) ==1 )
      {
         bytes++;
         if ( buffer[0]== ' ' || buffer[0] == '\t'  )
         {
            state = WHITESPACE;
         }
         else if (buffer[0]=='\n')
         {
            newLine++;
            state = WHITESPACE;
         }
         else 
         {
            if ( state == WHITESPACE )
            {
               words++;
            }
            state = WORD;
         }

      }        
      printf("%d %d %d %s\n",newLine,words,bytes,thefile);        
   }
 } 

}```

read 尝试将最多 LUNG_BUF 字节读入缓冲区和 returns 实际读取的字节数(或在文件结束时为零或 -1 表示错误) .

这意味着 == 1 的检查大多数时候都会失败。

如果您想解释数据,读取比最大缓冲区大小少一个字节以便能够在缓冲区末尾放置终止 NUL 字节也是有意义的。

然后您可以评估此​​数据,例如,通过在每次循环通过时使用设置为缓冲区开头的指针。

那么您的代码将如下所示:

size_t n;
while ((n = read(fileno(file), buffer, LUNG_BUF - 1)) > 0) {
    buffer[n] = '[=10=]';
    char *ptr = buffer;
    while (*ptr) {
        bytes++;
        if (*ptr == ' ' || *ptr == '\t') {
            state = WHITESPACE;
        } else if (*ptr == '\n') {
            newLine++;
            state = WHITESPACE;
        } else {
            if (state == WHITESPACE) {
                words++;
            }
            state = WORD;
        }
        ptr++;
    }
}

另一种选择是使用 fgets,它提供一行或最多 4095 字节的数据(因为 fgets 至少附加了一个终止 NUL 字节),如果该行实际上更长的话。

所以你的循环只是稍微修改一下,看起来像这样:

while (fgets(buffer, sizeof(buffer), file)) {
    char *ptr = buffer;
    while (*ptr) {
    ...