Is this a compiler issue or is my code incorrect?

I was told to make a c++ code where, a user can choose a txt file of their choice for a dynamic 2d array. The file syntax is sort of like this:

2
3 43.3 44.4 55.5
1 4

where the first number determines the total number of rows, and the first number of each row determines how many values there are in that row. I've got the input part resolved, and the next step is to find the sum of rows and columns respectively. But for some unknown reason, upon running the code, this weird thing happens where, for the output of the columns, the value for some of the values is random and in powers of 10. the output comes out sorta like this:

Sum of Rows: 12 43.2 55.3
Sum of Columns: 166 210.1 243.3 86.8 -1.45682e+144

But if when i run the code again, a different value pops up:

Sum of Rows: 12 43.2 55.5
Sum of Columns: 166 210.1 243.3 -1.45682e+144 -1.45682e+144

Is this a compiler issue? Or is this a problem with my code? Here is the code btw:


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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>
#include <fstream>
using namespace std;

void Readfile(double**, ifstream&);
int ColumnSize(int*, int);
void RowSum(double**, int*, int);
void ColumnSum(double**, int*, int, int);

int main()
{
	double** Matrix = {};
	int Rows = {};
	char FileName[100];
	ifstream Main;

	cout << "Enter File Name here: ";
	cin >> FileName; // This will allow a user to enter their own txt file for input

	for (int i = 0; i < 100; i++)
	{
		if (FileName[i] == -52 || FileName[i] == '\0')
		{
			for (int j = i; j < (i + 4); j++)
			{
				if (j == i)
				{
					FileName[j] = '.';
				}
				else if (j == i + 1 || j == i + 3)
				{
					FileName[j] = 't';
					if (j == i + 3)
					{
						FileName[j + 1] = '\0';
					}
				}
				else if (j == i + 2)
				{
					FileName[j] = 'x';
				}

			}
			break;

		}
	}

	Main.open(FileName);

	if (Main.is_open())
	{
		cout << "This file exists!" << endl;
		cout << endl;
		Readfile(Matrix, Main);
	}
	else if (!Main.is_open())
	{
		cout << "This file does not exist." << endl;
	}
}

void Readfile(double** Matrix, ifstream& Main) // Function for reading data from the txt file
{
	int Rows = {}, Columns = {}, MaxColumnSize = {};
	Main >> Rows;
	int* MatrixColumns = new int[Rows];
	Matrix = new double*[Rows];
	
	cout << "Matrix Input is: " << endl;

	for (int i = 0; i < Rows; i++)
	{
		Main >> Columns;
		MatrixColumns[i] = Columns;
		Matrix[i] = new double[Columns];
		for (int j = 0; j < Columns; j++)
		{
			Main >> Matrix[i][j];
			cout << Matrix[i][j] << " ";
		}
		cout << endl;
		Columns = {};
	}

	Main.close();
	cout << endl;
	cout << "---------------------------------------------" << endl;
	cout << endl;
	MaxColumnSize = ColumnSize(MatrixColumns, Rows);
	cout << MaxColumnSize << endl;
	RowSum(Matrix, MatrixColumns, Rows);
	ColumnSum(Matrix, MatrixColumns, Rows, MaxColumnSize);


}

int ColumnSize(int* MatrixColumns, int Rows)
{
	int Shifter = {}, rows = Rows;
	int* M = new int[Rows];

	for (int i = 0; i < Rows; i++)
	{
		M[i] = MatrixColumns[i];
	}

	for (int i = 0; i < Rows; i++)
	{
		for (int j = 0; j < Rows; j++)
		{
			if (M[i] > M[j])
			{
				Shifter = M[i];
				M[i] = M[j];
				M[j] = Shifter;
			}
		}
	}
	return M[0];

}

void RowSum(double** Matrix, int* MatrixColumns, int Rows)
{
	double SumofRows = {};
	cout << "Sum of Matrix Rows: ";
	for (int i = 0; i < Rows; i++)
	{
		for ( int j = 0; j < MatrixColumns[i]; j++)
		{
			SumofRows += Matrix[i][j];
		}
		cout << SumofRows << " ";
		SumofRows = {};
	}
	cout << endl;
}

