Внедрение утилиты Unix хвост в C


Я написал простую реализацию хвост как часть значение C язык программирования с Керниган & Ритчи.

Вопрос государства-оставить хвост, который печатает последние n строк из своего вклада. По умолчанию N равно 10, но может быть определена при записи: tail -n чтобы распечатать последние n строк. Я не думаю, что программа для открытия и чтения файлов, так что не были охвачены в книге, как еще.

Я решил взять вход tail -n <number> и написал код для парсинга аргументов в (надеюсь), что позволит кроме больше аргументов в дальнейшем легче с помощью оператора switch. Однако сейчас, если бы было больше аргументов (скажем, X и Z) можно было бы написать хвост -xzn 10, который будет действовать, печатать последние 10 строк - что может рассматриваться как проблема.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLEN 1000

int tail(char *buffer[], int n);
int read_line(char *line, int max);
void print_lines(char* buffer[], int n);

static int lines_read = 0;

int main(int argc, char* argv[]) {
  int number_of_lines = 10;
  char c;

  while(--argc > 0 && (*++argv)[0] == '-') {
    while((c = *++argv[0])) {
      switch(c) {
        case 'n':
          if(argc-1 > 0)
            number_of_lines = atoi(*(argv+1));
          break;
      }
    }
  }  

  char *line_buffer[number_of_lines];

  if(tail(line_buffer, number_of_lines) < 0) {
    printf("ERROR: failed to allocate memory for a line.\n");
    return -1;
  }

  printf("Output:\n"); 
  print_lines(line_buffer, number_of_lines);

  return 0;
}

int tail(char *buffer[], int n) {
  int characters_read = 0;
  char *p, line[MAXLEN];

  while((characters_read = read_line(line, MAXLEN)) > 0) {
    if((p = malloc(sizeof(char)*characters_read)) == NULL) {
      return -1;
    }
    strcpy(p, line);
    buffer[lines_read++ % n] = p;
  }

  return 0;
}

int read_line(char *line, int max) {
  int c, chars_read = 0;

  while((c = getchar()) != EOF && c != '\n' &&  ++chars_read < max-1)
    *line++ = c;

  *line = '\0';

  return chars_read;
}

void print_lines(char *buffer[], int n) {
  for(int i=0; i < (lines_read > n ? n : lines_read); i++)
    printf("%s\n", buffer[lines_read > n ? lines_read++ % n : i]);
}


187
3
задан 25 января 2018 в 06:01 Источник Поделиться
Комментарии
1 ответ


  • Избежать глобалс. lines_read естественно подходит для возврата lines_read.

  • tail утечек памяти. Вы должны free линии указывали buffer[....] прежде чем переназначить его.

  • sizeof(char) гарантированно будет 1.

Я не помню на какой точке K&Р предложить это упражнение. В любом случае,


  • Линия-значение цикла лучше выражается fgets.

  • malloc/strcpy комбинация-это долгий путь, чтобы сказать strdup.

1
ответ дан 25 января 2018 в 07:01 Источник Поделиться