2017-08-31 444 views
-3

我是C++的新手,而且我很難執行lynda.com教師給出的這個練習。逐行讀取文件並寫入C++數組

我應該創建一個txt文件,其中包含文字。我們使用ifstream逐行讀取並將字符串存儲到字符串數組中。 (注:此任務有哪些是無關緊要的,以我的問題的其他部分。)

所以,我有三個問題:

  1. 當我運行由導師給出的解決方案,但它可以編譯和運行它有EXC_BAD_ACCESS。

    這裏是她的代碼:

    #include <iostream> 
    #include <cstdlib> 
    #include <ctime> 
    #include <cstring> 
    #include <fstream> 
    using namespace std; 
    
    string getRandomReply(string [], int); 
    
    int main() 
    { 
        ifstream inputfile; 
    
        // Declare an input file 
        inputfile.open("replies.txt", ios::in); 
    
        char answer[30]; 
        string answers[20]; 
        int pos = 0; 
    
        // Read from the file until end of file (eof) 
        while (!inputfile.eof()) 
        { 
         inputfile.getline(answer, 30); 
         answers[pos] = answer; 
         pos++; 
        } 
    
        cout << "Think of a question for the fortune teller, " 
        "\npress enter for the answer " << endl; 
        cin.ignore(); 
        cout << getRandomReply(answers, 20) << endl; 
        return 0; 
    
    } 
    string getRandomReply(string replies[], int size) 
    { 
        srand(time(0)); 
        int randomNum = rand()%20; 
        return replies[randomNum]; 
    } 
    
  2. 即使這個方案是功能性的,我不明白,需要創造的char [],並通過它來分配值到字符串數組。

  3. 我在做練習時編寫了自己的代碼,它編譯並運行,但返回空白行。

    #include <iostream> 
    #include <cstdlib> 
    #include <ctime> 
    #include <cstring> 
    #include <fstream> 
    
    int main(int argc, const char * argv[]) { 
        std::ifstream inputfile; 
        inputfile.open("replies.txt", std::ios::in); 
        std::string answers[20]; 
        int pos = 0; 
    
        // Read from the file until end of file (eof) 
        while (inputfile.good()) 
        { 
         getline(inputfile, answers[pos], '\n'); 
         pos++; 
        } 
        for (int i=0; i<20; i++) 
        { 
         std::cout << answers[i] << std::endl; 
        } 
        /* 
         srand(time(0)); 
         std::cout << "Think of a question that you would like to ask fortune teller." << std::endl; 
         int ranNum = rand()%20; 
         std::string answer = answers[ranNum]; 
         std::cout << answer << std::endl; 
        */ 
        return 0; 
    } 
    
+5

[不要使用while while(!inputfile.eof())'](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – NathanOliver

+0

如果getline失敗,仍然會增加pos。你從不在第二個循環中使用計算的pos。而不是原始數組使用std :: vector - 你可以調用push_back,它會隨着你讀取你的文件而增長 –

+2

我相信逐行調試你的代碼,檢查發生了什麼會更好地爲你服務,而不是問這樣一個問題在堆棧溢出。 – user0042

回答

0

Eesh,我不認爲我會用這個特殊的過程中不斷。

在你的老師的代碼中,我猜測(但不能確定,因爲你沒有給出輸入)你的數組索引(pos)正在運行在數組的末尾並給你教師代碼中的EXEC_BAD_ACCESS。

http://www.cplusplus.com/reference/istream/istream/getline/

如果函數提取沒有字符,或者如果 的定界字符沒有發現一旦failbit標誌被設置(N-1)個字符已 已經被寫入到第請注意,如果輸入序列中那些(n-1)個字符後面的字符正好是 定界字符,那麼它也會被提取,並且失敗位標誌不是 集(提取的序列正好n個字符長)。

inputfile.getline(答案30)以這種形式將設置在ifstream的的failbit如果有任何問題都超過30個字符長,因爲它沒有達到分隔符(默認爲新行)。

無需更改任何數據結構(這是你的C++中更好的),如果添加類似,它可能工作:

// Read from the file until end of file (eof) 
while (!inputfile.eof()) 
{ 
    inputfile.getline(answer, 30); 
    answers[pos++] = answer; 

    while (!inputfile) 
    { 
    inputfile.clear(); 
    inputfile.getline(answer, 30); 
    } 
} 

這每次調用函數getline和嘗試後清除failbit如果超過30個字符,則可以閱讀該行。問題是,如果failbit被設置,循環將永遠運行,因爲!ifstream.eof()而條件從未滿足。這意味着您的pos索引將永遠增加並在陣列的末尾運行。

也可能是文件中的問題多於固定大小的數組答案可以存儲的問題。

使用調試器的註釋並不是荒謬的。這是你解決這些問題的方式。您需要在Xcode調試器上使用一些初學者閱讀材料(也許this?)。對於幾乎所有的初學者操作(檢查變量的值,設置斷點等),都可以通過GUI完成,並且應該非常簡單。

關於你的代碼(最好不要在堆棧 溢出中混合兩個問題),它添加了include <string>,其中包含字符串的std :: string和getline超載後運行。但是,我沒有和你一樣的意見。在調用getline的循環內設置一個斷點。如果您的路徑錯誤或者讀取輸入時出錯,您甚至不會進入該循環,並且您將遍歷一堆空字符串並將其打印出來。