void ColumnSum(double** Matrix, int* MatrixColumns, int Rows, int ColumnSize)
{
	double SumofColumns = {};
	cout << "Sum of Matrix Columns: ";
	for (int i = 0; i < ColumnSize; i++)
	{
		for (int j = 0; j < Rows; j++)
		{
			if (i <= MatrixColumns[j])
			{
				SumofColumns += Matrix[j][i];
			}
		}
		cout << SumofColumns << " ";
		SumofColumns = {};
	}
	cout << endl;
}
Manual memory management is all too easy to screw up. You'd be better off using the C++ std::vector container as your Matrix container instead of a C-ish double pointer construct. Let the C++ container do all the memory management for you.

I showed you how to use a 2D std::vector as read from a file here:
https://cplusplus.com/forum/beginner/284103/#msg1230174
Try this:

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <fstream>

void Readfile(double**&, int*&, int&, std::ifstream&);
int ColumnSize(const int*, int);
void RowSum(const double*const*, const int*, int);
void ColumnSum(const double*const*, const int*, int, int);

int main() {
	char FileName[100] {};
	std::ifstream Main;

	std::cout << "Enter File Name here: ";
	std::cin >> FileName;

	//????? What's this supposed to do ???
	/*
	for (int i = 0; i < 100; i++) {
		if (FileName[i] == -52 || FileName[i] == '\0') {
			for (int j = i; j < (i + 4); j++) {
				if (j == i) {
					FileName[j] = '.';
				} else if (j == i + 1 || j == i + 3) {
					FileName[j] = 't';
					if (j == i + 3) {
						FileName[j + 1] = '\0';
					}
				} else if (j == i + 2) {
					FileName[j] = 'x';
				}

			}
			break;
		}
	}
	*/

	Main.open(FileName);

	if (Main.is_open()) {
		std::cout << "This file exists!\n\n";

		double** Matrix {};
		int* MatrixColumns {};
		int Rows {};

		Readfile(Matrix, MatrixColumns, Rows, Main);

		std::cout << "\n---------------------------------------------\n\n";

		const auto MaxColumnSize { ColumnSize(MatrixColumns, Rows) };

		//cout << MaxColumnSize << '\n';
		RowSum(Matrix, MatrixColumns, Rows);
		ColumnSum(Matrix, MatrixColumns, Rows, MaxColumnSize);

		delete[] MatrixColumns;

		for (int i = 0; i < Rows; ++i)
			delete[] Matrix[i];

		delete[] Matrix;
	} else
		std::cout << FileName << " - This file does not exist.\n";
}

void Readfile(double**& Matrix, int*& MatrixColumns, int& Rows, std::ifstream& Main) {
	Main >> Rows;
	MatrixColumns = new int[Rows] {};
	Matrix = new double* [Rows] {};

	std::cout << "Matrix Input is:\n";

	for (int i = 0; i < Rows; i++) {
		int Columns {};

		Main >> Columns;
		MatrixColumns[i] = Columns;
		Matrix[i] = new double[Columns];

		for (int j = 0; j < Columns; j++) {
			Main >> Matrix[i][j];
			std::cout << Matrix[i][j] << " ";
		}

		std::cout << '\n';
	}
}

int ColumnSize(const int* MatrixColumns, int Rows) {
	auto maxcol { MatrixColumns[0] };

	for (int i = 1; i < Rows; ++i)
		if (MatrixColumns[i] > maxcol)
			maxcol = MatrixColumns[i];

	return maxcol;
}

void RowSum(const double*const* Matrix, const int* MatrixColumns, int Rows) {
	std::cout << "Sum of Matrix Rows: ";

	for (int i = 0; i < Rows; i++) {
		double SumofRows {};

		for (int j = 0; j < MatrixColumns[i]; j++)
			SumofRows += Matrix[i][j];

		std::cout << SumofRows << " ";
	}

	std::cout << '\n';
}

void ColumnSum(const double*const* Matrix, const int* MatrixColumns, int Rows, int ColumnSize) {
	std::cout << "Sum of Matrix Columns: ";

	for (int i = 0; i < ColumnSize; i++) {
		double SumofColumns {};

		for (int j = 0; j < Rows; j++)
			if (i < MatrixColumns[j])
				SumofColumns += Matrix[j][i];

		std::cout << SumofColumns << " ";
		SumofColumns = {};
	}

	std::cout << '\n';
}



Enter File Name here: array.txt
This file exists!

Matrix Input is:
43.3 44.4 55.5
4

---------------------------------------------

Sum of Matrix Rows: 143.2 4
Sum of Matrix Columns: 47.3 44.4 55.5

Last edited on
Can OP explain the algorithm in ColumnSize(), lines 108-119, to me?

