这是我坚持的实验室任务。
我需要接受这个语法(ab)*b
,这基本上意味着任何数量的“ab”并以b结尾。
我已经编写了这段代码但不知何故,它只检查前2个字母。
#include <iostream.h>
#include <conio.h>
#include <string.h>
enum track {true, false};
void main()
{
clrscr();
char*str;
enum track track_pos, track_pos_2;
cout<<"enter the string: ";
cin>>str;
int len=strlen(str);
cout<<"length of the string is "<<len;
getch();
int i;
for(i=0;i<len; i++)
{
++str;
cout<<"loop"<<i;
if(*str=='a' && i%2==0)
{
cout<<"\nchecking a...";
track_pos=true;
cout<<"\na.check";
++str;
if (*str=='b')
{
cout<<"\nchecking b...";
track_pos=true;
cout<<"\nb.check";
}
else{
track_pos=false;
cout<<"\nb.uncheck";
}
}
}
if(*str=='b')
track_pos_2=true;
else
track_pos_2=false;
if(track_pos==true && track_pos_2==true)
cout<<"\nThe string is accpeted.";
else
cout<<"\nThe string is rejected.";
getch();
cout<<"\n\nDo you want to continue (Y/N)? ";
char ch;
cin>>ch;
if(ch=='y' || ch=='Y')
main();
}
答案 0 :(得分:12)
我会后悔这一点,但每次看到这个问题,我都会看到你的代码出现了其他问题。这是逐行的。我可能错过了很多。
此标头的正确名称是“iostream”,而不是“iostream.h” - 不推荐使用“.h”版本。类似地,在现代C ++中使用“string”而不是“string.h”,并使用现代STL字符串类。
#include <iostream.h>
#include <conio.h>
#include <string.h>
正如所指出的,不要这样做。您已重新定义标准bool
类型,以使其与标准类型具有相反的值。我甚至都不知道这是合法的。
enum track {true, false};
main
函数的返回值为int
,而不是void
。
void main()
{
clrscr();
你知道缓冲区溢出是什么吗?您已将str
定义为此处的指针,没有分配的内存,稍后您将写入该未定义的内存位。这是未定义的行为,您几乎可以保证崩溃。我建议你应该将str
定义为std::string
- 这样可以很好地避免缓冲区溢出,并且它有许多可以在程序中使用的有用方法。
char*str;
enum track track_pos, track_pos_2;
cout<<"enter the string: ";
这是缓冲区溢出。你在写谁知道记忆的哪个方面。
cin>>str;
如果str
是std::string
- 你会size_t len=str.length()
;
int len=strlen(str);
cout<<"length of the string is "<<len;
将这样的控制台IO功能与iostreams功能混合起来可能不是一个好主意 - 有一些缓冲问题会导致困难。
getch();
在循环体中声明i
,因为你没有再使用它。像这样:
for (int i=0; i<len; i++) etc...
int i;
for(i=0;i<len; i++)
{
不要使用poiter算法,因为您要跟踪i
中当前字符的索引,只需使用它并将str
视为数组。这样,您就不必始终str
与i
保持同步。顺便说一句,这就是你报告的错误的原因。
++str;
cout<<"loop"<<i;
您应该将其更改为:
if (str[i]=='a' && i%2==0)
(顺便说一下,即使str
是std::string
也是如此,与指针算术版本不同。)
if(*str=='a' && i%2==0)
{
你真的应该在某些时候辍学,如果你发现字符串不匹配,那么就没有任何意义继续到字符串的末尾。
cout<<"\nchecking a...";
我不喜欢这样的状态标志 - 由于这些标志的激增,你的代码部分难以理解,你无法跟踪正确的行为。名称track_pos
不是助记符,如果不详细研究代码,很难弄清楚其意味着什么。
我建议你在for循环体内重构你的代码来调用一个函数,其目的只是匹配一组“ab” - 如果这样做,这个函数可以返回true,并且如果没有,则为假。
track_pos=true;
cout<<"\na.check";
请注意,由于我们正在处理之前提到的缓冲区溢出,因此您将迭代未定义的内存。另请注意,您未在此处增加i
。
++str;
if (*str=='b')
{
cout<<"\nchecking b...";
track_pos=true;
cout<<"\nb.check";
}
else{
track_pos=false;
cout<<"\nb.uncheck";
}
}
}
当我们到达这里时,根据你的for循环,我们迭代了整个字符串,所以我们必须看过字符串的末尾(甚至忽略缓冲区溢出),所以这个测试不可能成功。简而言之,你的for循环必须走得太远。
if(*str=='b')
track_pos_2=true;
else
track_pos_2=false;
if(track_pos==true && track_pos_2==true)
我应该提一下拼写错误吗?
cout<<"\nThe string is accpeted.";
else
cout<<"\nThe string is rejected.";
getch();
cout<<"\n\nDo you want to continue (Y/N)? ";
char ch;
cin>>ch;
如果将代码重构为适当的子例程,您会发现程序的结构可以自行处理。请注意,递归调用main
并非严格违法,但它有点奇怪并且有一个明显的漏洞,如果程序永远不会退出,将导致最终的堆栈溢出。
if(ch=='y' || ch=='Y')
main();
}
答案 1 :(得分:6)
实现一个简单的状态机。它有以下几种状态:
然后你需要一个像这样的函数:
int nextState(int currentState, char inputChar) {
if (currentState == 0 && inputChar == 'a') return 1; // handled string is "a"
if (currentState == 0 && inputChar == 'b') return 3; // handled string is "b"
if (currentState == 1 && inputChar == 'b') return 2; // handled string is "ab", or "abab", or ...
if (currentState == 2 && inputChar == 'a') return 1; // handled string is "aba", or "ababa", or ...
if (currentState == 2 && inputChar == 'b') return 3; // handled string is "abb", or "ababb", or ...
return -1;
}
在输入字符上迭代此“状态机”,从状态0开始,如果最终处于状态3,则输入有效。
int isValid(char* inputString) {
int state = 0;
for(int i=0; i<str_len(inputString); i++) {
state = nextState(state, inputString[i]);
}
return (state == 3);
}
答案 2 :(得分:4)
您的代码出了问题:
#include <iostream.h>
应该是:
#include <iostream>
以下是非标准(非常旧)的标题:
#include <conio.h>
以下是非法的 - 真假都是保留字。
enum track {true, false};
在C和C ++中,main必须返回一个int:
void main()
非标准功能:
clrscr();
没有为此指针分配内存:
char*str;
然后在这里使用 - 结果未定义的行为:
cin>>str;
非法打电话给主:
main();
我怀疑你使用的是一个非常陈旧和过时的C ++编译器。你应该用像MinGW这样的东西替换它。
答案 3 :(得分:1)
不要这样做!
enum track {true, false};
这里你的真等于0而假等于1!当您稍后分配track_pos时,您可能会得到错误的值! (因为将bool转换为int时,true转换为1,false转换为0。)
但这只是猜测。也许这是重要的事情。