分段错误:从文件访问 csv 记录时核心转储

Posted

技术标签:

【中文标题】分段错误:从文件访问 csv 记录时核心转储【英文标题】:segmentation fault: core dumped while accesing csv records from a file 【发布时间】:2019-11-06 21:25:17 【问题描述】:

我正在研究一个大学 c++ 项目并创建一个函数来解析 csv 文件并读取存储在其中的记录。但每次我使用该功能时都会出错

csv 文件示例:

9138119,913811921297,Shivam,J,Jha,3811921297,sj@g.c,DEL,sji2ns,100,sj@bank

我尝试使用vector的reserve()函数

void person::login()
   bool found = false;

   fstream fin;
   fin.open("acc_info.csv", ios:: in);

   string CRN, Password;
   cout << "\nEnter CRN: ";
   getline(cin, CRN);

   cout << "\nEnter password :";
   getline(cin, Password);

   vector<string> record;
   string line, word, temp;

   if(fin)
      while(fin >> temp)
         record.clear();
         getline(fin, line);
         stringstream s(line);

         while(getline(s, word, ','))
            record.push_back(word);
         

         if(CRN == record[0] && Password == record[10])
            found = true;
            cout << "\nLogin successfull!\n\n";
            break;
         
      
      if(!found)
         cout << "\nWrong CRN and password entered\n\n";
      
   
   else
      cout << "\nTechnical fault occured.. try again after some time!!\n\n";
   

应该与用户输入的CRN和密码匹配,并提供是否成功登录

这是人物类:

class person 

    public:
        void welcome();
        void show_account();
        void after_user_choice(int);
        void create_acc();
        void login();
        void accounts();
        void deposit();
        void cards();
        void loans();
        void insurance();
        void investments();
        int check(int, int, int);
        bool d;
        string retacno() const
            return acc_no;
        

        ~person();


        int x=5;

    protected:
        void show_acc_info(const unsigned long int);


        string firstname , middlename , lastname , address  , pan_no , fname ;
        string password, mobile_no ;
        string acc_no, crn, balance= "100";
        string email_id;
        string line, word, temp;

    private:
        string usr ; 
        string pswd;


;

这是我如何从用户那里获取输入以写入 CSV 文件:

void person::create_acc()

     ofstream xl("acc_info.csv" , ios::app );
         cout<<"ENTER FIRST NAME\n";
     getline(cin,firstname);

     cout<<"ENTER MIDDLE NAME \n";
     getline(cin,middlename);

     cout<<"ENTER LAST NAME: "<<endl;
     getline(cin,lastname);  

     cout<<"ENTER FATHER'S NAME: "<<endl;
     getline(cin,fname);  

     cout<<"ENTER YOUR EMAIL_ID: ";
     getline(cin,email_id);

     cout<<"ENTER PAN CARD NUMBER: "<<endl;
     getline(cin,pan_no);

     cout<<"ENTER YOUR RESIDENTIAL ADDRESS: "<<endl;
     getline(cin,address);  

     cout<<"ENTER YOUR MOBILE NUMBER: "<<endl;
     getline(cin, mobile_no);

    acc_no = to_string(910000000000 + stol(mobile_no, nullptr, 10)); //generating acc no;

    crn = to_string(int(stol(acc_no)/100000)); //generating crn;
     string repswrd;
     bool z;

    do

     cout<<"ENTER PASSWORD FOR YOUR CRN(USER_ACC): ";
     getline(cin,password);    

     cout<<"RE-ENTER YOUR PASSWORD: ";
     getline(cin,repswrd);

     if(!(password.compare(repswrd)))

           cout<<"Passwords matched succesfully!"<<endl<<endl;
           z = true;
           
     else

          cout<<"Passwords didn't match!!! Try again\n"<<endl;
          z = false;
               

         while(!z);

      cout<<"\n\nAccount created successfully\n\n";

      cout << "Customer Satisfaction is our main"
           << "priority, so we have deposited a "
           << "sum of Rs. 100 into your bank a/c"
           << endl << endl;

     xl<<crn<<","
      << acc_no<< ","
     << firstname << "," 
     << middlename << "," 
     << lastname<< ","
     << mobile_no<< ","
     <<email_id<<","
     << address<< ","
     <<pan_no<<","
     <<balance << ","
     << password<< "\n";

     xl.close();

     cout<<endl;  

     

【问题讨论】:

At ` if(CRN == record[0] && Password == record[10])` 你如何确定该记录有 10 个条目? if(CRN == record[0] &amp;&amp; Password == record[10]) -- 将其更改为 record.at(0)record.at(10)。如果没有这样的记录,你会得到一个out_of_range 异常抛出。 记录有 11 个条目 -- 不,请验证向量是否有这些条目。永远不要编写假设这些事情的代码。另外,请不要图像。将数据放在问题中,最好放在代码中。 进入temp的所有内容 @ShivamJha 仍然不是minimal reproducible example。 minimal reproducible example 的真正美妙之处在于它是一种非常有用的调试技术。如果不沿途发现并修复错误,就很难制作一个。虽然不断地询问可能会让我们显得迂腐,但如果您在提出问题之前创建了minimal reproducible example,那么您就不必提出问题了。 【参考方案1】:

您的while(fin &gt;&gt; temp) 读取该行并将其放入temp 但您不使用它,因此line 将为空,即使文件中紧跟着另一个有效行。 &gt;&gt; 将换行符留在流中,这是后面 std::getline 将读取的唯一内容。只要文件中的行不包含会使&gt;&gt; 拆分它的字符(如空白字符),它就会始终读取空行。

考虑只使用std::getline 跳过格式化输入并在索引之前实际检查您是否获得了有效记录:

    if(fin) 
        while(std::getline(fin, line)) 
            record.clear();
            stringstream s(line);

            while(std::getline(s, word, ',')) 
                record.push_back(word);
            

            // check that you've got a valid record
            if(record.size() != 11)
                throw std::runtime_error("invalid record size (" +
                                         std::to_string(record.size()) + ")");

            if(CRN == record[0] && Password == record[10]) 
                found = true;
                cout << "\nLogin successful!\n\n";
                break;
            
        
        if(!found) 
            cout << "\nWrong CRN and password entered\n\n";
        
    

【讨论】:

非常感谢 Ted Lyngmo。我一直试图找到这个问题几个小时,你救了我! 是的,伙计,它确实帮助了我很多……事实上,你拯救了我的项目!很高兴找到你的男人! :) 大声笑!现在我知道如何接受答案了!!再次感谢您!!! @ShivamJha 调试提示:添加一些额外的打印语句以确保您正在阅读您认为正在阅读的内容。 while(getline(s, word, ',')) record.push_back(word); cout &lt;&lt; word &lt;&lt; endl; 会很快表明您没有阅读任何内容。之后要查看的下一个合乎逻辑的事情是cout &lt;&lt; temp &lt;&lt; endl;,这将解开谜团。

以上是关于分段错误:从文件访问 csv 记录时核心转储的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中转储的分段故障核心

访问共享进程内存时出现分段错误(核心转储)

尝试执行茎文件时出现分段错误(核心转储)

无法从 cpp 代码运行 image_transport:“分段错误(核心转储)”

在命名管道中获取分段错误(核心转储)错误

段错误(核心已转储)的原因