程序找不到回车或换行符。退货超出范围

时间:2017-10-15 02:40:36

标签: c++ vim newline carriage-return

我目前在导航txt文件时遇到问题,因此我可以将其读入数组。程序编译很好,但是当我运行它时返回终端:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::erase: __pos (which is 18446744073709551615) > this->size() (which is 14)
Aborted (core dumped)

以下是代码:

#include<cstdlib>
#include<cmath>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<iostream>
#include<string>
#include<cstring>
#include<cassert>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<locale.h>
#include<stdio.h>
#include<functional>
#include<math.h>

using namespace std;

int main(int argc, char**argv)
{
    int r=0;
    int p=0;
    int c=0;
    string names[20];
    double scores[20][10];

    ifstream infile;
    infile.open("./bowlers.txt");

    for(int r=1;r<=10;r++)
    {
        getline(infile,names[r]);

        p=names[r].find_first_of("\n") ;
        names[r].erase(p,2);

        for(c=1;c<=5;c++)
        {
        infile>>scores[r][c];
        }
        infile.ignore(100,'\n');
    }
    infile.close();

    for(int r=1;r<=10;r++)
    {
        cout<<fixed<<setprecision(2)<<endl;
        cout<<names[r]<<endl;

    }  

    return 0;
}

我正在使用的txt文件如下所示:

charles
123
321
222
rose
432
515
123
Greg
123
553
136

以下是我在研究这个问题时发现的:

  1. Unix和Windows对EOL的处理方式不同。
  2. 我的部分问题是:

        p=names[r].find_first_of('\n') ;
        names[r].erase(p,2);
    

    导致问题,因为永远找不到\n它返回-1,而你不能.erase -1?

  3. 我尝试过使用\r, \n\r\n等所有可能的方法,而且我总是收到大致相同的输出。我也尝试过更改.txt文件的编码。唯一的区别在于(which is 14)。该数字将根据我对.txt文件的编码方式而波动。此外,我已在vim和:set list中打开.txt文件以查看换行符。所以我知道他们在那里。

    这只是一个更大的学校项目的部分代码,我对c ++还不是很有经验。谁能指出我正确的方向?我觉得一旦我得到了我的代码部分,我就应该能够完成这个项目。

    注意:txt文件只是一个例子,所以不要过多考虑我的数组的大小或我的for循环中的参数。我已经三次检查了我的数组的大小,以确保我没有问题尝试读入不存在的行。

2 个答案:

答案 0 :(得分:1)

始终检查查找函数的值的返回值。例如:

size_t p = names[r].find_first_of("\n");
if (p != string::npos)
    names[r].erase(p, 2);

如果找不到\n,则返回值为string::npos(可能是0xFFFFFFFF0xFFFFFFFFFFFFFFFF),这是无效索引。试图访问该索引会导致错误。

正如评论中所述,names[r]在这种情况下不包含\np始终为string::npos,此操作不是必需的。

for(c=1;c<=5;c++)
{
infile>>scores[r][c];
}

每个名称下面只有3个整数,所以你应该数到3而不是5.这个代码应该有效:

for(int r = 1; r <= 10; r++)
{
    getline(infile, names[r]);
    for(int c = 1; c <= 3; c++)
        infile >> scores[r][c];
    infile.ignore(100, '\n');
}

或者您可以添加更多错误检查,例如if (!(infile >> scores[r][c])) break;

答案 1 :(得分:0)

我不知道你为什么需要检测换行符。如果您要提取名称和数字,可以执行以下操作

string word;
int i(0); 
while ( infile >> word ){
    if(!(i%4)){
        //name 
        std::cout << word << endl;
    }else{
        //number
    }
    ++i;
}

充分了解文件的确切格式。该文件已经是一种完美而简单的操作方式。此外,如果您不知道数据的大小。我鼓励你在固定大小的数组上使用向量。