C++ 在运行时确定行数和列数时,将数字表读入数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8918084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:19:26  来源:igfitidea点击:

Read table of numbers into arrays when number of rows and columns determined at runtime

c++arraysgetline

提问by Adam Gosztolai

I would like to ask you about data input. I have a text file in the following format:

我想问你关于数据输入的问题。我有以下格式的文本文件:

7 2

7 2

X Y

XY

1 0
2 0.048922
3 0.0978829
4 0.146908
5 0.196019
6 0.245239
7 0.294584

1 0
2 0.048922
3 0.0978829
4 0.146908
5 0.196019
6 0.245239
7 0.294584

The first line contains the number of rows and columns to be read in. The second line are headers. From the third line onwards it's only data. I would like to read my data into a 2D array (mat[][]) and the headers into an array of strings (title[]), which could be easily referenced later. I came this far writing the script. It can read the array numbers into the array, but not a 2D one. I was trying to declare a pointer for the matrix which is passed to the function but I couldn't do it. I also tried getline() but I do not know how to separate the headers \t delimited into separate strings.

第一行包含要读入的行数和列数。第二行是标题。从第三行开始,它只是数据。我想将我的数据读入一个二维数组 (mat[][]) 并将标题读入一个字符串数组 (title[]),稍后可以轻松引用。我写了这么远的剧本。它可以将数组编号读入数组,但不能读入二维数组。我试图为传递给函数的矩阵声明一个指针,但我无法做到。我也试过 getline() 但我不知道如何将标头 \t 分隔成单独的字符串。

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;

void readFile(char[]);

int main(){

    char fileName[] = "results.txt";

    readFile(fileName);
    return 0;
}


// Read file to matrix
void readFile(char fileName[]){

    int m, n;

    // Create streamobject
    ifstream infile;
    infile.open(fileName);

    // Exit if file opening failed
    if (!infile.is_open()){
        cerr<<"Opening failed"<<endl;
        exit(1);
    }

    // Get size of the matrix
    infile >> m >> n;

    // Pre-allocate memory
    string title;
    float *mat=new float[m*n];

    // Read title

    // Start reading data
    while (!infile.eof()){
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                infile >> mat[i*n+j];
            }
        }
    }

    infile.close();
}

Could anyone help me out?

有人可以帮我吗?



Thank you for the help so far. I will have a look at applying vectors this weekend, but I have to read up on it. I have quickly changed my script so now it does what I wanted: return a pointer to an array "mat" with the values. I have a function called 'showMatrix', which prints it to the screen. If I call showMatrix within the function 'readFile' it works fine. If on the other hand I call it outside from the main script then it returns completely wrong values.

感谢您到目前为止的帮助。本周末我将看看应用向量,但我必须阅读它。我很快改变了我的脚本,所以现在它做了我想要的:返回一个指向带有值的数组“mat”的指针。我有一个名为“showMatrix”的函数,它将它打印到屏幕上。如果我在函数 'readFile' 中调用 showMatrix 它工作正常。另一方面,如果我从主脚本外部调用它,那么它返回完全错误的值。

I have a feeling there is something wrong here. Could you please help to point it out?

我有一种感觉,这里有些不对劲。你能帮忙指出吗?

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;

void readFile(char[],float *mat,int &m,int &n);
void showMatrix(float *mat,int m,int n);


/*******************************************************************
 Script
 *******************************************************************/
int main(){

    char fileName[] = "results.txt";
    int m, n;
    float *mat;

    // Read data from file
    readFile(fileName,mat,m,n);
    showMatrix(mat,m,n);

    return 0;
}

// Read file to matrix
void readFile(char fileName[],float *mat,int &m,int &n){


    // Create streamobject
    ifstream infile;
    infile.open(fileName);

    // Exit if file opening failed
    if (!infile.is_open()){
        cerr<<"Opening failed"<<endl;
        exit(1);
    }

    // Get size of the matrix
    infile >> m >> n;

    // Pre-allocate memory
    mat=new float[m*n];

    // Read title
    std::string X;
    std::string Y;
    infile >> X >> Y;

    // Reading data
    while (!infile.eof()){
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                infile >> mat[i*n+j];
            }
        }
    }
//    showMatrix(mat,m,n);
    infile.close();
}

// Print matrix to screen
void showMatrix(float *x,int m, int n){
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            cout << x[i*n+j] << "\t";
        }
        cout << endl;
    }
}

回答by Martin York

Note doing this:

注意这样做:

