在单词之间添加空格

时间:2019-12-15 06:57:01

标签: c++ visual-c++ state-machine

我正尝试如下向一组重复单词的文件添加空间。 基本上是状态机的作业。我已经在数组中为其创建了表。

再次,痛苦,熊,拍打,可以,被抓住,造成了我,更多,早晨,一周,去了,谁,你

在文本文件中的重复次数是

再次面对熊跳动可能引起了我早些时候的动静

我不知道为什么它不会分开他们,这是怎么回事。

//A state machine to parse a sequence of known strings.

#include <iostream>
#include "stdlib.h"

using namespace std;

  int counter;
// State Table for:
//      again, agony, bear, beat, can, caught, caused, me, more, morning, week, went, who, you
char NextState[27][31] = {
    // 0  1  2  3  4  5
1,  -1, 3,  -1, -1, -1, -1, -1, 9,  -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
7,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 8,  -1, -1, -1, -1, -1, -1, -1, 16, -1, 0,  -1, 0,  -1, -1, -1, -1, 25, 26, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 2,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 4,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 0,  6,  -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, -1, -1, 27, -1, -1, -1, -1, -1,
-1, -1, 5,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  30, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1, 0,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30, -1, -1, -1, -1, -1, 0,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

    //7, -1, 0, -1, -1, -1,  //1

};

//a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
char map[26] = { 0,1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };

char state = 0;

void process(char ch)
{
    // print current char
    cout << ch;

    // move to next state
    state = NextState[map[ch - 'a']][state];

    // output a space if we are back to initial state
    if (!state) {
      cout << " ";
      counter++;
    }

}

int main(void)
{

    char ch;
    FILE * f;

    // open file for text input
    if (!(f = fopen("againTHRUyou.txt", "r"))) {
        printf("Cannot open file\n");
        exit(1);
    }

    // read and display one byte at a time
    while ((ch = fgetc(f)) != EOF)
    {
        process(ch);


    }

    cout<<"The count is " << counter <<endl;

    fclose(f);
}

2 个答案:

答案 0 :(得分:0)

因为这似乎是您的大学作业,所以不要指望这里提供完整的答案。我会给你一些提示。

考虑以下代码行:

state = NextState[map[ch - 'a']][state];

您对代码运行时的假设是什么?

  • 第一个进入NextState的索引的预期范围是多少?实际参数是否始终在预期范围内?
  • 进入NextState的第二个索引的预期范围是多少?实际参数是否始终在预期范围内?

回答这两个问题将使您走上正确的道路。 顺便说一句,请熟悉调试器和断言https://en.cppreference.com/w/cpp/error/assert

另一个提示是,您的代码在大多数情况下运行良好,并且有时仅会失败。在这种情况下,最好显示程序的状态。在上述代码行的前面和后面添加这样的“ cout-debbugging”行,以查看您的程序如何更改状态。为此,请将输入文件缩短为大约100个字符。

答案 1 :(得分:0)

我没有时间仔细检查您的程序。以下是一些观察结果:

  • 一个问题是您在状态/事件表中犯了一些错误。例如,"morning"中最后一个字母之后的状态是-1 而不是0

    -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0/*-1*/, 0, -1, -1, -1, -1, -1, -1, -1,

  • 混合c和c ++样式。使用ifstream代替FILE

    #include <fstream>
    //...
    ifstream is{ "c:\\temp\\test.txt" }; // opens the file; the file is automatically closed when the object goes out of scope
    if ( !is )
      return -1; // could not open
    
    char c;
    while ( is.get( c ) ) // get characters until the eof is reached or an error is encountered
    {
      //...
    }
    
  • 您不会测试无效状态(-1)。由于这是一个教学应用程序,因此使我相信输入始终有效,因此您可以忽略此输入。一旦到达单词的末尾,您必须返回到状态零,因此将表初始化为0 (状态为零)而不是-1是有意义的。

  • 手动填充状态表既乏味又容易出错。您必须实现函数,该函数从单词开始生成表。。例如(未测试):

    enum
    {
      max_state = 50,
      max_event = 26
    };
    
    int table[ max_state ][ max_event ];
    int new_state = 0;
    
    int as_event( char c )
    {
      return c - 'a';
    }
    
    void add( const char* word )
    {
      const char* p = word;
      int state = 0;
      while ( *p )
      {
        int event = as_event( *p++ );
        int next_state = table[ state ][ event ];
        if ( next_state != 0 ) // path already exists: just use it
        {
          state = next_state;
          continue;
        }
        else // new path
        {
          next_state = ++new_state;
          table[ state ][ event ] = next_state;
          state = next_state;
        }
      }
    }
    
    void init()
    {
      memset( table, 0, sizeof table );
      add( "again" );
      add( "agony" );
      add( "bear" );
      // ...
    }