I know the function is suppose to return the max element of MatrixColumns and running it, I see that it seems to sort MatrixColumns in descending order.

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
// Example program
#include <iostream>

int ColumnSize(const int* MatrixColumns, int Rows)
{
    int Shifter = {};
    int* M = new int[Rows];

    for (int i = 0; i < Rows; i++)
    {
        M[i] = MatrixColumns[i];
    }

    for (int i = 0; i < Rows; i++)
    {
        for (int j = 0; j < Rows; j++)
        {
            if (M[i] > M[j]) 
            {
                Shifter = M[i];
                M[i] = M[j];
                M[j] = Shifter;
            }
        }
    } 
    return M[0];
}

void PrintArr(int* MatrixColumns, int Rows)
{
    for (int i = 0; i < Rows; ++i) std::cout << MatrixColumns[i] << " ";
    std::cout << "\n";
}

int main()
{
    const int Rows = 5;
    int testArr[Rows] = { 9, 10, 2, 1, 7 };
    std::cout << "Max: " << ColumnSize(testArr, Rows);
    return 0;
}


But does it always sort the array correctly?

Edited:
I went on a tangent but was curious about the correctness of this portion of code. If it fails, then OP's code might add out-of-bound values to a row sum. I think I've convinced myself the sorting works: i walks through the array and swaps itself with a greater element (pointed to by j), causing the smallest element to "trickle down" (and the largest element to bubble up; though not exactly bubblesort).
Last edited on
As the requirement of the function is to find the largest element, there's no need to sort the array. Just iterate through once to find this. See my code above.

Sum of Rows: 12 43.2 55.3
Sum of Columns: 166 210.1 243.3 86.8 -1.45682e+144

But if when i run the code again, a different value pops up:

Sum of Rows: 12 43.2 55.5
Sum of Columns: 166 210.1 243.3 -1.45682e+144 -1.45682e+144

Can you provide the input files for us to work with? These outputs don't correspond to the input example you provided.

In any case:
72
73
74
75
76
77
78
79
80
81
82
83
84
	for (int i = 0; i < Rows; i++)
	{
		Main >> Columns;
		MatrixColumns[i] = Columns;
		Matrix[i] = new double[Columns]; 
		for (int j = 0; j < Columns; j++)
		{
			Main >> Matrix[i][j];
			cout << Matrix[i][j] << " ";
		}
		cout << endl;
		Columns = {};
	}


This code snippet, Line 76 in particular, will allocate just enough space to fit the number of values in a row e.g., If line 1 of the input file has 10 values, Line 76 will allocate an array of 10 doubles. If line 2 of the input file has 5 values, Line 76 will allocate an array of 5 doubles (and the next 5 locations in memory will contain garbage).

90
91
92
93
	MaxColumnSize = ColumnSize(MatrixColumns, Rows);
	cout << MaxColumnSize << endl;
	RowSum(Matrix, MatrixColumns, Rows);
	ColumnSum(Matrix, MatrixColumns, Rows, MaxColumnSize);

You get the MaxColumnSize in Line 90 and this value is used to compute the column sum in Line 93. The issue is that ColumnSum assumes the matrix with which to compute the sum is regular i.e., if line 1 of the input file has 10 values and line 2 has 5 values, ColumnSum assumes you've allocated an array of 2-by-10 doubles (and initialized each value of the array to 0.0), which you did not do.

The result is that garbage values are used in the addition. For the input you'd provided in OP, set a conditional breakpoint on Line 150:
140
141
142
143
144
145
146
147
148
149
150
151
void ColumnSum(double** Matrix, int* MatrixColumns, int Rows, int ColumnSize)
{
	double SumofColumns = {};
	cout << "Sum of Matrix Columns: ";
	for (int i = 0; i < ColumnSize; i++)
	{
		for (int j = 0; j < Rows; j++)
		{
			if (i <= MatrixColumns[j])
			{
				SumofColumns += Matrix[j][i]; // Break here when i==1 && j==1
			}

You'll find that you're not actually adding a valid matrix value to 0.0 but actually to garbage double value at an uninitialized location.

Edited: Oops - my analysis wasn't correct. I missed the if (i <= MatrixColumns[j]) which should prevent this. I agree with seeplus' suggestion, below.
Last edited on
MatrixColumns contains the number of cols for that row (L75). Hence L150 will only be executed if the col index (i) is valid for the number of cols for that row. The condition should be < rather than <= as in my code above.
Last edited on
Topic archived. No new replies allowed.