C程序,换行问题&标签彼此相邻

时间:2010-10-20 02:53:44

标签: c

这是我的原始代码:

#include <stdio.h>

#define IN  1   // inside a word
#define OUT 0   // outside a word

// program to print input one word per line

int main(void)
{
  int c, state;

  state = OUT;
  while ((c = getchar()) != EOF) {
    if (c == ' ' || c == '\n' || c == '\t') {
      state = OUT;
      printf("\n");
    }
    else if (state == OUT) {
      state = IN;
    }
    if (state == IN) {
      putchar(c);
    }
  }
  return 0;
}

但问题是如果有多个空格(空格)或多个标签彼此相邻,则会为两者打印换行符。所以我用一个变量(最后一个)来跟踪我的位置:

#include <stdio.h>

#define IN  1   // inside a word
#define OUT 0   // outside a word

// program to print input one word per line, corrected bug if there was
// more than one space between words to only print one \n

int main(void)
{
  int c, last, state;

  last = EOF;
  state = OUT;
  while ((c = getchar()) != EOF) {
    if (c == ' ' || c == '\n' || c == '\t') {
      if (last != c) {
        state = OUT;
        printf("\n");
      }
    }
    else if (state == OUT) {
      state = IN;
    }
    if (state == IN) {
      putchar(c);
    }
    last = c;
  }
  return 0;
}

解决了这个问题,除非现在彼此相邻[空白] [标签],否则会打印换行符。

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:6)

您原始代码的问题在于,您将输出每个空白字符的换行符。您只想在从单词转换为非单词时执行此操作:

变化:

if (c == ' ' || c == '\n' || c == '\t') {
    state = OUT;
    printf("\n");
}

为:

if (c == ' ' || c == '\n' || c == '\t') {
    if (state == IN) printf("\n");
    state = OUT;
}

事实上,我原先认为我建议的是对各州的列举:

enum eState {IN, OUT};
:
enum eState state = OUT;

但是,对于只有两个状态的简单有限状态机,您只需使用布尔值:

#include <stdio.h>

#define FALSE (1==0)
#define TRUE  (1==1)
// Or: enum eBoolean {FALSE = 0, TRUE = 1};

int main (void) {
    int ch;
    int inWord = FALSE;     // Or: enum eBoolean inWord = FALSE;

    // Process every character.
    while ((ch = getchar()) != EOF) {
        // Check for whitespace.
        if (ch == ' ' || ch == '\n' || ch == '\t') {
            // Check if transitioning nonwhite to white.
            if (inWord) {
                printf("\n");
            }

            // Mark white no matter what.
            inWord = FALSE;
        } else {
            // Mark non whitespace.
            inWord = TRUE;
        }

        // If not whitespace, output character.
        if (inWord) {
            putchar(ch);
        }
    }
    return 0;
}

答案 1 :(得分:2)

正如paxdiablo所说,你的程序是典型的有限状态自动机(FSA)。您必须在从状态OUT到状态IN的转换中打印一个新行,然后才能打印。

以下是我编写此类代码的方法。在这种特殊情况下,它可以更简单,但结构很有趣,因为它是典型的,适用于任何FSA。你有一个很大的外部开关,每个状态都有一个外壳。在每种情况下,您将获得另一个实现转换的转换,此处转换事件是输入字符。剩下要做的就是考虑每次过渡应该做些什么。这种结构也非常有效。

你应该牢记这一点,这在你的预思考程序结构的工具包中真的很常见。我当然这样做。

#include <stdio.h>

#define IN  1   // inside a word
#define OUT 0   // outside a word

// program to print input one word per line

int main(void)
{
  int c, state;

  state = OUT;
  while ((c = getchar()) != EOF) {
    switch (state){
    case OUT:
        switch (c){
        case ' ': case '\n': case '\t':
        break;
        default:
            putchar(c);
            state = IN;
        }
    break;
    case IN:
        switch (c){
        case ' ': case '\n': case '\t':
            putchar('\n');
            state = OUT;
        break;
        default:
            putchar(c);
        }
    break;
    }        
  }
  return 0;
}

答案 2 :(得分:1)

查看您何时签入第二个代码

if (last != c) {

您没有检查所有条件。last可能等于空格,制表符或新行。在所有这些情况下,它不应该打印新行。让我们将这三个特殊字符的集合称为X

现在,在打印新行时,您需要确保打印的last字符无法设置X。但你检查last!=current。现在当前可以是空格,制表符或新行。但这只是一个价值。它不符合我们的需要,我们的目的。

所以改为用

替换它
 if (last != ' ' && last != '\n' && last != '\t' ) {

您可以在此处查看代码:

#include <stdio.h>

#define IN  1                   // inside a word
#define OUT 0                   // outside a word

// program to print input one word per line, corrected bug if there was
// more than one space between words to only print one \n

int main(void)
{
    int c, last, state;

    last = 0;  // We need it to make sure that a newline is not printed in case first
               // char is space, tab or new line.
    state = OUT;
    while ((c = getchar()) != EOF) {
        if (c == ' ' || c == '\n' || c == '\t') {
            // if (last != c)
            if (last != ' ' && last != '\n' && last != '\t' && last != 0 )
            {
                state = OUT;
                printf("\n");
            }
        } else if (state == OUT) {
            state = IN;
        }
        if (state == IN) {
            putchar(c);
        }
        last = c;
    }
    return 0;
}

修改
修复了paxdiablo在评论中指出的错误。

答案 3 :(得分:0)

#include<stdio.h>

#define OFF 0
#define ON 1
main()
{
  int c,state=ON;
  while((c=getchar())!=EOF)
    {
      if(c=='\n'||c==' '||c=='\t')
       {
         if(state==OFF)putchar('\n');
         state=ON;
       }
      else if(state==ON)
       {
         putchar(c);
         state=OFF;
       }
      else if(state==OFF)
       {
         putchar(c);
       }
    }
}

这是解决问题的一种方法,上面使用过:

Where, STE=Space, tab or enter.

<STE><WORD>---->TYPE<WORD>
<STE><STE>----->DO NOTHING
<WORD><SPACE>-->TYPE<WORD><ENTER/NEWLINE>
<WORD><WORD>--->TYPE<WORD>

如上图所示,您可以替换ON和OFF。