2017-10-15 20 views
2

現在、txtファイルを移動する際に問題が発生しているため、配列に読み込むことができます。プログラムはうまくコンパイルが、私は実行したときには、端末に返します。このようなキャリッジリターンまたは改行が見つかりません。戻り値範囲外

#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 
ここ
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) 

コードです

これは私がこの問題を自分自身で調べたところで分かったことです:

  1. EOLは、UnixおよびWindowsによって異なる方法で処理されます。 \nが、それは-1を返したことはありませんので、
    p=names[r].find_first_of('\n') ; 
        names[r].erase(p,2); 
    

    が問題を引き起こしている、とすることはできません.erase -1:私の問題の
  2. 一部は、ということでしょうか?

私は\r,\n\r\n、などの考えられるあらゆるを使用してみましたが、私はいつも大体同じ出力を受け取ります。私も.txtファイルのエンコーディングを変更しようとしました。唯一の違いは(which is 14)です。番号は.txtファイルをどのようにエンコードするかによって変動します。また、vimで.txtファイルを開き、改行文字を表示するには:set listを開いています。だから私は彼らがそこにいることを知っている。

これは、学校向けのはるかに大きなプロジェクトの一部のコードであり、私はまだC++にはあまり経験がありません。誰かが私を正しい方向に向けることができますか?私は一度私は私のコードのこの部分は、私がプロジェクトを完了することができることがわかったように感じる。

注:txtファイルは単なる例であり、私のforループの配列やパラメータのサイズをあまり考慮しないでください。私は配列が存在しない行を読み込もうとする際に問題がないことを確認するために配列のサイズを3倍にチェックしました。

+2

ここでの答えは、「なぜ水が濡れているのか」と「なぜ空が青いのですか」と同じ答えです。 'getline()'の目的は、入力ストリームから次の行を読み込み、改行*を除いた 'std :: string' *に保存することです。 'std :: getline()'によって定義された文字列に '\ n'を得ることは決してありません。これが 'std :: getline()'の働きです。 –

+0

Cで 'fgets()'に慣れているので混乱しているかもしれません。これは文字列に改行を保持します。しかし、C++の 'getline()'はそれをしません。 – Barmar

+0

18446744073709551615は2から64乗-1を引いたものです。これは符号なし64ビット整数の最大値です。それを得るための一般的な方法は、符号なし64ビット整数を期待する変数に-1を与えることです。あなたは '名前'の要素の1つの始まりを見ようとしているところでは、良いことがあります。 – user4581301

答えて

1

find関数の戻り値を常にチェックします。例:\nが見つからない場合

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

、戻り値が無効なインデックスである(それは0xFFFFFFFFまたは0xFFFFFFFFFFFFFFFFすることができる)string::nposです。その索引にアクセスしようとすると、エラーが発生します。

コメントに記載されているように、names[r]には\nが含まれていません。 pは常にstring::nposであり、この操作は必須ではありません。あなたがいない5.このコードは動作するはずです、3まで数える必要がありますので、

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

あなただけの、それぞれの名の下に3つの整数があります。

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; 
} 

ファイルの形式を正確に把握して活用してください。このファイルは既に完璧で簡単に操作できます。また、データのサイズがわからない場合もあります。私はあなたが固定サイズの配列の上にベクトルを使用することをお勧めします。

関連する問題