Pass a stream to a method

Hi,

if a file is open in read mode at main(), then I want to call a method() to read something in the file. How can I pass the stream to the method?

I think it can be something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
method(iFile){
    int c = 0;
    string line;
    while(!iFile.eof()) {
        getline (iFile, line);
        c++;
    }
}
int main(int argc, char**argv) {
    ifstream iFile;
    iFile.open(argv[1]);
    method(iFile);
    iFile.close();
}


?
Last edited on
You should pass streams by reference (they don't have copy-constructor) so:
1
2
3
4
void method ( istream &iFile )
{
    //etc
}
should work
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdlib.h>


#include <iostream>
#include <fstream>
#include <string>
#include <istream>

using namespace std;

int matrix(istream &iFile) {
    cout << "Método para obter o número de linhas e colunas da "
            "matriz" << endl;
    int c = 0;
    string line;
    while(!iFile.eof()) {
        getline (iFile, line);
        c++;
    }
    cout << "Número de linhas: " << c+1 << endl;

    return 0;
}

int main(int argc, char**argv) {

    int matrix(istream &iFile); // Declaração do método para obter número de
                           // linhas e colunas da matriz

    matrix(argv[1]); // Chamada ao método passando o nome do arquivo
                     // como parâmetro

    cout << "Using file " << argv[ 1 ] << endl;


    ifstream iFile;
    iFile.open(argv[1]);
    float value;
    for(int i = 0; i < 3; i++){
        for(int j = 0; j < 3; j++){

            iFile >> value;
            cout << value << " ";
        }
        cout << "\n";
    }

    iFile.close();

    return 0;
}


What is wrong in the code above?
Last edited on
Remove line 27
At line 30 you are passing a C string, not a file stream. If is that the way you want your program to work you should change/overload it to this:
1
2
3
int matrix(char *file_name) {
    ifstream iFile ( file_name );
    //etc 
By the way, why does it have int as return type if you always return 0 ?
You are never checking the number of arguments passed to your program so argv[1] can lead to problems
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdlib.h>


#include <iostream>
#include <fstream>
#include <string>
#include <istream>

using namespace std;

void matrix_sz(istream &iFile) {
// Método para obter o número de linhas e colunas da matriz.
    int c = 0;
    string line;
    while(!iFile.eof()) {
        getline (iFile, line);
        c++;
    }
    cout << "Número de linhas: " << c-1 << endl;
}

void matrix_read(istream &iFile) {
// Método para ler a matriz.
    double value;
    for(int i = 0; i < 3; i++){
        for(int j = 0; j < 3; j++){
            iFile >> value;
            cout << value << " ";
        }
        cout << "\n";
    }
}

int main(int argc, char**argv) {

    cout << "Using file " << argv[ 1 ] << endl;

    ifstream iFile;
    iFile.open(argv[1]);

    if(!iFile) { // file couldn't be opened
        cerr << "Error: file could not be opened" << endl;
        exit(1);
    }

    matrix_sz(iFile);
    matrix_read(iFile);


    iFile.close();

    return 0;
}


I am using, as input, a file with an ascii matrix

1 2 3
4 5 6
7 8 9

but the code above is outputing strange values. Can you see what is wrong?

The output is:

4.92586e-270 4.92586e-270 4.92586e-270
4.92586e-270 4.92586e-270 4.92586e-270
4.92586e-270 4.92586e-270 4.92586e-270
Last edited on
That should be because in function matrix_sz you read (and removed) all the character in the stream.
Try something like this:
1
2
3
4
5
6
7
8
9
10
11
12
void matrix_sz(istream &iFile) {
    iFile.seekg(0,ios::end);//go to the end of the file
    int c = 0, size = iFile.tellg();//get the size in bytes
    iFile.seekg(0);//returnt to the beginning of the file
    for (int p=0; p<size; p++)//p iterates all the possible character positions
    {
        if ( iFile.peek() == '\n' ) c++;// check for newline (peek doesn't remove characters from the stream)
        iFile.seekg(p);//go to the position
    }
    cout << "Número de linhas: " << c+1 << endl;
    iFile.seekg(0);//returnt to the beginning of the file
}
All you need to do is

1
2
iFile.seekg(0);
iFile.clear();


at the start of each function to make sure you can read the file in each function.

However, a better solution might be to read the data in to vectors once, then print the number of lines and the data that are in the vectors rather than re-reading the file multiple times.

That's the point PanGalactic,

but I am a newbie and my algorithm is:

1 - Discover the number of columns
2 - Discover the number of lines
3 - Create the a vector with the correct size
4 - Read data to the vector

I believe that is an intelligent way to what I want, but I do not know that way...

My mission is simple, I need to read a matrix of double from an ASCII file.

I will appreciate if you can help.

I tried(code below) what you proposed, but it does not work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <istream>
#include <sstream>

using namespace std;

int matrix_lines(istream &iFile) {
// Método para obter o número linhas da matriz.
    iFile.seekg(0);
    iFile.clear();
    int lines = 0;
    string line;
    while(!iFile.eof()) {
        getline (iFile, line);
        lines++;
    }
    cout << "Número de linhas: " << lines << endl;
    return lines;
}

int matrix_columns(istream &iFile) {
// Método para obter o número de colunas da matriz.
    iFile.seekg(0);
    iFile.clear();
    string line;
    double n;
    int cols = 0;

    getline (iFile, line);
//    cout << line << endl;

    stringstream is(line);
    n = 0;
    while (is >> n) {
//        cout << n << endl;
        cols++;
    }


//     
    cout << "Número de colunas: " << cols << endl;
    return cols;
}

void matrix_read(istream &iFile, int lines, int cols) {
// Método para ler a matriz.
    iFile.seekg(0);
    iFile.clear();
    float value;
    for(int i = 0; i < lines; i++){
        for(int j = 0; j < cols; j++){
            cout << iFile.get() << " ";
        }
        cout << "\n";
    }
}

int main(int argc, char**argv) {

//    cout << "Using file " << argv[ 1 ] << endl;

    ifstream iFile;
    iFile.open("/home/cristiano/matrix2.dat");

    if(!iFile) { // file couldn't be opened
        cerr << "Error: file could not be opened" << endl;
        exit(1);
    }

    int cols = matrix_columns(iFile);
    int lines = matrix_lines(iFile);
//    int cols = 3;
//    int lines = 3;

    matrix_read(iFile, lines, cols);


    iFile.close();

    return 0;
}
Last edited on
PanGalactic,

in fact your replay is correct in some way. But is not

1
2
iFile.seekg(0);
iFile.clear();


it work when I do

1
2
iFile.clear();
iFile.seekg(0);


Thanks.
Ah -- your algorithm is OK, but you can do 3 & 4 before 1 & 2. :-)

A vector is variable size. It can grow to fit your needs. And then it can tell you how big it is.
PanGalactic,

and how can I do that?

There is some thing like?

 
vector = iFile;
I think this is what you should do.
Get the file character by character or read the entire file into memory (whichever you prefer) and:
To look for lines: Look for newlines. If between [two newlines or [between a newline and [the beginning or end of file]]] there are non-whitespace characters, then that's a line in the matrix. Stop at the EOF.
To look for columns: Look for non-newline whitespace. If between [two whitespaces or [a whitespace and [the beginning of file or a newline or the end of file]]] there are non-whitespace characters, then that's a column in the matrix. Stop at the first newline or at the EOF.

EDIT: Hmm... This may be exceedingly robust for this, though...
Last edited on
cstrieder: No, but you can read one element at a time and call push_back(). In your matrix_columns() function you would call v.push_back(n). Have you used vectors before?
Topic archived. No new replies allowed.