2017-10-15 113 views
2

我目前遇到導航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?

我一直在使用的\r,\n\r\n等各種可能的嘗試,我總是收到大致相同的輸出。我也曾嘗試更改.txt文件的編碼。唯一的區別是(which is 14)。該數字會根據我如何對.txt文件進行編碼而波動。我也打開vim和:set list中的.txt文件來查看換行符。所以我知道他們在那裏。

這是學校的一個更大的項目的一部分只是代碼,我不是很用C++經驗呢。任何人都可以將我指向正確的方向嗎?我感覺有一次,我得到了這部分代碼,我認爲應該能夠完成這個項目。

注:txt文件僅僅是一個例子,所以不要放太多心思在我的數組或參數的大小在我的for循環。我有三倍檢查我的數組的大小,以確保沒有問題,我試圖讀入一個不存在的行。

+2

答案與「爲什麼是水溼」和「爲什麼是天藍色」是一樣的答案。 getline()'的全部目的是從輸入流中讀取下一行,並將其保存在不包含換行符*的'std :: string' *中。您將永遠不會在由'std :: getline()',***定義的***填充的字符串中獲得'\ n'。這就是'std :: getline()'的作用。 –

+0

也許你感到困惑,因爲你習慣於在C中使用'fgets()',它保持字符串中的換行符。但是C++'getline()'不會那樣做。 – Barmar

+0

18446744073709551615是2到64次方減1.這是最大的無符號64位整數。一個常見的方法是將-1饋入一個期望無符號64位整數的變量。在某些地方,你試圖從「名稱」的元素之一開始看,可能性很大。 – user4581301

回答

1

總是檢查find函數的返回值。例如:

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

如果\n未找到,則返回值爲string::npos(它可能是0xFFFFFFFF0xFFFFFFFFFFFFFFFF),這是無效的索引。嘗試訪問該索引會導致錯誤。

正如在評論中指出,names[r]不包含\n在這種情況下。 p始終爲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;

0

我不知道爲什麼你需要檢測換行符。如果您正在尋找提取姓名和號碼,你可以做以下

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

以瞭解你的文件的確切格式的優勢。該文件已經以完美和簡單的方式被操縱。另外,如果你不知道你的數據的大小。我鼓勵你通過一個固定大小的數組使用向量。