Попытка заменить все экземпляры char в char *, который был прочитан из канала - PullRequest
1 голос
/ 13 ноября 2011

Я реализую функцию для домашнего задания.Определение функции:

int processchar(int fdin, int fdout, char inchar, char *outstr);

Функция processchar читает из файлового дескриптора fdin до конца файла и записывает в файловый дескриптор fdout, переводя любое вхождение символа inchar в строку outstr.В случае неудачи processchar возвращает -1 и устанавливает значение errno.

Мой текущий код выглядит следующим образом:

#define CHUNK 256
int processchar(int fdin, int fdout, char inchar, char *outstr){
  int j = 0, n = CHUNK, np = CHUNK, r;
  char *buf, *tmp_buf, *fin_buf, *k, *rbuf, *rrbuf;

  if((buf = malloc(sizeof(char) * n )) == NULL)
    return 1;
  while((r = read(fdin, buf, CHUNK))){
    if( r == -1 )
      return -1;
    n += r;
    if(np - n < CHUNK) {
      np *= 2;
      rbuf = malloc(np * sizeof(char));
      memcpy(rbuf, buf, n * sizeof(char));
      free(buf);
      buf = rbuf;
    }
  }
  fprintf(stderr, "buf is %s\n",
  for(tmp_buf = buf; tmp_buf < buf + n; tmp_buf++){
    if(*tmp_buf == inchar)
      j++;
  }
  if((fin_buf = malloc((sizeof(char) * n) + (sizeof(char) * j * strlen(outstr) + 1)) == NULL))
    return 1;
  rrbuf = fin_buf;
  for(tmp_buf = buf; tmp_buf < buf + n; tmp_buf++){
    if(*tmp_buf == inchar){
      fprintf(stderr, "got another j\n");
      k = outstr;
      while(*fin_buf++ = *k++);
    } else {
      fprintf(stderr, "swing n a miss\n");
      *fin_buf++ = *tmp_buf;
    }
  }
  write(fdout, rrbuf, strlen(rrbuf));
  return 0;
}

Из проведенного тестирования похоже на раздел:

tmp_buf < buf + n

в определении цикла for не имеет ожидаемых последствий.Функция вызывается кольцом процессов, каждый из которых передает свой стандартный поток на стандартный поток следующего (в случае использования fdin равен STDIN_FILENO, а fdout равен STDOUT_FILENO).В частности, операторы fprintf во втором цикле for не печатают столько раз, сколько я ожидаю (я ожидаю, что они будут печататься один раз для каждого символа, напечатанного fprintf из buf).

Я давно смотрю на эту функцию и буду признателен за любое направление или мнение, которое вы все сможете дать.Ранее я использовал несколько потоков на этом сайте и фактически извлек прямо из этого для определения j в приведенном выше коде.

(Примечание : это назначение является вспомогательным средством для обучения реализации колец в книге по программированию в Unix-системах)

1 Ответ

2 голосов
/ 13 ноября 2011

Я думаю, что вы, возможно, думаете об этом. Простая реализация, которая должна удовлетворять назначению, будет:

#define CHUNK 256
int processchar ( int fdin, int fdout, char inchar, char *outstr ) {
    char buf[CHUNK];
    int r, outlen = strlen( outstr );

    while ( (r = read( fdin, buf, CHUNK )) > 0 ) {
        int i;
        for ( i = 0; i < r; i++ ) {
            if ( buf[i] == inchar ) {
                if ( write( fdout, outstr, outlen ) < 0 ) return -1;
            } else {
                if ( write( fdout, &buf[i], 1 ) < 0 ) return -1;
            }
        }
    }
    return r;
}

Вы можете немного оптимизировать это, собирая последовательные несовпадающие символы и записывая их в один вызов write(); Я оставлю это как упражнение.

(Кроме того, я не проверяю частичные записи или EINTR. В общем, это IMO, что лучше всего делать в функциях-оболочках вокруг read() и write(), а не в коде вызова высокого уровня.)

...