Чтение каждого символа за раз — C

#c #getchar

#c #getchar

Вопрос:

Для приведенного ниже вопроса,

Упражнение 12336 — Считывайте обычный текст по символу за раз из стандартного ввода программы и печатайте его с каждой строкой, перевернутой слева направо. Читайте, пока не столкнетесь с окончанием данных `

Возможно, вы захотите протестировать программу, набрав `

       prog5rev | prog5rev
  

чтобы увидеть, воссоздана ли точная копия исходного ввода. Для чтения символов до конца данных используйте цикл, такой как`

    char ch;
   while( ch = getchar(), ch >= 0 ) /* ch < 0 indicates end-of-data */
    or
    char ch;
    while( scanf( "%c", amp;ch ) == 1 ) /* one character read */
  

Вот мое решение:

 #include  <stdio.h>

void f(char *);
int main(void)
{
    char ch = getchar();
    f(amp;ch);

    return 0;
}

void f(char *ch){
    if(*ch < 0)
        return;
    else{
        char character = getchar();
        f(amp;character);
    }
    putchar(*ch);
}
  

Ввод:

 abc | abc
  

Вывод:

 cba | cba
  

Вопрос:

Проблема гласит: print it with each line reversed from left to right.

Правильно ли это решение?

Комментарии:

1. Я думаю, что в условии prog5rev указано имя программы, а не пример ввода. Они предлагают запустить программу дважды (с результатами одного, передаваемыми другому), и предоставить какой-то другой ввод, и ожидать, что результат будет таким же, как и ввод, потому что он был отменен дважды. Вы, кажется, неправильно истолковали это как означающее | ввод ввода программы.

Ответ №1:

Это такое умное решение, что я действительно ненавижу его нарушать, но использование стека для него имеет некоторые ограничения. если быть точным, ограничения памяти. Если у вас больше определенного, относительно небольшого объема входных данных, он достигнет предела и произойдет сбой тем или иным способом, например: ошибка сегментации. Все 5 560 737 символов полного Шекспира из Гутенберга не проходят, они разбиваются на 654 337 символов.

Извините, вам нужно использовать кучу для большего ввода.

Комментарии:

1. Я безоговорочно склонен к рекурсии. Всегда пытаюсь найти странный подход для получения рекурсивного решения. Это большая проблема для меня

2. @overexchange с этим подходом нет абсолютно никаких проблем, если вы знаете о его пределах.

Ответ №2:

Да, это работает так, как ожидалось.

Вы читаете символ и вызываете f . Если EOF не был прочитан, вызовите f снова, а затем выведите прочитанный символ. Поскольку вы печатаете символ после рекурсивного вызова, символы печатаются в обратном порядке.

Однако одно изменение, которое вы должны внести, — использовать int вместо char для типа данных. getchar Функция возвращает an int , чтобы можно было правильно определить EOF. putchar Функция принимает int , поэтому вам не о чем беспокоиться.

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

Ответ №3:

Формулировка проблемы уже дает подсказку о решении:

    char ch;
   while( ch = getchar(), ch >= 0 ) /* ch < 0 indicates end-of-data */
    or
    char ch;
    while( scanf( "%c", amp;ch ) == 1 ) /* one character read */
  

Вы должны использовать цикл для чтения данных, stdin а затем внутри цикла проверять, есть ли новая строка, и только после этого печатать эту строку справа налево (возвращать строку).

Ниже приведен код, который простым способом выполняет задачу, возможно, потребуется некоторое улучшение, но он работает.

Пожалуйста, прочитайте комментарии и попытайтесь понять, что там происходит, если у вас есть какие-либо вопросы, пожалуйста, задавайте их.

 #include <stdio.h>
#include <string.h> // for memset

void f(char *, int);

int main(void)
{
    char ch;
    char buffer[1024] = { 0 }; // 1024 = max supported line length
    int i; // ieterator

    i = 0;
    while( scanf( "%c", amp;ch ) == 1 ) { // while there is input
        if ( ch == 'n' ) { // if there is a new line
            f(buffer, i); // print the line (inverted)
            i = 0; // reset iterator
            memset(buffer, 0, 1024); // reset buffer
        } else {
            buffer[i  ] = ch; // append read char to the buffer
        }
    }

    return 0;
}

void f(char *str, int n) {
    // just print from right to left (easier than reversing and then printing the string)
    while (n >= 0) {
        putchar(str[n]);
        n--;
    }
    putchar('n');
}
  

Обновление: в книге рекомендуется протестировать программу с помощью

  prog5rev | prog5rev
  

Я рекомендую создать входной файл, а затем запустить:

  $ prog5rev < input.txt | prog5rev
  

В предыдущем утверждении предполагается, что вы используете linux (или какой-либо unix).

Пример:

 [ichramm@wilderjager][~]$ cat input.txt 
hello
world
[ichramm@wilderjager][~]$ ./test < input.txt  
olleh
dlrow
[ichramm@wilderjager][~]$ ./test < input.txt | ./test 
hello
world
  

Комментарии:

1. Пожалуйста, не выполняйте все его домашнее задание… конечно, направляйте и отвечайте на острые вопросы, но раздача всей энчилады не помогает ему научиться думать, в чем смысл практики

2. @ScottStensland Ты серьезно? Правила ясны: ответ должен быть полным. Итак, вы понижаете голос, если ответ неполный, а также понижаете голос, если ответ слишком полный? Решайтесь!