【问题标题】:Reading array from file not giving correct values?从文件中读取数组没有给出正确的值?
【发布时间】:2019-12-11 10:06:01
【问题描述】:

目前正在处理一个必须在太平洋标准时间星期四晚上之前完成的项目。为了快速总结,该程序必须基于菜单并允许用户创建一个长双精度数组(用户设置的行/列数和所有数组值)并将其保存到文件(用户设置名称)。它还必须允许用户将文件读入长双精度数组并将其打印到程序中,然后允许用户选择要排序的列并将排序后的数组保存到另一个文件中,最后允许用户搜索文件中的值(程序必须知道列是已排序还是未排序并使用适当的搜索算法)。

由于 CHOICE_2 和 CHOICE_3 函数的问题,我没有完成菜单中的 CHOICE_4。这是我整个项目的源代码:

#include <iostream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <fstream>
#include <vector>

using namespace std;

//Function prototypes required for project
void displayMenu(int &);                //Menu function
int unsortedFile(string, int, int);     //Function for menu choice 1
int printFile(string, int, int);        //Function for menu choice 2
int sortFile(string, int, int);     //Function for menu choice 3

int main()
{
    int choice;             //Menu choice

    do
    {
        displayMenu(choice);
    } 
    while (choice > 0 && choice <= 4);

    return 0;
}

void displayMenu(int &c)
{
    //Constants for menu choices
    const int   CHOICE_1 = 1,
                CHOICE_2 = 2,
                CHOICE_3 = 3,
                CHOICE_4 = 4,
                QUIT_CHOICE = 0;

    string  filenameU,      //unsorted
            filenameP,      //printed
            filenameS,      //to be sorted
            filenameSOut;   //sorted data

    int         SIZE1,      //Array dimensions
                SIZE2;      //Array dimensions

    cout << "-------------------------" << endl;
    cout << "\tMENU" << endl;
    cout << "-------------------------" << endl;
    cout << "1. Create a custom array file." << endl;
    cout << "2. Print an array from a file." << endl;
    cout << "3. Sort an array from a file." << endl;
    cout << "4. Search an array from a file." << endl;
    cout << "0. Exit program." << endl;
    cout << "-------------------------" << endl;
    cout << "Enter your choice from above: ";
    cin >> c;
    cout << endl;

    switch(c)
    {
        case CHOICE_1:
            cout << "Enter the name of the file you want to write: ";
            cin.ignore(100, '\n');
            getline(cin, filenameU, '\n');

            do
            {
                cout << endl;
                cout << "Enter the amount of rows you want in your array between 2 and 10: ";
                cin >> SIZE1;
            } while (SIZE1 < 2 || SIZE1 > 10);

            do
            {
                cout << endl;
                cout << "Enter the amount of columns you want in your array between 2 and 10: ";
                cin >> SIZE2;
            } while (SIZE2 < 2 || SIZE2 > 10);

            unsortedFile(filenameU, SIZE1, SIZE2);
            break;
        case CHOICE_2:
            cout << "Enter the name of the file you want to print: ";
            cin.ignore(100, '\n');
            getline(cin, filenameP, '\n');

            printFile(filenameP, SIZE1, SIZE2);
            break;
        case CHOICE_3:
            cout << "Enter the name of the file you want to sort: ";
            cin.ignore(100, '\n');
            getline(cin, filenameS, '\n');

            sortFile(filenameS, SIZE1, SIZE2);
            break;
        case CHOICE_4:
            break;
        case QUIT_CHOICE:
            cout << "Exiting program." << endl;
            break;
        default:
            cout << "The valid entries are 1-4 or 0 to exit program.";
    }
}

int unsortedFile(string filenameU, int SIZE1, int SIZE2)
{
    long double arr[SIZE1][SIZE2];  //Array for user definition

    ofstream outputFileU;
    outputFileU.open(filenameU.c_str());

    //Get data for file output
    if (outputFileU)
    {
        //Get user input for array
        cout << "Enter numbers into the array." << endl;
        for (int i = 0; i < SIZE1; i++)
        {
            for (int j = 0; j < SIZE2; j++)
            {
                cout << "Enter element [" << i << "] [" << j << "]: ";
                cin >> arr[i][j];

                outputFileU << arr[i][j] << " ";
            }
            outputFileU << endl;
        }
    }
    else
    {
        cout << "File could not be opened for writing..." << endl;
        return 1;
    }

    //Close the file
    outputFileU.close();
    cout << "-------------------------" << endl;
    cout << "File named: " << filenameU << " written." << endl;
    cout << endl;
}

