【问题标题】:Reading a file into an Array and Outputting the Array C++ [duplicate]将文件读入数组并输出数组 C++ [重复]
【发布时间】:2020-06-14 06:46:47
【问题描述】:
#include <fstream>
#include <cmath>
#include <iomanip>
#include <iostream>
using namespace std;

int main()
{
    ifstream inData("Text.txt");
    ofstream outData("arrayout.txt");

    int n = 0;
    int num;
    int array[10];

    while (!inData.eof())
    {
        inData >> array[n];
        n++;
    }
    for (int a = 0; a < n; a++)
    {
        cout << array[n];
    }

    inData.close();
    outData.close();
}

我的问题是这个。该程序应该读取一个数据文件,将其读入一个数组,然后向前和向后打印数组。我整天都在寻找一些答案,我已经接近了,但我不明白为什么这个代码在我执行它时不打印我的数字。我连续十次得到-858993460的数字线。

文本文件中的数字是:1-10 逐行输入。谁能帮帮我? :)

【问题讨论】:

  • 在输入文件中,数字是如何分隔的?每行有一个号码吗?还是它们都在同一行,由某个分隔符分隔?请编辑您的问题以澄清这一点。
  • @Drewster301 那么您的文件要么没有正确打开,要么里面有超过 10 个数字。请说明您如何验证文件已打开。在int n = 0 之前添加if(!inData) throw "inData not opened";if(!outData) throw "outData not opened";,然后查看程序在执行时是否会给出错误消息。
  • @walnut,好的,我更改了代码的一个非常简单的部分,在现在打印出数字的循环内。我只是将 for 循环中的 n 更改为 a。这东西可真令人沮丧……

标签: c++ arrays file


【解决方案1】:
  1. 您已经声明了一个大小为 10 的固定数组,但循环检查的是文件的结尾,而不是数组的结尾。 n 在做什么?只需使用 std::vector 代替。如果数据文件的大小始终为 10,则可能是第二次循环中的拼写错误。
  2. 第二个循环上的错字。将 array[n] 更改为 array[a]。如果n=10,则array[n] 超出边界

