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

时间:2012-01-18 21:59:08

标签: c++ arrays getline

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

7 2

X Y

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

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

#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();
}

有人可以帮帮我吗?


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

我觉得这里有问题。你能帮忙指出来吗?

#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;
    }
}

4 个答案:

答案 0 :(得分:4)

注意这样做:

while (!infile.eof()){

几乎总是错的。如果由于eof之外的任何其他原因导致文件读取失败,则进入无限循环。

此外,您的代码组织方式也意味着您尝试将数据初始化两次(尽管它会在第二次传递时失败而不执行任何操作(除了重新执行循环)),因为eof标志是直到你读完EOF之后才设置,因为你知道你的第一遍的读取数据不会超过EOF,你会一直读到(但不是过去)。

读入一维数组

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*/}
}

读入2D数组几乎一样简单:

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

}

答案 1 :(得分:0)

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

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

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

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

infile >> mat[i][j];

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

//Read title

答案 2 :(得分:0)

在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);
}

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

void f(float* data, int length);

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

答案 3 :(得分:0)

如上所述,您无法动态分配多维数组,因为在编译时必须知道除一个维之外的所有维。虽然您可以使用std::vector<std::vector<float> >,但最好创建Matrix类型。这是一个(非常简化的)示例:

class Matrix
{
public:
  Matrix (int _m, int _n) : m(_m), n(_n), t(m * n) {}
  float& operator() (int i, int j) { return t[i * n + j]; }
  int size_x () { return m; }
  int size_y () { return n; }

private:
  int m;
  int n;
  std::vector<float> t;
};

std::ostream &operator<<(std::ostream &os, Matrix mat)
{
  for (int i = 0; i < mat.size_x(); i++) {
    for (int j = 0; j < mat.size_y(); j++) {
      os << mat(i,j) << ' ';
    }
    os << '\n';
  }
  return os;
}

当然,您应该使用现有的库,例如uBLAS