Программа на C для чтения альтернативных символов из файла с помощью системных вызовов, не работающих в цикле - PullRequest
0 голосов
/ 12 февраля 2019

Я создал программу, которая считывает альтернативные символы из файла, передаваемого в качестве аргумента терминала, и печатает его на терминале.Программа:

#include<stdio.h>
#include<unistd.h>


int main(int argc, char * argv[])
{
    int fd = open(argv[1]);

    if(fd>0)
    {
        char content[1];

        while(read(fd,content,1))
        {
            write(1,content,1);
            lseek(fd,1,SEEK_CUR);
        }
    }
    else
    {
        printf("File could not be opened.\n");
    }

    return 0;
}

Но это печать символов в странном порядке.Но когда я просто использовал этот код, повторяя его один за другим, он печатал альтернативные символы.Вот что работает:

    read(fd,content,1);
    write(1,content,1);
    lseek(fd,1,SEEK_CUR);

    read(fd,content,1);
    write(1,content,1);
    lseek(fd,1,SEEK_CUR);

    read(fd,content,1);
    write(1,content,1);

Мой входной файл:

abcdefgh
ijklmnopq
rstuvwxyz

Вывод, который я получаю:

ikmoq
suwy

Под альтернативными символами я имею в виду пропуск 1 символа.

Этот код печатает 3 альтернативных символа из файла, но цикл печатает разные символы из самого второго символа.Куда я иду не так?Почему повторяющийся код работает, а цикл не работает?

1 Ответ

0 голосов
/ 12 февраля 2019

Вам нужно #include <fcntl.h>, но проблема не в этом.

На самом деле ожидается вывод

ikmoq
suwy

.

Входной файл

abcdefgh
ijklmnopq
rstuvwxyz

Выглядит так в памяти abcdefgh\r\nijklmnopq\r\nrstuvwxyz, потому что в Windows окончания строк обозначаются "\ r \ n" двумя байтами 13 и 10.

Вы печатаете каждый второй символ, поэтому выprint:

'a' 'c' 'e' 'g' '\ r' 'i' 'k' и т. д.

Но когда вы делаете необработанный вывод с write,\r помещает только курсор в начало строки, и поэтому последующие символы будут перезаписывать уже напечатанные символы.

Измените вашу программу следующим образом:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char * argv[])
{
  int fd = open("input.txt", O_RDONLY);

  if (fd > 0)
  {
    char content[1];

    while (read(fd, content, 1))
    {      
      if (content[0] == '\r')
      {
        static char cr[] = "<CR>";
        write(1, cr, sizeof cr - 1);
      }
      else if (content[0] == '\n')
      {
        static char lf[] = "<LF>";
        write(1, lf, sizeof lf - 1);
      }

      else
      {
        write(1, content, 1);
        lseek(fd, 1, SEEK_CUR);
      }
    }
  }
  else
  {
    printf("File could not be opened.\n");
  }

  return 0;
}

Это показывает, что байтыфактически считывается из файла.

Вывод:

aceg<LF><CR>ikmoq<CR>rtvxz

Упрощенная версия цикла while с использованием putc, который автоматически обрабатывает окончания строк:

while (read(fd, content, 1))
{
  putc(content[0], stdout);
  lseek(fd, 1, SEEK_CUR);
}

Versionиспользование только системных вызовов (это, вероятно, зависит от платформы):

while (read(fd, content, 1))
{
  if (content[0] == '\r' || content[0] == '\n')
  {
    static char eol[] = "\r\n";
    write(1, eol, sizeof eol - 1);
  }
  else
  {
    write(1, content, 1);
  }

  lseek(fd, 1, SEEK_CUR);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...