использование двух буферов в программе C, которая копирует команду w c - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть следующий код, который имитирует команду w c из linux. Мне нужно использовать буфер с размером 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);        
   }
 } 

}```

1 Ответ

1 голос
/ 15 апреля 2020

read пытается прочитать до LUNG_BUF байтов в буфер и возвращает количество фактически прочитанных байтов (или ноль в случае конца файла или -1, чтобы указать на ошибку).

Это означает, что проверка для == 1 в большинстве случаев будет неудачной.

Если вы хотите интерпретировать данные, также имеет смысл прочитать на один байт меньше максимального размера буфера, чтобы иметь возможность поместить завершающий NUL-байт в конец буфера.

Вы Затем можно оценить эти данные, например, используя указатель, который устанавливается в начало буфера при каждом проходе l oop.

Таким образом, ваш код будет выглядеть следующим образом:

size_t n;
while ((n = read(fileno(file), buffer, LUNG_BUF - 1)) > 0) {
    buffer[n] = '\0';
    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 байтов (так как по крайней мере один завершающий NUL к байту добавляется fgets), если строка на самом деле длиннее.

Таким образом, ваш слегка измененный l oop будет выглядеть так:

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