我是一名CS学生正致力于实施代码,但很难运行它。
请帮我解决这个L1解析表的问题。
可能是我在做一些愚蠢的语法错误。
我非常感谢你的回复。
干杯!
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
clrscr();
int i=0,j=0,k=0,m=0,n=0,o=0,o1=0,var=0,l=0,f=0,c=0,f1=0;
char str[30],str1[40]="E",temp[20],temp1[20],temp2[20],tt[20],t3[20];
strcpy(temp1,'\0');
strcpy(temp2,'\0');
char t[10];
char array[6][5][10] = {
"NT", "<id>","+","*",";",
"E", "Te","Error","Error","Error",
"e", "Error","+Te","Error","\0",
"T", "Vt","Error","Error","Error",
"t", "Error","\0","*Vt","\0",
"V", "<id>","Error","Error","Error"
};
cout << "\n\tLL(1) PARSER TABLE \n";
for(i=0;i<6;i++)
{
for(j=0;j<5;j++)
{
cout.setf(ios::right);
cout.width(10);
cout<<array[i][j];
}
cout<<endl;
}
cout << endl;
cout << "\n\tENTER THE STRING :";
gets(str);
if(str[strlen(str)-1] != ';')
{
cout << "END OF STRING MARKER SHOULD BE ';'";
getch();
exit(1);
}
cout << "\n\tCHECKING VALIDATION OF THE STRING ";
cout <<"\n\t" << str1;
i=0;
while(i<strlen(str))
{
again:
if(str[i] == ' ' && i<strlen(str))
{
cout << "\n\tSPACES IS NOT ALLOWED IN SOURSE STRING ";
getch();
exit(1);
}
temp[k]=str[i];
temp[k+1]='\0';
f1=0;
again1:
if(i>=strlen(str))
{
getch();
exit(1);
}
for(int l=1;l<=4;l++)
{
if(strcmp(temp,array[0][l])==0)
{
f1=1;
m=0,o=0,var=0,o1=0;
strcpy(temp1,'\0');
strcpy(temp2,'\0');
int len=strlen(str1);
while(m<strlen(str1) && m<strlen(str))
{
if(str1[m]==str[m])
{
var=m+1;
temp2[o1]=str1[m];
m++;
o1++;
}
else
{
if((m+1)<strlen(str1))
{
m++;
temp1[o]=str1[m];
o++;
}
else
m++;
}
}
temp2[o1] = '\0';
temp1[o] = '\0';
t[0] = str1[var];
t[1] = '\0';
for(n=1;n<=5;n++)
{
if(strcmp(array[n][0],t)==0)
break;
}
strcpy(str1,temp2);
strcat(str1,array[n][l]);
strcat(str1,temp1);
cout << "\n\t" <<str1;
getch();
if(strcmp(array[n][l],'\0')==0)
{
if(i==(strlen(str)-1))
{
int len=strlen(str1);
str1[len-1]='\0';
cout << "\n\t"<<str1;
cout << "\n\n\tENTERED STRING IS VALID";
getch();
exit(1);
}
strcpy(temp1,'\0');
strcpy(temp2,'\0');
strcpy(t,'\0');
goto again1;
}
if(strcmp(array[n][l],"Error")==0)
{
cout << "\n\tERROR IN YOUR SOURCE STRING";
getch();
exit(1);
}
strcpy(tt,'\0');
strcpy(tt,array[n][l]);
strcpy(t3,'\0');
f=0;
for(c=0;c<strlen(tt);c++)
{
t3[c]=tt[c];
t3[c+1]='\0';
if(strcmp(t3,temp)==0)
{
f=0;
break;
}
else
f=1;
}
if(f==0)
{
strcpy(temp,'\0');
strcpy(temp1,'\0');
strcpy(temp2,'\0');
strcpy(t,'\0');
i++;
k=0;
goto again;
}
else
{
strcpy(temp1,'\0');
strcpy(temp2,'\0');
strcpy(t,'\0');
goto again1;
}
}
}
i++;
k++;
}
if(f1==0)
cout << "\nENTERED STRING IS INVALID";
else
cout << "\n\n\tENTERED STRING IS VALID";
getch();
}
输出
LL(1) PARSER TABLE
NT <id> + * ;
E Te Error Error Error
e Error +Te Error
T Vt Error Error Error
t Error *Vt
V <id> Error Error Error
ENTER THE STRING :<id>+<id>*<id>;
CHECKING VALIDATION OF THE STRING
E
Te
Vte
<id>te
<id>e
<id>+Te
<id>+Vte
<id>+<id>te
<id>+<id>*Vte
<id>+<id>*<id>te
<id>+<id>*<id>e
<id>+<id>*<id>
ENTERED STRING IS VALID
[/Code]
答案 0 :(得分:4)
因此,您需要进行代码检查/代码审查。在这里:
C ++与C
你的程序看起来像是C,但你的问题标签是C ++。所以,我将从C ++的角度来看它。
将头文件切换为C ++:
#include <iostream>
#include <string>
#include <cstdlib>
请注意标题名称中没有“.h”后缀。
控制台I / O
conio.h
头文件是特定于编译器的。您没有提到您正在使用的编译器,因此我们很多人无法加载您的源代码并为您提供帮助。
clrscr()
功能不是必需的,通常,清除屏幕会删除以后可能需要的信息。顺便说一句,它不便携,因为并非所有平台都有屏幕。
void main
main
函数始终返回int
。
变量名称
C ++语言规范允许标识符中至少包含32个字符。允许使用更多字符,但只有前32个字符用于确定重复字符。
所以使用它们。单个字母只会减少您的打字时间。描述性名称允许其他人和您轻松了解代码的工作方式。你知道所有这些变量用于什么,而不阅读任何其他文档?
样式 - 每行一个声明
每行声明一个变量。易于维护,更易于阅读。
<强>空间吗
空间花费很少的构建时间并且不会影响执行速度。它们增加了清晰度,使用它们。
一般规则是变量和运算符之间的一个空间;逗号后面的一个空格。
角色阵列
不要使用它们,引起问题。由于您的问题标记为C ++,请改用std::string
。
一个字符的strcpy
不要将strcpy
用于一个字符,只需直接指定:
temp1[0] = '\0';
顺便说一句,strcpy
很危险,请改用strncpy;注意字母'n'。
<强> CONST 强>
用它。应该将未更改的内容声明为const
以防止错误并允许编译器发现此错误。此外,字符常量(a.k.a. literals)是常量,不能更改。
映射表
三个维度?真?
如何更容易理解,例如结构表:
struct Token_Entry
{
const char * token_text;
unsigned int token_ID;
};
const Token_Entry token_table[] =
{
{TOKEN_NT, "NT"},
{TOKEN_ID, "<id>"},
{TOKEN_PLUS, "+"},
// ...
};
const unsigned int Number_Of_Token_Entries =
sizeof(token_table) / sizeof(token_table[0]);
避免获取,这很危险。
无论数量多少,gets
都会读取输入。如果您分配5个插槽并且用户键入10个字母,您将超出缓冲区。很糟糕。
如果必须,请使用fgets
或切换到C ++并使用getline(std::string)
。
避免exit
功能
正确的方法是在return
函数中使用main
。这样可以正确清理变量。 exit
函数更危险一点。
没有Gotos和标签
阅读您喜欢的,正确的C ++文本中的循环。特别是break
和continue
个关键字。
每行一个作业
回车,换行和换行是免费的,使用它们。每行一个分配。它会使编译过程减慢微秒或纳秒;换句话说,处理行结束字符所需的时间可以忽略不计。
使用括号
如果您已经记住优先级表,则可能没有必要使用括号对逻辑语句进行分组,但它们使代码更具可读性:
while ((m < strlen(str1)) && (m < strlen(str)))
一次计算常数
例如,在分析循环期间,字符串的长度不会更改。所以将它存储到一个常量变量中:
const unsigned int length_str1 = str1.length(); // Since you will be using std::string.
const unsigned int length_str = strlen(str); // Or if you insist on C-style strings.
while ((m < length_str1) && (m < length_str))
无符号与有符号整数
我的一个小小的烦恼。如果值为负数,请使用int
(a.k.a。signed int
);否则使用unsigned int
。例如,文本长度不能为负数。长度为-5的字符串是什么样的?
评论您的代码
告诉读者你在做什么以及为什么。不要谈论分配变量。例如,为什么k
在循环结束时递增?为什么在一个部分中将temp
设置为null而不是另一个部分。 f1
变量用于什么?设置verbosity = maximum。
使用调试器
由于您没有对代码进行注释,因此使用单字母变量名称,您的代码将花费大量时间来理解。您可以通过使用调试程序来提供帮助。调试器允许您一次执行一行(a.k.a。单步执行),并打印或显示变量中的值。比在代码中的不同位置为变量添加print语句的古老艺术要快得多。
另外,使用调试器测试和评估程序比在网上发布更快,特别是在这里。