2016-08-30 3 views
2

Я изучаю путем чтения K & Р. Я стараюсь быть методичным и убеждаюсь, что понимаю понятия, прежде чем двигаться дальше.Пространство не заменено

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

Я написал следующее, но он выводит входные дословное даже при наличии нескольких последовательных пробелов:

#include <stdio.h> 

main() 

{ 
    int c, d, a; 

    c = getchar(); 
    while (c != EOF) 
    { 
     a = c; 

     if (c == ' ' && d == ' ') 
     { 
      a = 0; 
     } 

     d = c; 

     putchar(a); 
     c = getchar(); 
    } 
} 

Что я здесь делаю неправильно? Я не очень далеко в книге, так что я чувствую, что я что-то на самом деле просто не хватает ...

+3

Вы должны начать используя значащие имена переменных. Это в 80-х годах больше :) – Blorgbeard

+0

Повторно проверьте логику. Существует так много вызовов 'putchar' как (успешный)' getchar', поэтому никакие символы не будут удалены. Что касается 'он выводит входной дословный', я не думаю, что это так. – dxiv

+1

@Blorgbeard Я полностью согласен. Однако в этом примере алфавитные имена фактически облегчили разговор. – 2501

ответ

2

Есть некоторые хорошие моменты в комментариях:

  • использовать осмысленные имена переменных
  • putchar(0) не то же самое, как ничего
  • все переменные должны быть инициализированы

не писать Я хотел бы сделать еще одно предложение:

  • цикл while должен прочитать символ и проверить EOF, как показано ниже

(При условии, что у вас есть 2-е издание K & R, смотри раздел 1.5.1 на странице 17 для детального объяснения.)

Вот как я хотел бы написать код:

#include <stdio.h> 

int main(void) 
{ 
    int c; 
    int oldc = 'a'; 

    while ((c=getchar()) != EOF) 
    { 
     if (oldc != ' ' || c != ' ') 
      putchar(c); 
     oldc = c; 
    } 
} 
+0

Спасибо за это. Ваше решение намного элегантнее моего! – ARich

1

Я понял это, хотя я не вполне доволен моим решением:

#include <stdio.h> 

main() 

{ 
    int c, d; 

    d = 'a'; 
    c = getchar(); 
    while (c != EOF) 
    { 

     if (c != ' ') 
      putchar(c); 

     if (c == ' ' && d != ' ') 
      putchar(c); 

     d = c; 

     c = getchar(); 
    } 
} 

Спасибо тем, кто комментировал. Помимо проблем с моей логикой, я ошибочно полагал, что putchar(0) - это то же самое, что и печать строки нулевой длины.

+0

Это действительно довольно близко к принятому ответу. Все, что вы должны отметить, это то, что в общем случае 'if (x) do_that(); if (! x && y) do_that(); 'эквивалентно' if (x || y) do_that(); '. – dxiv

+0

@ dxiv Да, я это видел. Я чувствую себя идиотом за то, что не осознал этого раньше, ха. – ARich

0

Там есть проблема в вашем коде, потому что вы тестируете d до инициализации первого запуска цикла

Вот решение, которое я быстро придумал. Это не самый эффективный, но я считаю, что это просто понять и работает только с точки зрения переменной c.

#include <stdio.h> 

int main(void) 
{ 
    int c; 
    c = getchar(); 
    while(c != EOF) 
    { 
     putchar(c); 
     if(c == ' ') /* If the last character was a space */ 
     { 
      do /* Then keep getting new characters and overwrite */ 
      { 
       c = getchar(); 
      } while(c == ' '); /* as long as spaces keep coming */ 
     } 
     else 
      c = getchar(); /* if a space wasn't received, then just get the next */ 
    } 
    return 0; 
} 

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

Смежные вопросы