Arrays, file I/O

Hello, I have a question about input and output with files. Unfortunately, file I/O was not touched at all in a previous class I was in due to its rapid pacing, so I'm pretty much in the dark here and find many tutorials confusing. Textbook is meh. A class I am in is asking to input a text file into an array and then input their sum into a new file. This is shoddy, but what I've come up with so far:

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
#include <iostream>
#include <fstream>

using namespace std; 
int main() 
{ 
	// Create variables to store matrix information in 
	int score1[2];
	int score2[4][5];
	int score3[4][5];
	int score4[2];
        int score5[3][7];
        int score6[3][7];

	int i, j;

	ifstream fin;		// Create input and output file streams 
	ofstream fout;
	
	fin.open("input.txt");		// Open up file streams   
	fout.open("output.txt");

	//i assume i should input the files here somehow?

	for (i = 0; i < 2; i++)
		score1[i] = i;

	for (i=0; i < 4; i++)
	{
		for (j=0; j < 5; j++)
		{
			score2[i][j] = i + j;
		}
	}

        for (i=0; i < 4; i++)
	{
		for (j=0; j < 5; j++)
		{
			score3[i][j] = i + j;
		}
	}

	for (i = 0; i < 2; i++)
		score4[i] = i;

	for (i=0; i < 3; i++)
	{
		for (j=0; j < 7; j++)
		{
			score5[i][j] = i + j;
		}
	}

        for (i=0; i < 3; i++)
	{
		for (j=0; j < 7; j++)
		{
			score6[i][j] = i + j;
		}
	}

	fin.close();
	fout.close();

	return 0;
}


If it helps, my file, input.txt, looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
4 5
95 36 96 6 74
71 95 13 45 38
63 94 74 93 64
96 42 83 3 39
33 34 21 26 2
36 21 47 98 3
52 55 42 92 27
37 25 71 23 51
3 7
77 48 10 5 95 15 15
82 88 35 53 6 78 14
68 60 99 80 68 54 33
2 74 89 16 8 82 95
58 62 97 92 95 94 46
60 76 61 27 10 90 63


and output.txt is supposed to look like this:

1
2
3
4
5
6
7
8
9
4 5
128 70 117 32 76
107 116 60 143 41
115 149 116 185 91
133 67 154 26 90
3 7
79 122 99 21 103 97 110
140 150 132 145 101 172 60
128 136 160 107 78 144 96
Last edited on
I don't understand what the 4 is on line 1 of input or what the 3 is on line 10 of input, they don't seem to correlate to the following lines in any way.

By the way, it's bad practice to use .open() and .close() on file streams - you should open them via the constructor and let them close themselves when they go out of scope.
Last edited on
I don't think they're really supposed to correlate to anything as much as be separate one-dimensional arrays. Since they stay the same in the output, I just assumed they're added to zero.
I think I see the pattern. There are two arrays for each pair of numbers.
The pair of numbers indicates the number of rows and columns in each of the two arrays.

I added comment lines to the input file to make this clear.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
4 5
// First 4x5 array
95 36 96 6 74
71 95 13 45 38
63 94 74 93 64
96 42 83 3 39
// Second 4x5 array
33 34 21 26 2
36 21 47 98 3
52 55 42 92 27
37 25 71 23 51
3 7
//  first 3x7 array
77 48 10 5 95 15 15
82 88 35 53 6 78 14
68 60 99 80 68 54 33
//  second 3x7 array
2 74 89 16 8 82 95
58 62 97 92 95 94 46
60 76 61 27 10 90 63  

AbstractionAnon is correct on that part. It took me a while to comprehend it without spaces in between them- I didn't understand why the new arrays were smaller until I edited my original post.

I feel like I may have to incorporate a void and value-returning function now...
Last edited on
Correlation is simple.

Input file lists:

NROWS NCOLS
a11 a12 ...
a21 a22 ...
...
b11 b12 ...
b21 b22 ...
...

The two matrices are added: A + B --> C, and the output is produced:

NROWS NCOLS
c11 c12 ...
c21 c22 ...
...


Also, it is not bad practice to open() and close() your streams when you need them. In OP's case, it would probably be easier for him to do it using ctor/dtor, but it really makes no difference.

