逐行读取文件并在C ++中写入数组

时间:2017-08-31 18:49:02

标签: c++ arrays ifstream

我是C ++的新手,我在lynda.com教练的练习中遇到了麻烦。

我应该创建一个包含单词行的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;
    }
    

1 个答案:

答案 0 :(得分:0)

Eesh,我认为我不会继续这个特定的课程。

在你老师的代码中,我猜测(但不能确定,因为你没有给出输入)你的答案索引(pos)的数组是在数组末尾运行的并在教师代码中为您提供EXEC_BAD_ACCESS。

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

  

如果函数不提取任何字符,则设置failbit标志   一旦(n-1)个字符找不到分隔字符   已写入s。请注意,如果后面的字符   输入序列中的那些(n-1)个字符恰好是   分隔字符,它也被提取,而failbit标志则不是   set(提取的序列正好是n个字符)。

如果任何问题长度超过30个字符,则此表单中的

inputfile.getline(answer,30)将设置ifstream上的failbit,因为它尚未到达分隔符(默认为换行符)。

不改变任何数据结构(在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完成,并且应该非常简单。

关于你的代码(最好不要在Stack Overflow上混合两个问题),在添加包含std :: string和getline的字符串重载的include <string>后,它就可以运行了。但是,我没有和你一样的输入。在调用getline的循环内设置断点。如果您的路径错误或者读取输入有问题,您甚至不会进入该循环,并且您将遍历一堆空字符串并将其打印出来。