2017-11-07 19 views
3

임의의 배열을 생성하려고합니다.파일이 올바르게 설정되었지만 예기치 않게 새 스트림에서 eof() 및 peek()이 잘못된 값을 반환합니다.

void Random_nums(int n, string fileName) { 

    ofstream fsave(fileName); 
    int ranArray[n]; 

    srand((unsigned int)time(NULL)); 
    for(int i=0; i<n; i++) 
    { 
     ranArray[i]=rand()%2001 - 1000; 
     fsave << ranArray[i] << '\n'; //save them into ranArray 
    } 

    fsave.close(); 
} 

그리고 개별 파일에 저장하고 싶습니다.

그런 다음 방금 저장 한 데이터를 읽고 새로운 기능으로 구현하고 싶습니다.

void FunctionWantToUse(string inputFile, string outputFile) { 

    //reading data 
    ifstream fin(inputFile); 
    cout << fin.is_open();//which is 1 

    //how many numbers are there in this file 
    int n = 0; 
    n = distance(istream_iterator<int>(fin), istream_iterator<int>()); 

    //restore the array 
    int array[n]; 

    //test 
    cout << fin.peek() << ' ' << EOF;//they are both -1! 

    //another test 
    cout << fin.peek() << '\n'; //which return -1 
    cout << fin.eof() << '\n'; //which return 1 

    //since peek() and EOF both return -1, I can't get into this loop. 
    while (fin.peek() != EOF) { 
     if ((fin >> array[i]).good()) { 
      cout << array[i]; 
     } 
    } 

은 완전히 왜 -1 fin.peek()와 fin.eof() 변화의 값 1은 각각 모른다.

그리고이 두 기능을 실행하면 콘솔에서이 사실을 알려줍니다. I는 난수를 생성 할 때

-1 -1-1 
1 

Process finished with exit code 0 

I은 ​​또한 루프의 장소 fsave.eof()와 같은 다른 검사를 제공하고, 그것은 모두 0을 출력한다.

누군가가 여기에 무슨 일이 일어나는지 말해 줄 수 있습니까? 나는 지금 전혀 실마리가 없다.

+0

'istream :: eof()'는'bool'을 반환합니다. 'bool' 만 출력하면'0' 또는'1' 값을 갖습니다. 'EOF'는 일반적으로'int' 리터럴로 확장되는 C의 매크로로 보통 문자의 범위를 벗어나는 값을 가지므로 '0'이나 '1'이 될 수 없습니다. 그러므로'EOF'와'fin.eof()'는 같은 것을 비교할 수 없다. 간단한 해결책 : C 매크로 (예 :'EOF')를 사용하여 C++ 스트림의 상태를 테스트하지 말것. – Peter

답변

3

std::distance(istream_iterator<int>(fin), istream_iterator<int>())은 읽을 수 없을 때까지 파일을 처리하고 int입니다. 그 이유는 (공백 문자를 건너 뛴 후에) int으로 구문 분석 할 수없는 입력이 있거나 파일 끝에 도달했기 때문입니다. 어떤 경우에는 distance()에 대한 호출이 std::ios_base::failbit으로 설정되고 오류가 도달하는 파일의 끝에 도달하는 경우 std::ios_base::failbit이 반환됩니다.

분명한 수정점은 이 아니며은 거리를 결정하고 대신 정수를 적절한 표현으로 직접 읽는 것입니다. 예를 들면 : 당신이 정말 대신 루프를 사용하려면

std::vector<int> array{std::istream_iterator<int>(fin), 
         std::istream_iterator<int>()}; 

, 당신은에서, 스트림에서 읽기 후 상태 를 실패하지 될 스트림에 대한 테스트해야합니다 예 :

for (int tmp; fin >> tmp;) { 
    // use tmp 
} 

때를 정말

  1. clear()이이있어 스트림 상태 이후에 당신이 필요합니다, 당신은 첫 번째 요소의 수를 결정해야합니다 느낀다3210 세트. 이것이 없으면 대부분의 스트림 작업은 무시됩니다.
  2. seekg() 스트림 시작 부분으로 돌아 가기.

참고 그러나 std::vector<int> 몇 번 크기를 조정하는 것은 거의 확실 파일을 통해 읽고 두 번 그 내용을 분석하는 것보다 더 효과적 일 것입니다.

  1. 변수 크기의 배열은 표준 C의 하지 일부 ++ 어떤 컴파일러는 않지만 확장으로 그들을 지원 :

    BTW, 배열의 사용은 두 가지 문제가있다.

  2. 파일의 크기가 적당한 경우 스택 오버플로가 발생합니다.

대신 std::vector<int>을 사용하면 훨씬 편리합니다.

+0

("EOF"와 같은). 고마워요! 그냥 고쳐주세요! – Sail