我正尝试如下向一组重复单词的文件添加空间。 基本上是状态机的作业。我已经在数组中为其创建了表。
再次,痛苦,熊,拍打,可以,被抓住,造成了我,更多,早晨,一周,去了,谁,你
在文本文件中的重复次数是
的再次面对熊跳动可能引起了我早些时候的动静
我不知道为什么它不会分开他们,这是怎么回事。
//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);
}
答案 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" );
// ...
}