K & R Упражнение 1-9 (C) - PullRequest
       46

K & R Упражнение 1-9 (C)

18 голосов
/ 22 июля 2010

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

Я предполагаю, что под этим он подразумевает что-то вроде ...

Мы (пустой) (пробел) (пробел) 1011 * идти * (пробел) до (пробел) (пробел) (пробел) The (пусто) торговый центр!

... и выведите его как:

Мы (пустой) 1027 * идти * (пробел) до (пробел) The (пусто) торговый центр!

Возможно, это проще, чем я себе представляю, но, тем не менее, я не могу понять это. Мне не очень нужен код ... тем более псевдокод .

Кроме того, как я должен смотреть на это? Я почти уверен, что любой программе, которую я напишу, понадобится хотя бы один variable, цикл while, пара операторов if, и он будет использовать функции getchar() и putchar() ... кроме того, я в растерянности. На самом деле у меня пока нет мыслителей, поэтому, если бы вы могли дать мне несколько советов о том, как я должен смотреть на «проблемы» в целом, это было бы здорово.

(И, пожалуйста, не поднимайте else, я не дошел до такой степени в книге, так что сейчас это выходит за рамки моих возможностей.)

Ответы [ 30 ]

22 голосов
/ 22 июля 2010

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

Он читает ввод по одному символу за раз. Если он видит что-то, кроме пробела, он просто печатает символ, который видит. Если он видит пробел, он переходит в другое состояние. В этом состоянии он печатает один пробел, а затем не печатает пробелы, если видит их. Затем он продолжает читать вводные данные, но игнорирует все пробелы, которые видит - до тех пор, пока не попадет на непустой символ, после чего он вернется в первое состояние.

(Кстати, эту концепцию называют конечным автоматом , и многие теоретические работы в области компьютерных наук посвящены тому, что они могут и не могут делать. Wikipedia может рассказать вам больше, хотя, возможно, в более сложных деталях, чем вы ищете;))

12 голосов
/ 22 июля 2010

Псевдокод

while c = getchar:
    if c is blank:
        c = getchar until c is not blank
        print blank
    print c

C

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

После многих замечаний, высказанных Мэтью в комментариях ниже, эта версия и версия, содержащая isblank, совпадают.

int c;
while ((c = getchar()) != EOF) {
    if (c == ' ') {
        while ((c = getchar()) == ' ');
        putchar(' ');
        if (c == EOF) break;
    }
    putchar(c);
}
5 голосов
/ 29 ноября 2012

Поскольку реляционные операторы в C генерируют целочисленные значения 1 или 0 (как объяснено ранее в книге), логическое выражение «текущий непустой символ или предыдущий непустой символ» может быть смоделировано с целочисленной арифметикой, что приводит к более короткому ( если немного загадочно) код:

int c, p = EOF;
while ((c = getchar()) != EOF) {
    if ((c != ' ') + (p != ' ') > 0) putchar(c);
    p = c;
}

Переменная p инициализируется с EOF, так что она имеет допустимое непустое значение во время самого первого сравнения.

4 голосов
/ 11 июня 2011

Вот что я получил:

while ch = getchar()
   if ch != ' '
      putchar(ch)
   if ch == ' '
      if last_seen_ch != ch
         putchar(ch)
   last_seen_ch = ch
2 голосов
/ 25 августа 2015

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

#include <stdio.h>

/* Write a            program         to copy its input to       its output, replacing             each string of one         or more blanks by a single blank. */

main()
{
    int c;

    while ((c = getchar()) != EOF){
        if (c == ' '){
            putchar(c);
            while ((c = getchar()) == ' ')
                ;
        }
        if(c != ' ')
            putchar(c);
    }
}
1 голос
/ 26 января 2014

То же самое объяснение с Мэттом Джоинером, но этот код не использует break.

int c;

while ((c = getchar()) != EOF)
{
    if (c == ' ') /* find a blank */
    {
        putchar(' '); /* print the first blank */
        while ((c = getchar()) == ' ') /* look for succeeding blanks then… */
            ; /* do nothing */
    }

    if (c != EOF) /* We might get an EOF from the inner while-loop above */
        putchar(c);
}
1 голос
/ 05 декабря 2013
#include <stdio.h>
main()
{
    int c, numBlank=0 ;
    while((c= getchar())!=EOF)
    {
        if(c ==' ')
    {
        numBlank ++;
        if(numBlank <2)
        {
        printf("character is:%c\n",c);
        }
    }
    else
    {
        printf("character is:%c\n",c);
        numBlank =0;
    }
    }
}
1 голос
/ 30 мая 2013
#include <stdio.h>
int main()
{
    int c;
    while( (c = getchar( )) != EOF )
    {           
        if (c == ' ') 
        {
            while ((c = getchar()) == ' ');
            putchar(' ');
            putchar(c);
        }
        else 
            putchar(c);
    }
    return 0;
}
1 голос
/ 23 мая 2013

Я написал это и, кажется, работает.

 # include <stdio.h>
 int main ()
{

int c,lastc;
lastc=0;
while ((c=getchar()) != EOF)
    if (((c==' ')+ (lastc==' '))<2)
        putchar(c), lastc=c;
 }
1 голос
/ 23 апреля 2019

Многие другие уже использовали последнюю символьную логику в своем коде, но, возможно, следующую версию легче читать:

int c, prevchar;
while ((c = getchar()) != EOF) {
    if (!(c == ' ' && prevchar == ' ')) {
        putchar(c);
        prevchar = c;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...