2017-08-31 440 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的循环内设置一个断点。如果您的路径错误或者读取输入时出错,您甚至不会进入该循环,并且您将遍历一堆空字符串并将其打印出来。