【问题标题】:Read a file line by line and write to an array in C++在 C++ 中逐行读取文件并写入数组
【发布时间】:2017-08-31 18:49:01
【问题描述】:

我是 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;
    }
    

【问题讨论】:

  • 如果 getline 失败,你仍然会增加 pos。您永远不会在第二个循环中使用计算出的 pos。使用 std::vector 而不是原始数组 - 您可以调用 push_back ,它会随着您阅读文件而增长
  • 我相信使用调试器逐行检查代码并检查发生的情况比在 Stack Overflow 上提出这样的问题更好。
  • @NathanOliver,即使我将 while 循环更改为类似于 while (inputfile.good) 的内容,它也只会返回空白空格。这也是我的第三个问题。
  • @Y.Yang 那是一回事。如果您阅读该链接,它将向您展示从文件中读取的正确方法。

标签: c++ arrays ifstream


【解决方案1】:

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

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

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

如果函数没有提取字符,或者如果 一旦(n-1)个字符有 已经写入 s。请注意,如果后面的字符 输入序列中的那些 (n-1) 个字符正是 定界字符,它也被提取并且failbit标志不是 集(提取的序列正好是 n 个字符长)。

inputfile.getline(answer, 30) 如果任何问题的长度超过 30 个字符,这种形式的输入文件.getline(answer, 30) 将在 ifstream 上设置故障位,因为它没有到达分隔符(默认为换行符)。

无需更改任何数据结构(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 后清除故障位,并在超过 30 个字符时尝试完成读取该行。问题是,如果设置了故障位,循环将永远运行,因为 !ifstream.eof() while 条件永远不会满足。这意味着您的 pos 索引将永远递增并从数组末尾运行。

文件中的问题也可能比固定大小的数组答案可以存储的要多。

使用调试器的 cmets 不是开玩笑的。这就是你解决这些问题的方法。您需要一些关于 Xcode 调试器的初学者阅读材料(可能是 this?)。对于几乎所有初学者操作(检查变量的值、设置断点等)都可以通过 GUI 完成,而且应该非常简单。

关于您的代码(最好不要在 StackOverflow 上混合两个问题),在添加包含 std::string 和 getline 重载字符串的 include &lt;string&gt; 后,它对我来说运行得很好。但是,我没有与您相同的输入。在调用 getline 的循环内设置断点。如果您的路径错误或读取输入出现问题,您甚至不会进入该循环,您将遍历一堆空字符串并将它们打印出来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多