int printFile(string filenameP, int SIZE1, int SIZE2)
{
    ifstream inputFileP;
    inputFileP.open(filenameP.c_str());

    if (inputFileP.is_open())
    {
        long double pArr[SIZE1][SIZE2];
        inputFileP >> SIZE1 >> SIZE2;

        while (inputFileP.good())
        {
            for (int i = 0; i < SIZE1; i++) //steps through rows
            {
                for (int j = 0; j < SIZE2; j++) //steps through columns
                {
                    inputFileP >> pArr[i][j]; //reads data at position i, j
                    cout << pArr[i][j] << " "; //prints value at position i, j
                }
                cout << endl;
            }
        }

        inputFileP.close();
        cout << "-------------------------" << endl;
        cout << "File named: " << filenameP << " printed." << endl;
        cout << endl;
    }
    else
    {
        cout << "File could not be opened for printing..." << endl;
        return 1;
    }
}

int sortFile(string filenameS, int SIZE1, int SIZE2)
{
    int key;

    ifstream inputFileS;
    inputFileS.open(filenameS.c_str());

    if(inputFileS)
    {
        inputFileS >> SIZE1;
        inputFileS >> SIZE2;
        long double temp[SIZE1];
        long double data[SIZE1][SIZE2];

        for (int i = 0; i < SIZE1; i++)
        {
            for (int j = 0; j < SIZE2; j++)
            {
                inputFileS >> data[i][j];
            }
        }

        cout << "Enter which column you want to sort: ";
        cin >> key;
        key--;

        for (int i = 0; i < SIZE1; i++)
        {
            for (int j = 0; j < SIZE2; j++)
            {
                if (data[i][key] > data[j][key])
                {
                    for (int t = 0; t < SIZE1; t++)
                    {
                        temp[t] = data[i][t];
                    }
                    for (int t = 0; t < SIZE1; t++)
                    {
                        data[i][t] = data[j][t];
                    }
                    for (int t = 0; t < SIZE1; t++)
                    {
                        data[j][t] = temp[t];
                    }
                }
            }
        }
        string filenameSOut;
        cout << "\nEnter file name to save sorted data: ";
        cin.ignore(100, '\n');
        getline(cin, filenameSOut, '\n');

        ofstream outputFileS;
        outputFileS.open(filenameSOut.c_str());

        outputFileS << SIZE1 << " " << SIZE2 << endl;

        for (int i = 0; i < SIZE1; i++)
        {
            for (int j = 0; j < SIZE2; j++)
            {
                outputFileS << data[i][j];
            }
            outputFileS << endl;
        }
        outputFileS.close();
        cout << "-------------------------" << endl;
        cout << "File named: " << filenameSOut << " sorted." << endl;
        cout << endl;
    }
    else
    {
        cout << "File could not be opened for sorting...";
        return 1;
    }
}

我的输出目前是这样的(使用一些示例输入):

-------------------------
        MENU
-------------------------
1. Create a custom array file.
2. Print an array from a file.
3. Sort an array from a file.
4. Search an array from a file.
0. Exit program.
-------------------------
Enter your choice from above: 1

Enter the name of the file you want to write: Yeetus

Enter the amount of rows you want in your array between 2 and 10: 3

Enter the amount of columns you want in your array between 2 and 10: 4
Enter numbers into the array.
Enter element [0] [0]: 5
Enter element [0] [1]: 3
Enter element [0] [2]: 8
Enter element [0] [3]: 9
Enter element [1] [0]: 2
Enter element [1] [1]: 1
Enter element [1] [2]: 0
Enter element [1] [3]: 3
Enter element [2] [0]: 5
Enter element [2] [1]: 7
Enter element [2] [2]: 4
Enter element [2] [3]: 4
-------------------------
File named: Yeetus written.

-------------------------
        MENU
-------------------------
1. Create a custom array file.
2. Print an array from a file.
3. Sort an array from a file.
4. Search an array from a file.
0. Exit program.
-------------------------
Enter your choice from above: 2

Enter the name of the file you want to print: Yeetus
8 9 2
1 0 3
5 7 4
4 1.45808e-4950 1.45808e-4950
1.45808e-4950 1.74779e-4944 4.70418e+1991
-------------------------
File named: Yeetus printed.

