std::ifstream::getline empty, in rather "big" project

Hi,

I am doing some matrix operations, and, in the process of it, need to read in matrices, or, rather, matrix lines (vectors, if you so will), into c++.

I have a system of equations with 2079 lines and 12 variables.

It is stored in a comma-separated text file E:\foot\mat.txt

a sample line looks like this:

3.727272749,0.071428575,0.071428575,0.214285716,0,0.071428575,3.636363745,0.071428575,0.071428575,0.142857149,0,0,-1000



From these 2079 lines, I want to choose 12, so that I can solve this "resulting SubMatrix" for the 12 variables.

I want to do this a fair amount, choosing different 12 lines each time. I have chosen, for now, to do 20 Choose 12 (20C12) combinations of lines, resulting in 20C12, or, 125970 sub-matrices.

I have code for solving them and all, and that is not the problem (although It'll take a while ;)). BUT, when reading in the lines, there is a problem at some point.

Let me try and break this down even further, into parts:

Part (a): Generate all possible 20C12 combinations, and store them in a manner that they can be used for any purpose (in this case, for "indexing" the lines I want to read from the "mat.txt" file.

I have an algorithm for this, which looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void do_next(std::vector<set> *newSets, int t[], int i, int n, int N )
{
	for( int j = t[i-1] + 1; j <= N - n + i; ++j)
    {
        t[i] = j;
        if( i == n)
        {
			set newSet;
            for(int k = 1; k <= n; ++k)
            {
              
				newSet.intSet.push_back(t[k]);
            }
			newSets->push_back(newSet);
        }                                
        else
        {
            do_next(newSets, t, i + 1, n, N);
        }
    }
}


and works fine. It a struct set, in order to hold an individual combination in the 20C12 set of combinations, i.e., just a set of integers. it is this:

1
2
3
4
struct set
{
	std::vector<int> intSet;
};
,

and pushes_back all these individual sets into a std::vector<set>, and, then, returns this std::vector.


So, Part (a), generating the combinations of possible lines, is done.

Then part (b):

Reading in the lines into the code, and, then, storing them in my customly defined avector struct:

1
2
3
struct avector{
	std::vector<double> doubles;
};
.

This struct stored the individual (in this case double) "numbers"/"entries", or what you will, entries in an individual vector.

The resulting avector object instances are then stored in a matrix struct:

1
2
3
struct matrix{
	std::vector<avector> vectors;
};


So far, so good.

My code, for reading in the vectors from the text file into an individual avector, and, subsequently, matrix instance, is:

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
matrix getMatrixFromSubFile(set rows, std::string fn, int factor)
{
	matrix ma;
	std::ifstream *f = new std::ifstream(fn);
	char a[10000];

	for (int i = 0; i < rows.intSet.size(); i++)
	{
		for (int j = 0; j <rows.intSet.at(i)*factor; j++)
		{
			if (j == rows.intSet.at(i)*factor -1)
			{
				f->getline(a, 10000);
				std::string szVec = std::string(a);
				avector curvec = szVectorToRealVec(szVec);
				ma.vectors.push_back(curvec);
				f = new std::ifstream(fn);
			}
			else
			{
				f->getline(a,10000);
			}

		}
	}
	f->close();
	delete f;
	return ma;
}


which should be pretty straight forward. It "loops" through the file, using std::ifstream::getline, and, once it reaches a certain line, converts the char buffer *a, or a[10000] to a std::string.

It then uses szVectorToRealVec, defined here:

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
vector szVectorToRealVec(std::string szVec)
{
	avector vec;
	bool bEOL = false;	

	int posS = 0;
	int posE = 100000000;
	int l = 0;
		
	while(bEOL != true)
	{
		std::string af;
		if(szVec.find(",") != -1)
		{
			posE = szVec.find(",");
			l = posE - posS;
			af = szVec.substr(posS, l);
			szVec = szVec.substr(af.length()+1);
		}
		else
		{
			bEOL = true;
			af = szVec.substr(posS);
		}
		_CRT_DOUBLE *curDStr = new _CRT_DOUBLE;
		_atodbl(curDStr,const_cast<char*>(af.c_str()));
		double d = double(curDStr->x);
		vec.doubles.push_back(d);
		delete curDStr;
	}

	return vec;
}


to create an avector with the current vector/line stored in the text file.

This avector is then stored in the matrix.

The condition
if (j == rows.intSet.at(i)*factor -1), i.e., the factor-1 part, in getMatrixFromSubFile is used so that I can read in lines in the range of the entire system of equations, i.e. lines in range [1,2079]. I chose 77 for the value of factor, because, I will probably later use 27C12 combinations, rather than 20C12, and, 27*77 is 2079, resulting in the max line I have in the file.

So, again, so far, so good. This works, I can generate the 20C12 combinations, and then read in the matrices. However, my part(c), subsequent solving of the matrices, later crashes, and it ALWAYS (at least so far), crashes at matrix number 43. This happens, because, for some reason, when READING IN matrix number 43, from the "mat.txt" file, using the code posted above, the line

f->getline(a, 10000);, to place the line into the char buffer a, "fails", leaving the char buffer empty.

Tracking this down further, I could see that, for this "matrix number 43", it was still able to read in the first FIVE lines of the matrix, from the text file. Using the combination number 43, generated from the previuos algorithm, and using the factor of 77, which I used, I can see that it, thus, reads in lines
77*1 (so 77), 77*2 (so 154), 77*3 (so 231), 77*4(so 308), and line 77*5 (so, 385), successfully, but, then, on the line number six, 77*6, which is 462, the line:
f->getline(a, 10000);,

fails to place anything in the char buffer, just leaving it absolutely empty (or, rather, I THINK, as an empty string "").

Verifying line 462 in my "mat.txt" file, I can see that it is:

3.363207579,0.091954023,0.068965517,0.130268201,0,0.003831418,3.6340909,0.122137405,0.110687025,0.106870227,0,0,1000
, and, that, at least from my perspective, nothing seems to be "weird" or "funny" about neither the previous, nor the next lines:

461:
3.795348883,0.114503816,0.087786257,0.156488553,0.003816794,0.003816794,3.799086809,0.07662835,0.07662835,0.107279696,0,0.007662835,-1000


or 463:
3.751162767,0.08429119,0.057471264,0.183908045,0.003831418,0,3.775701046,0.080769233,0.065384619,0.115384616,0.007692308,0.003846154,0
.

So, I have really no idea why it is failing, and, always on matrix number 43, line 6.

I am only guessing, that it might have something to do with memory allocation, somehow?

The task is at about 420,000 KB of private memory allocated, reported by task mon, at the time it crashes.


Finally, I will post my calling code, so you can see how I call the stuff defined above:

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

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<matrix> matrices;
	int toI;
	int combosize;
	while (true)
	{
		std::vector<set> *combos = new std::vector<set>;	
		std::cout << "from 1 to ";
		std::cin >> toI;
		std::cout << std::endl << "pick ";
		std::cin >> combosize;
		int * t = new int[combosize + 1];
		t[0] = 0;
		
		time_t s = time(NULL);
		do_next(combos, t, 1, combosize, toI);
		delete t;
		time_t a = time(NULL);
		time_t diff = difftime(a,s);
		std::cout << std::endl;
			
		std::cout << combos->size() << " combinations" << std::endl;
		std::cout << "t: " << diff << std::endl;

		std::string fn = std::string("E:\\foot\\combos\\combos.txt");
		std::cout << combos->size() << " printing to " << fn.c_str();
		std::cout << std::endl;

		std::cout << "size of combos is " << sizeof(combos) << std::endl;

		std::ofstream *f = new std::ofstream(fn);
		setsToFile(*combos, f); 
		f->close();
		delete f;

		std::cout << "printed" << std::endl;


		for (int i = 0; i < combos->size(); i++)
		{
			std::cout << "getting matr " << i+1 << std::endl;
			matrices.push_back(getMatrixFromSubFile(combos->at(i), "E:\\foot\\mat.txt", 77));
		}

		std::cout << "size of matrices is " << sizeof(matrices) << std::endl;
		
		for (int i = 0; i < matrices.size(); i++)
		{
			std::cout << "solving mat " << i+1 << std::endl;
			matrix ma = solveSystem(matrices.at(i));
		}


		std::cout << std::endl;

	
		delete combos;
		matrices.erase(matrices.begin(), matrices.end());
	}	
	return 0;
}


Topic archived. No new replies allowed.