【讨论】:

    【解决方案2】:

    您已经从 cmets 学习了 Why !.eof() inside a loop condition is always wrong.Why is “using namespace std;” considered bad practice?

    如果您的教授要求您使用 POA(普通数组)而不是容器(例如 std::vector),那么您有责任进行所有边界检查,以将您读取的元素限制为不超过数组被声明为持有,并在您读取的元素少于容器将持有的元素的情况下保留读取的元素数量的有效索引。

    所以本质上,您的任务是使用 C++ iostream 填充一个普通的 C 数组以进行输入处理。对于初学者,不要使用Magic-Numbers,也不要Hardcode-Filenames。而是:

     #define ARRSZ 10    /* if you need a constant, #define one (or more) */
    

    而接受参数的main() 的正确原型是int main (int argc, char **argv)(或*argv[],如果您更喜欢指针数组等效项)。您现在可以将要读取的文件名作为第一个参数传递给程序,而不必重新编译代码来读取另一个文件。要将参数用作要读取的文件名,您只需验证命令行上提供了足够数量的参数(正在运行的程序的名称始终是第一个参数,@987654329 @,所以第一个用户参数是argv[1]),例如

    int main (int argc, char **argv) {
    
        if (argc < 2) { /* validate at least one argument given for filename */
            std::cerr << "error: insufficient arguments\n"
                         "usage: " << argv[0] << " in-file\n";
            return 1;
        }
        int ndx = 0,                                /* index for array */
            array[ARRSZ] = {0};                     /* array */
        std::ifstream fin (argv[1]);                /* input file stream */
    

    注意:如果您只是写信给std::cout,则无需打开std::ofstream文件)

    现在您需要做的就是在ndx 小于ARRSZ 时从文件中读取值到您的数组中。您总是希望使用正在使用的读取函数来控制您的读取循环,以便可以使用stream-state 来指示您尝试读取的成功/失败。在这里,您还有另一个要保护的限制——您的数组边界。如果数组中有空间存储值,您只想尝试从文件中读取另一个值。结合两者,您可以将输入循环编写为:

        /* protect plain-old array bounds && validate integer input */
        while (ndx < ARRSZ && fin >> array[ndx])
            ndx++;                                  /* increment index on success */
    

    您现在已将ndx 元素读入您的数组,因此您需要做的就是以forwardreverse 的顺序输出它们。您可以通过循环 0 &lt;= i &lt; ndx 来实现正向情况,然后 ndx &gt; i &gt;= 0 在反向情况下,例如

        std::cout << "forward:\n";
        for (int i = 0; i < ndx; i++)               /* loop outputting each element */
            std::cout << "  array[" << i << "]: " << array[i] << '\n';
    
        std::cout << "\nreverse:\n";
        for (int i = ndx - 1; i >= 0; i--)          /* loop outputting each element */
            std::cout << "  array[" << i << "]: " << array[i] << '\n';
    

    注意:不需要关闭文件流——当流指针超出范围时会自动关闭)

    总而言之,你可以这样做:

    #include <iostream>
    #include <fstream>
    
    #define ARRSZ 10    /* if you need a constant, #define one (or more) */
    
    int main (int argc, char **argv) {
    
        if (argc < 2) { /* validate at least one argument given for filename */
            std::cerr << "error: insufficient arguments\n"
                         "usage: " << argv[0] << " in-file\n";
            return 1;
        }
    
        int ndx = 0,                                /* index for array */
            array[ARRSZ] = {0};                     /* array */
        std::ifstream fin (argv[1]);                /* input file stream */
    
        /* protect plain-old array bounds && validate integer input */
        while (ndx < ARRSZ && fin >> array[ndx])
            ndx++;                                  /* increment index on success */
    
        std::cout << "forward:\n";
        for (int i = 0; i < ndx; i++)               /* loop outputting each element */
            std::cout << "  array[" << i << "]: " << array[i] << '\n';
    
        std::cout << "\nreverse:\n";
        for (int i = ndx - 1; i >= 0; i--)          /* loop outputting each element */
            std::cout << "  array[" << i << "]: " << array[i] << '\n';
    }
    

    注意: iostreamfstream 是这个有限示例所需的唯一标头。养成仅包含源所需标头的习惯)

    输入文件示例

    读取8个整数空格分隔:

    $ cat dat/int8.txt
     15815 9999 6607 32552 1479 1769 20868 6058
    

    使用/输出示例

    $ ./bin/rdpoafile dat/int8space.txt
    forward:
      array[0]: 15815
      array[1]: 9999
      array[2]: 6607
      array[3]: 32552
      array[4]: 1479
      array[5]: 1769
      array[6]: 20868
      array[7]: 6058
    
    reverse:
      array[7]: 6058
      array[6]: 20868
      array[5]: 1769
      array[4]: 1479
      array[3]: 32552
      array[2]: 6607
      array[1]: 9999
      array[0]: 15815
    

    输入文件示例

    或者读取由'\n'分隔的整数没有区别(space'\t''\n'都是空格):

    $ cat dat/int10.txt
    19243
    31875
    3191
    11369
    22478
    1783
    25723
    835
    12093
    6888
    

    使用/输出示例

    $ ./bin/rdpoafile dat/int10.txt
    forward:
      array[0]: 19243
      array[1]: 31875
      array[2]: 3191
      array[3]: 11369
      array[4]: 22478
      array[5]: 1783
      array[6]: 25723
      array[7]: 835
      array[8]: 12093
      array[9]: 6888
    
    reverse:
      array[9]: 6888
      array[8]: 12093
      array[7]: 835
      array[6]: 25723
      array[5]: 1783
      array[4]: 22478
      array[3]: 11369
      array[2]: 3191
      array[1]: 31875
      array[0]: 19243
    

    检查一下,如果您还有其他问题,请告诉我。

    【讨论】:

      【解决方案3】:

      cout &lt;&lt; array[n]; 导致未定义的行为,因为n 超出了数组的末尾。你的意思可能是cout &lt;&lt; array[a];。在输出项之间留一些空白是个好主意。

      eof 的使用很差,see here for full explanation。循环可以改进为:

      for (n = 0; n < 10 && inData >> array[n]; ++n )
          {}
      

      (当然有多种方法可以格式化这样的循环),但退出条件应该是读取失败,并且不要超出存储范围。

      【讨论】:

        【解决方案4】:

        试试这个:

        #include <iostream>
        #include <fstream>
        #include <vector>
        using std::ios;
        using std::ifstream;
        using std::ofstream;
        using std::cout;
        using std::cerr;
        using std::exit;
        using std::vector;
        
        int main() {
        
            ifstream inData("Text.txt", ios::in);
            ofstream outData("arrayOut.txt", ios::out);
        
            if (!inData)  // Check for possible file opening errors
            {
                cerr << "The input file could not be opened";
                exit(1);
            }
            inData.seekg(0);  // Just for being sure 
            vector<int> numbers;  // The array where the values will be stored
            int currentNumber;
            int i = 0;
            while(inData >> currentNumber)
            {
                numbers.push_back(currentNumber);
                i++;
            }
        
            cout << "Printing the array forward:  ";
            for (size_t i = 0; i < numbers.size(); ++i)  // Print array forward
                cout <<numbers.at(i)<<' ';
        
            cout << "\n\nPrinting the array backwards:  ";
            for (int i = 9; i >= 0; --i)  // Print array backwards
            {
                cout << numbers.at(i) << ' ';
            }
        
            return 0;
        }
        

        这里程序在打开 ifstream 对象时检查是否有任何错误。然后,Text.txt 中的值现在将存储在向量numbers 中。最后,向量被向前和向后打印。 注意:在您的代码中,您没有使用 ofstream 对象。

        【讨论】:

          猜你喜欢
          • 2023-03-30
          • 1970-01-01
          • 2017-06-07
          • 2011-05-05
          • 2012-10-28
          • 2014-03-15
          • 2015-07-11
          • 2021-01-03
          • 1970-01-01
          相关资源
          最近更新 更多