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

На приведенный ниже вопрос:

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

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

      prog5rev | prog5rev

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

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

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

#include  <stdio.h>

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

    return 0;
}

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

Вход:

abc | abc

Выход:

cba | cba

Вопрос:

В задаче написано: print it with each line reversed from left to right.

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


person overexchange    schedule 13.10.2016    source источник
comment
В условии я думаю, что prog5rev - это имя программы, а не образец ввода. Они предлагают запустить программу дважды (с результатами одного, переданного другому), и предоставить некоторые другие входные данные, ожидая, что выходные данные будут такими же, как и входные, потому что они были изменены дважды. Вы, кажется, неправильно истолковали это как ввод | в вводе программы.   -  person M.M    schedule 13.10.2016


Ответы (3)


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

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

person deamentiaemundi    schedule 13.10.2016
comment
Безоговорочно склоняюсь к рекурсии. Всегда пытаюсь найти странный подход, чтобы дать рекурсивное решение. Это большая проблема во мне - person overexchange; 13.10.2016
comment
@overexchange, с этим подходом нет абсолютно никаких проблем, если вы знаете о его ограничениях. - person deamentiaemundi; 13.10.2016

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

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

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

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

person dbush    schedule 13.10.2016

Постановка задачи уже дает подсказку о решении:

   char ch;
   while( ch = getchar(), ch >= 0 ) /* ch < 0 indicates end-of-data */
    or
    char ch;
    while( scanf( "%c", &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", &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
person JuanR    schedule 13.10.2016
comment
Пожалуйста, не выполняйте все его домашнее задание ... направляйте и отвечайте на острые вопросы, конечно, но раздача всей энчилады не помогает ему научиться думать, в чем смысл практики - person Scott Stensland; 13.10.2016
comment
@ScottStensland Вы серьезно? Правила здесь ясны: ответ должен быть полным. Итак, вы минусуете, если ответ неполный, а также минусите, если ответ слишком полный? Сделайте свой ум! - person JuanR; 13.10.2016