2013-03-08 4 views
0

이것은 K & R 연습입니다. 그것은 하나 이상의 공간을 두 배 이상으로 대체해야합니다. 대신 입력, 공간 및 모든 것을 정확하게 반영합니다. 또한, 다른 연습에서 EOF (ctrl-d)를 사용하고이 연습을 위해 RETURN (Enter)을 사용해야하는 이유는 무엇입니까? (I 우분투를 실행하지만 맥에서 SSH를 사용하고 있습니다.)왜 C에서 이중 공백을 제거하지 않습니까? K & R의 getchar() 연습 중 하나입니다.

#include <stdio.h> 

main() 
{ 

    int c; 

    c = getchar(); 

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

사용 EOF 검사 진리 값으로 작업 할 때 파일 스트림 –

+1

에서 문자를 읽고 있다면, 당신은 사용해야합니다 || 및 | 대신 && 및 &. | & 연산자는 비트 단위 연산입니다. –

답변

3

도시 니펫 갖는다 적어도 하나의 논리 오류 및 논리적 부울 연산자 및 비트 부울 사이의 혼란에 의한 다른 오류 연산자.

논리 오류 :

c != EOF에 두 번째 테스트는 OR-ED C가없는 경우이 OR-ED 테스트에 도착하기 때문에 문자가 공간 (c != ' ') ... 없는에 시험에 EOF (이것은 while의 제어 조건 인)의 OR-ED 시험은 항상 사실이다 운영자의 실수의

... 
    while (c != EOF) 
    { 
     // This test always true regardless of c being a space or not 
     // Also it should be a logical OR, if at all. The bitwise OR will produce 
     // odd results if you are not sure of the bit patterns of the operands. 
     while (c != EOF | c != ' ') 
     { 
      putchar(c); 
      c = getchar(); 
     } 
    ... 

혼란! 이 경우, 당신 bitwise boolean 연산자 (|&)가 아닌 논리 OR (또는 실제로는 논리 AND) 연산자 (즉, ||&&)를 사용해야합니다.

일반적으로 논리 연산자를 사용하여 부울 조건을 자주 사용하므로 변수의 비트 패턴을 효과적으로 처리해야 할 때 비트 연산자 만 필요합니다 (예 : 일부 비트를 마스크하거나 이들을 설정하도록 강요하십시오.)

이제는 "있는 그대로"라는 코드의 문제를 해결하면서 공백이 다른 문자와 마찬가지로 처리 된 이유를 설명했습니다. K & R 연습의 목표 : 여러 공백의 시퀀스를 단 하나의 공백으로 대체한다는 논리는 명백하게 잘못되었습니다. 차라리 멀리 여기를 포기하지 싶지만, 몇 가지 힌트 :

  • 는 이전 문자가
  • 이 하나를 사용 공간을이었다 여부를 나타내는 "상태"변수를 소개 루프 (동안 EOF 또는 무엇이든하지 동안 종료 상태 조건)
  • 루프 내에서 체계적으로 상태 변수가 출력되지 않으면 문자를 출력합니다.
  • 조건부로 현재 문자를 출력 한 후 상태 문자를 업데이트하십시오. 일반적인 힌트로

, 그것은 종종 (항상 하지만)는 "code smell"(코드/로직을 재 작업해야한다는 즉, 표시)이 (끝 루프 상태를 반복 할 필요가있다 s) 루프 내에서 및/또는 여러 입력 지점에서 읽은 부분을 입력하십시오 (여기에 복수 getchar())

+0

고마워요 - 권장 사항대로 다시 작성하면 작동합니다. K & R은 설명에 드문 것 같습니다. 거의 '남자'파일과 같습니다. –

1

코드에 두 가지 문제점이 있습니다.

첫 번째는 논리 OR 연산자 (||)를 사용하려고하지만 비트 단위 OR (|)을 사용하고 있다는 것입니다.두 번째는 논리 오히려 어쨌든, 논리적 OR보다 사용되어야한다는 것이다 : 얻고 박았 및 값의 확인이 많이 있어요

while (c != EOF) 
    { 
     if (c == ' ') 
     { 
      putchar(c); 
      while(c == ' ' && c != EOF) 
      c = getchar(); 
     } 
     else 
     { 
      if (c != EOF) 
      putchar(c); 
      c = getchar(); 
     } 
    } 
1

이 루프를보십시오. 탭 청소도하는 클리너가 있습니다.

void main (void) 
{ 
int F_space=F_tab=0; // Flags for special chars 
char ch; 
do 
    { 
    ch = getchar(); 

    // test for special characters 
    switch (ch) 
     { 
     case ' ': // space 
      F_space = 1; 
      continue; 

     case '\t': // tab 
      F_tab = 1; 
      continue; 

     default: // anything else 
      // output a space if necessary 
      if (F_space || F_tab) { 
       F_space = F_tab = 0; // clear flags 
       putchar (' '); 
      } 
      break; 
     } 

    // output the character 
    putchar (ch); 
    break; 
    } 
while (ch != EOF); 
0

:

while (c != EOF && c != ' ')