-------------------------
        MENU
-------------------------
1. Create a custom array file.
2. Print an array from a file.
3. Sort an array from a file.
4. Search an array from a file.
0. Exit program.
-------------------------
Enter your choice from above: 3

Enter the name of the file you want to sort: Yeetus
Enter which column you want to sort: 3

Enter file name to save sorted data: YeetusSorted
-------------------------
File named: YeetusSorted sorted.

-------------------------
        MENU
-------------------------
1. Create a custom array file.
2. Print an array from a file.
3. Sort an array from a file.
4. Search an array from a file.
0. Exit program.
-------------------------
Enter your choice from above: 0

Exiting program.

--------------------------------
Process exited after 58.35 seconds with return value 0
Press any key to continue . . .

第一个函数unsortedFile 可以完美地工作,因为它还必须在第一行中包含 UNSORTED,然后分别在第二行和第三行中包含 ROWS: 和 COLUMNS:。只有数字,它会打印如下:

5 3 8 9 
2 1 0 3 
5 7 4 4 

第二个函数似乎跳过了文件中的前两个数字,打印其余的,然后打印一堆垃圾。

第三个函数提供了以下文件,其中包含我提供的示例数据:

5 3
894
103
572
4-2.71616e-11730
1.56264e-48671.68249e-2119-inf

不...完全确定为什么会这样。如果我能够正确地从文件中读取数据以获得实数,我可以使用排序和搜索算法轻松完成这个程序(希望如此)。现在,我被困住了。如果有人可以帮助我修复第二个和第三个函数来读取/打印和排序准确的数字,并让我知道如何在不破坏其他功能的情况下使文件看起来像这样:

UNSORTED
Rows: 3
Columns: 4
5 3 8 9 
2 1 0 3 
5 7 4 4 

供参考:本课程为 C++ 入门课程。我们只应该使用我今天在这里提供的东西。也允许使用向量和指针,但我尽量避免使用它们,因为我没有完全了解如何使用它们,也没有时间学习如何在这个项目中使用它们。

【问题讨论】:

  • 除此之外,long double temp[SIZE1]; - 不要那样做。任何告诉你不这样做的课程都是有问题的。 C++ 没有对本机 VLA(可变长度数组)的标准支持。请改用 std::vector&lt;long double&gt; temp(SIZE1);,希望您不再假设您的流读取 work 并实际验证它们以及它们产生的产品。
  • "由于 CHOICE_2 和 CHOICE_3 函数的问题,我没有完成菜单中的 CHOICE_4。这是我整个项目的源代码" - 而不是转储完整在这里的项目,创建一个minimal reproducible example,你试图解决你在CHOICE_2 上遇到的问题。为CHOICE_3 等提出一个单独的问题。

标签: c++ arrays file-io


【解决方案1】:

现在关注printFile: 你的函数做的第一件事是

inputFileP >> SIZE1 >> SIZE2;

但是有很多问题:

  • 您的unsortedFile 函数不写入此标头。您实际上将第一行的前两个元素视为要读取的大小。
  • 它会覆盖您作为参数传递的SIZE1SIZE2 参数。如果您要直接从文件中读取它们,为什么还要传递这些?
  • 最后是杀手级问题:使用作为参数提供的SIZE1SIZE2 分配数组后从文件中读取大小。

因此,您有效地为一个 3x4 的数组分配内存,然后将其写入,就好像它是一个 5x3 矩阵一样。这会产生烟花。

最后说明:您的顶级菜单假定用户始终通过选项 1 来设置 SIZE1SIZE2。您应该从不使用它们的函数中删除这些参数,或者显式设置它们。从我在这里看到的情况来看,最好从选项 2-4 中的函数调用中删除这些参数。

【讨论】:

  • 谢谢!我认为有一个逻辑缺陷。是否甚至需要定义数组的维度,或者我可以让它读取每一行直到什么都没有,在下一行继续,等等。使用行/列变量(在 for 循环中而不是 SIZE1/ SIZE2) 只是设置为比可能的最大数量多一吗?即const int row = 11; 用于for (int i = 0; i &lt; row; i++),当数组最多有 10 行或列时。
  • 这是非常主观的。我的经验法则:如果您的文件格式编码了特定的数据形状,您可以通过包含尽可能多的有关该形状的数据来帮助读者。忽略当前的形状数据比重新创建丢失的形状数据更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多