As for reading the matrices, you must consider that the file is telling you how many rows and columns the matrix will have. You cannot, then, hardcode a bunch of matrices to use. (What if your professor tests your program with an input file that lists 3 rows and 7 columns? It will break. (4*5 = 20 elements; 3*7 = 21 elements, causing overflow and undefined behavior -- most likely a random crash.)

To read a number from the file, you'll need a variable to store the number and the following line of code:

cin >> varname ;

Here are two examples:

1
2
int nrows;
cin >> nrows;  // nrows = next integer from file 
1
2
int A[ 100 ][ 100 ];
cin >> A[ 7 ][ 3 ];  // A 8,4 = next integer from file 


Hint 1: Input with >> doesn't care about newlines. (You can read the entire file with just a bunch of >>s.)
Hint 2: Output needs you to tell it where to put newlines.
Hint 3: Give your variables meaningful names. For example, names like nrows and row are useful.
Hint 4: Either dynamically allocate space for each array, or just put an upper limit on the size of array your program will accept, and terminate (with an apology note to cerr) if the user specifies more columns or rows than you have available. I recommend the latter.

Keep in mind that you don't have to use the entire space of the array available. You may have a variable that can hold a 100 x 100 array, but if the user only gives you a 4 x 5 array, then only use the first four rows and the first five columns of that array -- ignoring everything else. Remember, you should have a couple of handy variables to keep track of how much array you are actually using (nrows, ncols).

Hint 5: Whenever you notice that you are doing the same thing over and over, that should immediately suggest to you using either a loop or a function (or both).

The input file format suggests that it may contain any number of input matrix pairs (to add). So long as you can get a next number from the file (nrows) then there is more input. If your attempt to get the next matrix pair's nrows fails, then you can quit the loop and terminate your program normally.

(Well, I often find that the attempt to write pseudocode turns out to be code itself...)
1
2
3
4
5
6
7
8
9
10
11
while (fin >> nrows)
{
  fin >> ncols;
  read_matrix( fin, A, nrows, ncols );  // Use a subfunction to do the nested read loop into A[ row ][ col ]
  read_matrix( fin, B, nrows, ncols );  // Use a subfunction to do the nested read loop into B[ row ][ col ]

  sum_matrices( A, B, nrows, ncols );  // Add the two matrices, putting the result into the first

  fout << nrows << " " << ncols << "\n";
  write_matrix( fout, A, nrows, ncols );
}

Make sure to write the functions:

1
2
3
void read_matrix( ifstream& fin, int M[100][100], int nrows, int ncols );
void sum_matrices( int A[100][100], int B[100][100], int nrows, int ncols );
void write_matrix( ofstream& fout, int M[100][100], int nrows, int ncols );

This is enough to get you started on a very-well organized answer.

Good luck!
I think this will help me out a lot, thanks. I'll get back if I have any other issues or questions. Knowing me, probably so. User-defined functions are a weak point for me right now as a newbie, even more so when arrays are involved.
This is what I have now:

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
85
86
87
88
89
90
91
92
93
#include <iostream>
#include <fstream>

using namespace std;

const int MAX_SIZE = 20;

int A[MAX_SIZE][MAX_SIZE];
int B[MAX_SIZE][MAX_SIZE];
int M[MAX_SIZE][MAX_SIZE];
int nrow, ncol;

void inputMatrix1(ifstream& fin, int A[MAX_SIZE][MAX_SIZE], int nrow, int ncol);
void inputMatrix2(ifstream& fin, int B[MAX_SIZE][MAX_SIZE], int nrow, int ncol);
void sumArrays(int A[MAX_SIZE][MAX_SIZE], int B[MAX_SIZE][MAX_SIZE], int nrow, int ncol);
void writeMatrix(ofstream& fout, int M[MAX_SIZE][MAX_SIZE], int nrow, int ncol);

int main()
{
	// Create variables to store matrix information in 

	ifstream fin;		// Create input and output file streams ifstream fin; ofstream fout
	ofstream fout;

	fin.open("input.txt");		// Open up file streams fin.open("input.txt"); fout.open("output.txt");
	if (!fin)
	{
		cout << "File not found. Program terminates." << endl;
		return 1;
	}

	fout.open("output.txt");

	cout << "How many rows are in the matrix? ";
	cin >> nrow;
	cout << endl;

	while (fin >> nrow)			// Start loop for reading in files 
	{
		fin >> ncol;

		inputMatrix1(fin, A, nrow, ncol);
		inputMatrix2(fin, B, nrow, ncol);

		sumArrays(A, B, nrow, ncol);

		fout << nrow << " " << ncol << "\n";

		writeMatrix(fout, A, nrow, ncol);
	}


	fin.close();
	fout.close();

	return 0;
}

void sumArrays(int A[MAX_SIZE][MAX_SIZE], int B[MAX_SIZE][MAX_SIZE], int nrow, int ncol)
{
	for (int nrow = 0; nrow < MAX_SIZE; nrow++)
	{
		for (int ncol = 0; ncol < MAX_SIZE; ncol++)
		{
			M[MAX_SIZE][MAX_SIZE] = A[nrow][ncol] + B[nrow][ncol];
		}
	}
}
void inputMatrix1(ifstream& fin, int A[MAX_SIZE][MAX_SIZE], int nrow, int ncol)
{
	for (int nrow = 0; nrow < MAX_SIZE; nrow++)
	{
		for (int ncol = 0; ncol < MAX_SIZE; ncol++)
			fin >> A[nrow][ncol];
	}
}
void inputMatrix2(ifstream& fin, int B[MAX_SIZE][MAX_SIZE], int nrow, int ncol)
{
	for (int nrow = 0; nrow < MAX_SIZE; nrow++)
	{
		for (int ncol = 0; ncol < MAX_SIZE; ncol++)
			fin >> B[nrow][ncol];
	}
}
void writeMatrix(ofstream& fout, int M[MAX_SIZE][MAX_SIZE], int nrow, int ncol)
{
	for (int nrow = 0; nrow < MAX_SIZE; nrow++)
	{
		for (int ncol = 0; ncol < MAX_SIZE; ncol++)
			fout << M[nrow][ncol] << " ";
		cout << endl;
	}
}


I tried to avoid making the arrays global variables, but if I place them inside of main, the void definitions claimed they were not defined. I feel like I may have missed something else within the program too...

Edit: Never mind on the inability to find the file. It ran, but it asked me for the row number twice. Looks like it put everything on one line and didn't add anything.
Last edited on
Much better.

(1)
It asks for the row number twice because you ask for the row number twice. Get rid of lines 34-36. (Why are you asking the user to tell information found in the file? Don't do that.)

Your assignment is to read a file and write a different file. There is no reason to be using cin or cout.

(2)
The point of using a function is to avoid having to duplicate code. Notice that you have two functions to read a matrix. The only difference in them is in the names of things:

  inputMatrix1  
-->  inputMatrix2
and
  A  
-->  B

See Hint 5 above in my original post. Get rid of one of the functions. It may help you to understand better if you don't use the names "A", "B", or "M" in the function. Try this:

inputMatrix(ifstream& fin, int Q[MAX_SIZE][MAX_SIZE], int nrow, int ncol)

Inside your function, all you have to care about is Q. That's the point of the argument. The array Q is whichever one your code tells it to be:

42
43
		inputMatrix(fin, A, nrow, ncol);  // Q == A
		inputMatrix(fin, B, nrow, ncol);  // Q == B 


(3)
Move your variables back into main().

I know it takes some careful reading to understand what the compiler says when it complains, but you have to pay close attention. Here's what GCC says:

a.cpp: In function 'int main()':
a.cpp:18:5: warning: unused variable 'M' [-Wunused-variable]
a.cpp: In function 'void sumArrays(int (*)[20], int (*)[20], int, int)':
a.cpp:65:4: error: 'M' was not declared in this scope

This tells us two things are wrong. The first says "unused variable 'M'". In other words, you have a variable that is not used in the function. Take another look at main(). At no point do you actually use M. The compiler noticed this and let you know.

The second problem is what you complained about. It says "'M' was not declared in this scope". Scope is anything that appears between two braces { }. It also gives you a line number (which will probably be different for you than me). If you go to that line you will find it puts you in the middle of the sumArrays() function, right where M is used.

The problem is, the function doesn't know anything about any array named "M". It only knows about an array named "A", another array named "B", an integer named "nrow", and another integer named "ncol".

If you want to put the results in "M", then you need to tell the function about it first.

void sumArrays(int M[MAX_SIZE][MAX_SIZE], int A[MAX_SIZE][MAX_SIZE], int B[MAX_SIZE][MAX_SIZE], int nrow, int ncol)

And call it appropriately:

45
46
47
		sumArrays(M, A, B, nrow, ncol);  // M = A + B

		writeMatrix(fout, _, nrow, ncol);  // which matrix do you want to write to file? 


(4)
All your functions are ignoring the values of nrows and ncols. The number of rows and columns is (nrows, ncols), not (MAX_SIZE, MAX_SIZE).

(5)
Once you get all the above problems fixed and your program works, then you can help make things easier to read with a typedef.

Since all the matrices are the same, you can give a name to the type of a matrix instead of having to spell it all out each time.

1
2
3
4
5
6
7
8
9
10
11
12
typedef int Matrix[MAX_SIZE][MAX_SIZE];

...

void inputMatrix(ifstream& fin, Matrix A, int nrow, int ncol);

...

int main()
{
	Matrix A, B, M;
	int nrows, ncols;


(6)
Finally, make sure to check that the user's matrix will fit in your matrix. Your matrix has space for a maximum of a (20, 20) matrix. What if the user gives you a (30,40) matrix?

Once you read the values for (nrows, ncols), check to see that they are <= MAX_SIZE. If they aren't, complain and halt.

Hope this helps.
Topic archived. No new replies allowed.