What's wrong in the reading the file

Hello fellows. In the following code I am trying to read a file for some mathematical operations. DoOneFile function reads the file and when I uncomment "cout.." lines, the code prints correct values. However, when I want to read 2D dimensional matrix like "su" in the DoMath function, it does not print correct values, it gives me 2D dimensional matrix full of 0; ( If I initialize T and K with some positive values) what's wrong in my code? Thank you so much in advance
The content of data file as follows:

T= 6;
P= 5;
cap= [ 19000 19000 19000 19000 19000 19000 ];
su=[[ 689.5 689.5 689.5 689.5 689.5 ]
[ 638.0 638.0 638.0 638.0 638.0 638.0 ]
[ 827.5 827.5 827.5 827.5 827.5 827.5 ]
[ 719.5 719.5 719.5 719.5 719.5 719.5 ]
[ 618.0 618.0 618.0 618.0 618.0 618.0 ]]



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

using namespace std;

void doOneFile(int T, int K, int In, vector<vector<double>>&su,vector<double>&cap)
{
	const char* filename = "C:/Users/UserName/Desktop/9.dat";
	fstream in(filename);
	if (!in) {
		cerr << "ERROR: could not open file '" << filename << "' for reading" << endl;
		cerr << "ERROR: could not open file for reading" << endl;
		//	cerr << "usage:   " << argv[0] << " <file>" << endl;
		throw(-1); //return 1;
	}

	if (in.is_open())
	{
		string word;

		in >> word >> T >> word;
		cout << "T = " << T << endl;

		in >> word >> K >> word;
		cout << "P = " << K << endl;
		in >> word >> In >> word;
		cout << "I = " << In << endl;

		in >> word;
		cout << word << endl;

		/*** read the data*****/
		int i = 0;
		in >> word;
		cout << word;

		do
		{
			in >> word;
			if (word != "[" && word != "];" && word != " ")
			{
				int x = stoi(word);
				cap.push_back(x);
				cout << x << " ";
			}

		} while (word != "];");
		cout << endl;
		
		i = 0;
		in >> word;
		cout << word;
		do
		{
			su.push_back(vector<double>());
			do
			{
				in >> word;
				if (word != "]" && word != "[" && word != "]]" && word != " ")
				{
					double x = stod(word);
					su[i].push_back(x);
					cout << x << " ";
				}
			} while (word != "]" && word != "]]");
			cout << endl;
			i++;
		} while (word != "]]");
		cout << endl;


		
	}

	else
	{
		cerr << "File or stream not valid.\n";
	}

double DoMath(int &T, int &In, int &K, vector<vector<double>>&su,vector<double>&cap)
{
	
	//...some mathematical operations...
	//.....................
	for (int k=0;k<K;kk++)
	{ 
    		for (int t=0;t<T;t++)
    	{ 
    		cout << su[k][t] << " ";
    	}
	cout<<endl;
	}
	
	return 0;
}
int main()
{

	int T=0;
	int K=0;
	int In=0;
	vector<vector<double>>su(K, vector<double>(T));
	vector<double>cap(T);

	doOneFile(T, K, In, su, cap);
	DoMath (T,K,In,su,cap)
	
	return 0;
}

}
Last edited on
is it because T&K are not reference params, so the values gotten from the file are thrown out?
Thank you @jonnin. T and K must be taken from the file. However, if I do not initialize them in line 100, 101 and 102, whe I call the functions in 106 and 107, the code returns the initialization error. Since when I uncomment "cout<<... " lines in DoOneFile, it prints the values in the file. The problem occurs in the function DoMath, when I try to print the data. When I change
double DoMath(int &T, int &In, int &K, vector<vector<double>>&su,vector<double>&cap)
to
double DoMath(int T, int In, int K, vector<vector<double>>&su,vector<double>&cap)
the problem goes on. How can I fix the issue ?
If T and K are initialized from the file being read you don't need them instantiated in main and passed by value into your functions.

For that matter T and K don't need to be instantiated at all, the values can be derived "on the fly" as needed from your filled vectors. Declare empty vectors, 1D and 2D, in main and pass those by reference into your functions.

Fill the vectors from the data file. Properly filled vectors know their sizes, use those values when looping to "do the math".
Also.....

Using a const C++ std::string to store your filename is more appropriate than using a C string. There is a std::basic_fstream constructor overload to use C++ strings since C++11.

https://en.cppreference.com/w/cpp/io/basic_fstream/basic_fstream

You could go the extra modern step to use the <filesystem> library that became available in C++17.

https://en.cppreference.com/w/cpp/filesystem
Given the format of the provided file, this will read the data into the two vectors and display these vectors. Some error detection is provided and some flexibility regarding spaces around [:

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

using ROW = std::vector<double>;
using SU = std::vector<ROW>;
using CAP = std::vector<double>;

bool doOneFile(size_t& T, size_t& P, SU& su, CAP& cap) {
	const auto getA { [](std::istream& in, const std::string& att) {
		if (std::string line; (in >> line >> std::ws) && line.substr(0, att.size()) != att) {
			std::cout << "Invalid file format - missing " << att << '\n';
			return false;
		}

		return !!in;
	} };

	const auto getVal { [getA](size_t& val, std::istream& in, const std::string& att) {
		if (!getA(in, att))
			return false;

		return !!((in >> val) && in.ignore(std::numeric_limits<std::streamsize>::max(), '\n'));
	} };

	const auto getAttr { [getA](std::istream& in, const std::string& att) {
		if (!getA(in, att))
			return false;

		if (in.peek() == '[') {
			std::string line;

			in >> line;
		}

		return !!in;
	} };

	const std::string filename { "9.dat" };
	std::fstream in { filename };

	if (!in) {
		std::cerr << "ERROR: could not open file '" << filename << "' for reading\n";
		return false;
	}

	su.clear();
	cap.clear();

	if (!(getVal(T, in, "T=") && getVal(P, in, "P=") && getAttr(in, "cap=")))
		return false;

	for (double value {}; in >> value; cap.push_back(value));

	in.clear();
	in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

	if (!getAttr(in, "su="))
		return false;

	char t1 {}, t2 {};

	do {
		ROW row;

		for (double e {}; in >> e; row.push_back(e));

		su.push_back(row);
		in.clear();
	} while ((in >> t1 >> t2) && (t1 != ']' || t2 != ']'));

	return true;
}

double DoMath(const std::vector<std::vector<double>>& su, const std::vector<double>& cap) {
		//...some mathematical operations...
		//.....................

	for (size_t kk {}; kk < su.size(); ++kk) {
		for (size_t t {}; t < su[kk].size(); ++t)
			std::cout << su[kk][t] << " ";

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

	return 0;
}

int main() {
	SU su;
	CAP cap;
	size_t T {}, P {};

	if (doOneFile(T, P, su, cap)) {
		std::cout << "T= " << T << ", P= " << P << '\n';

		for (const auto& c : cap)
			std::cout << c << ' ';

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

		DoMath(su, cap);
	}
}



T= 6, P= 5
19000 19000 19000 19000 19000 19000

689.5 689.5 689.5 689.5 689.5
638 638 638 638 638 638
827.5 827.5 827.5 827.5 827.5 827.5
719.5 719.5 719.5 719.5 719.5 719.5
618 618 618 618 618 618


Note that the first row of su has only 5 elements rather than the expected 6
Last edited on
Topic archived. No new replies allowed.