while (!infile.eof()){

Is nearly always wrong. If the file reading fails for any other reason than eof then you enter an infinite loop.

几乎总是错误的。如果文件读取因 eof 以外的任何其他原因失败,则您将进入无限循环。

Also the way you code is organized this will also mean that you try and initialize your data twice (though it will fail on the second pass an not do anything (apart from re-do the loop)) as the eof flag is not set until you read past the EOF and since you know how much data to read your first pass will not read past the EOF, you will read all the way up-to (but not past).

此外,您的代码组织方式也意味着您尝试两次初始化数据(尽管它会在第二次通过时失败并且不做任何事情(除了重新执行循环)),因为 eof 标志直到你读过 EOF 并且因为你知道有多少数据读你的第一遍不会读过 EOF,你会一直读到(但不是过去)。

Reading into a 1D array

读入一维数组

int main()
{
    std::ifstream file("plop");

    int n;
    int m;
    std::string ColHeadX;
    std::string ColHeadY;
    // You forgot to read the Col Header out.
    // Just read them into strings.
    file >> n >> m >> ColHeadX >> ColHeadY;

    // Don't do manual memory management.
    // Use a vector it will do the work for you.
    std::vector<double>   data(n*m); // initialized with (n*m) elemensts

    // Always put the read in the loop test
    //      This bit:  file >> data[loop]
    // If this read fails you want the loop to exit immediately.
    // By putting the read here the result of the read will be
    // tested to see if it worked.
    for(int loop=0;loop < (n*m) && (file >> data[loop]); ++loop) { /*Empty*/}
}

Reading into a 2D array is nearly as simple:

读入二维数组几乎同样简单:

int main()
{
    std::ifstream file("plop");

    int n;
    int m;
    std::string ColHeadX;
    std::string ColHeadY;
    // You forgot to read the Col Header out.
    // Just read them into strings.
    file >> n >> m >> ColHeadX >> ColHeadY;

    // Don't do manual memory management.
    // A vector of vectors gives you a 2D array.
    // The initialize(r) is slightly more complex but given the example above
    // I think you should be able to see the outer vector is initialized with
    // n copies of a vector with m elements. 
    std::vector<std::vector<double> >   data(n,std::vector<double>(m));


    // Again I would advise putting the read in the loop condition
    // The easiest way here is then to calculate the x/y coordinates in the body as you go.
    for(int loop=0, x=0, y=0;loop < (n*m) && (file >> data[x][y]);)
    {
       ++loop
       x = loop % n;
       y = loop / n;
    }

}

回答by Nolan Amy

To allocate the two-dimensional array inside your function, use:

要在函数内分配二维数组,请使用:

float **mat = new float*[m];

for(int i=0; i<m; i++){
    mat[i] = new float[n];
}

Then you can change infile >> mat[i*n+j];to:

然后您可以更改infile >> mat[i*n+j];为:

infile >> mat[i][j];

Finally, make sure you implement reading the title; right now it's empty:

最后,确保你实现了阅读标题;现在它是空的:

//Read title

回答by brendanw

In C and C++, pointers (C and C++) and references (C++ only) to arrays are declared with a somewhat obscure syntax, like this:

在 C 和 C++ 中,指向数组的指针(C 和 C++)和引用(仅 C++)是用有点晦涩的语法声明的,如下所示:

void fp(float (*array)[10]);
void fr(float (&array)[10]);
void f2d(float (&array)[10][10]);


void main()
{
    float a[10];
    fp(&a);
    fr(a);

    float b[10][10];
    f2d(b);
}

You cannot declare a pointer or reference to an array that is not of compile-time constant size. To pass variable-sized data you need to use a pointer to the first element in the array and pass in the size of the data, so your code can safely use the array with out running out of bounds, like this:

不能声明指向非编译时常量大小的数组的指针或引用。要传递可变大小的数据,您需要使用指向数组中第一个元素的指针并传入数据的大小,这样您的代码就可以安全地使用数组而不会越界,如下所示:

void f(float* data, int length);

However, this places a burden on the programmer to carefully write safe and correct code. Since you're using C++ and not C, using std::vectoris highly recommended! vectoris a sequential container object that behaves just like an array when you need to index into it. It is dynamically resizable, and will handle the details of allocation and deallocation for you.

然而,这给程序员带来了仔细编写安全且正确的代码的负担。由于您使用的是 C++ 而不是 C,std::vector因此强烈建议您使用!vector是一个顺序容器对象,当您需要对其进行索引时,它的行为就像一个数组。它可以动态调整大小,并会为您处理分配和释放的细节。