2017-10-15 13 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 비트 정수입니다. 이를 얻는 일반적인 방법은 -1을 부호없는 64 비트 정수를 기대하는 변수에 넣는 것입니다. 확률은 네가 '이름'요소 중 하나의 시작 부분을 보려고하는 것이 좋다. – user4581301

답변

1

항상 찾기 기능의 반환 값을 확인하십시오. 예 :

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

\n하는 경우가 발견되지 않는, 반환 값은 string::npos이 잘못 인덱스입니다 (이 0xFFFFFFFF 또는 0xFFFFFFFFFFFFFFFF 수)입니다. 해당 인덱스에 액세스하려고 시도하면 오류가 발생합니다.

의견에서 언급했듯이 names[r]에는이 경우 \n이 포함되어 있지 않습니다. p은 항상 string::npos이며이 작업이 필요하지 않습니다.

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;

을 추가 할 수 있습니다

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

당신은 각 이름 아래 3 개 정수를 가지고, 그래서 당신은 3으로 계산해야하지 5.이 코드는 작동합니다

0

왜 새 줄 바꾸기가 필요한지 알 수 없습니다. 이름과 전화 번호를 추출하려면 다음을 수행하십시오.

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

파일의 정확한 형식을 알고 있어야합니다. 이 파일은 이미 완벽하고 쉬운 방법으로 조작 할 수 있습니다. 또한 데이터 크기를 모르는 경우 고정 크기 배열을 통해 벡터를 사용하는 것이 좋습니다.