C++ 分段故障核心转储

C++ 分段故障核心转储,c++,C++,我试图写一个lexer,当我试图在一个char数组中复制isdigit缓冲区值时,我得到了这个核心转储错误,尽管我对identifier做了同样的事情,但没有得到错误 #include<fstream> #include<iostream> #include<cctype> #include <cstring> #include<typeinfo> using namespace std; int isKeyword(char

我试图写一个lexer,当我试图在一个char数组中复制isdigit缓冲区值时,我得到了这个核心转储错误,尽管我对identifier做了同样的事情,但没有得到错误

#include<fstream>
#include<iostream>
#include<cctype>
#include <cstring>
#include<typeinfo>

using namespace std;



int isKeyword(char buffer[]){
    char keywords[22][10] = {"break","case","char","const","continue","default", "switch",
                            "do","double","else","float","for","if","int","long","return","short",
                            "sizeof","struct","void","while","main"};
    int i, flag = 0;
    
    for(i = 0; i < 22; ++i){
        if(strcmp(keywords[i], buffer) == 0)
        {
            flag = 1;
            break;
        }
    }
    
    return flag;
}
int isSymbol_Punct(char word)
{
    int flag = 0;
    char symbols_punct[] = {'<','>','!','+','-','*','/','%','=',';','(',')','{', '}','.'};
    for(int x= 0; x< 15; ++x)
    {
        if(word==symbols_punct[x])
           {
               flag = 1;
               break;
           }
            
    }
    return flag;
}

int main()
{
    char buffer[15],buffer1[15];
    char identifier[30][10];
    char number[30][10];
    memset(&identifier[0], '\0', sizeof(identifier));
    memset(&number[0], '\0', sizeof(number));
    char word;
    ifstream fin("program.txt");
    if(!fin.is_open())
    {
        cout<<"Error while opening the file"<<endl;
    }
    int i,k,j,l=0;
    while (!fin.eof())
    {
        word  = fin.get();

        if(isSymbol_Punct(word)==1)
        {
            cout<<"<"<<word<<", Symbol/Punctuation>"<<endl;
        }
       
        if(isalpha(word))
        {        
            buffer[j++] = word;
            // cout<<"buffer: "<<buffer<<endl;
        }
        else if((word == ' ' || word == '\n' || isSymbol_Punct(word)==1) && (j != 0))
        {
            buffer[j] = '\0';
            j = 0;
                            
            if(isKeyword(buffer) == 1)
                cout<<"<"<<buffer<<", keyword>"<<endl;
            else
                {
                cout<<"<"<<buffer<<", identifier>"<<endl;
                strcpy(identifier[i],buffer);
                i++;
                }
                    
        } 
           
        else if(isdigit(word))
        {
            buffer1[l++] = word;
            cout<<"buffer: "<<buffer1<<endl;
        }
        else if((word == ' ' || word == '\n' || isSymbol_Punct(word)==1) && (l != 0))
        {
            buffer1[l] = '\0';
            l = 0;
            cout<<"<"<<buffer1<<", number>"<<endl;
            // cout << "Type is: "<<typeid(buffer1).name() << endl;
            strcpy(number[k],buffer1);
            k++;
                        
        } 

    }
    cout<<"Identifier Table"<<endl;
    int z=0;
    while(strcmp(identifier[z],"\0")!=0) 
    {       
        cout <<z<<"\t\t"<< identifier[z]<<endl; 
        z++;
        
    }  
    // cout<<"Number Table"<<endl;
    // int y=0;
    // while(strcmp(number[y],"\0")!=0) 
    // {       
    //     cout <<y<<"\t\t"<< number[y]<<endl; 
    //     y++;
        
    // }   

    
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int isKeyword(字符缓冲区[]){
字符关键字[22][10]={“break”、“case”、“char”、“const”、“continue”、“default”、“switch”,
“do”、“double”、“else”、“float”、“for”、“if”、“int”、“long”、“return”、“short”,
“sizeof”、“struct”、“void”、“while”、“main”};
int i,flag=0;
对于(i=0;i<22;++i){
if(strcmp(关键字[i],缓冲区)==0)
{
flag=1;
打破
}
}
返回标志;
}
int isSymbol_点(字符字)
{
int标志=0;
字符符号_putch[]={'、'!'、'+'、'-'、'*'、'/'、'%'、'='、';'、'('、')'、'{'、'}'、'.'};
对于(int x=0;x<15;++x)
{
if(字==符号\u点[x])
{
flag=1;
打破
}
}
返回标志;
}
int main()
{
字符缓冲区[15],缓冲区1[15];
字符标识符[30][10];
字符编号[30][10];
memset(&identifier[0],'\0',sizeof(identifier));
memset(&number[0],'\0',sizeof(number));
字符词;
ifstream fin(“program.txt”);
如果(!fin.is_open())
{

CUT

一些一般的提示,可以帮助你完全避免你的撞车原因:设计:

    <> LI>因为这是C++,你应该尽可能地引用这里建立的C++数据类型和方案。我知道,在解析器/词法书写方面,不同的东西可能变得非常低,但是至少对于你想要在这里实现的东西,你应该非常感激。尽量避免使用简单的数组。例如,t8_t和/或std::string
  • 类似于点1,结果是:总是使用检查边界迭代!你不需要尝试比编译器的优化器更好,至少在这里不需要。一般来说,应该总是避免复制容器大小的信息。对于所述C++容器,此信息总是在数据源侧提供。如果n不可能在非常罕见的情况下(?),使用常量,直接在数据源定义/初始化中声明
  • 为变量指定有意义的名称,并尽可能将它们声明为其使用位置的本地变量
  • isXXX方法-至少您的方法应该返回布尔值。您永远不会返回0或1以外的值
  • 一个有点争议的个人建议是:使用早期返回和中止标准!即使在检查文件读取问题之后,您也可以继续
  • 尽量让你的函数保持智能和非样板!使用子例程完成不同的子任务
  • 尽量避免在全局范围内使用名称空间!即使没有像UnityBuilds这样的外来构建方案,对于规模更大的项目来说,这也很容易出错
  • 数组关键字和符号至少应该是静态常量。优化器将很容易识别这一点,但至少对您快速理解代码有帮助。尝试在此处使用类以可读、自适应、易于修改和可重用的方式组合属于一起的内容。请始终记住,几个月后,您可能想要理解自己的代码,甚至可能是其他开发人员
  • 原因如下(第56行):

    inti,k,j,l=0;
    
    您可能认为它将
    i
    j
    k
    l
    初始化为
    0
    ,但实际上它只将
    l
    初始化为
    0
    j
    k
    在这里声明,但没有初始化为任何内容。因此,它们包含随机垃圾,如果您将它们作为数组索引使用可能会超出所讨论数组的边界

    在这一点上,任何事情都可能发生,换句话说,这是。一个可能的结果,可能发生在你身上,就是你的程序试图访问操作系统没有分配给它的内存,在这一点上它崩溃了(a)

    为了具体说明我的意思,请考虑下面的程序:

    #包括
    无效打印变量(标准::字符串名称,int v)
    {
    
    STD:因为这是C++(不是C),为什么不使用<代码> STD::字符串< /代码>?更好地初始化所有的这个代码> int i,k,j,l=0;< /COD>只是为了避免错误访问,已经使用<代码> j<代码>这里>代码>缓冲区[j++ ]=单词,在初始化之前,你可以随意忽略:我建议开始更容易的项目而不是编写(C)词法,因为你似乎还不太精通C++。
    i: 32765
    j: -113535829
    k: 21934
    l: 0
    
    int i = 0;
    int j = 0;
    int k = 0;
    int l = 0;