reading text file with unknown column size

Hello everyone.
I wrote a code to read a txt file with specified number of column into a vector of vector. This text file has two part, the first part starts and ends with this expression, Coordinates and end coordinates. the start and end line for the second part is elements and and elements. in this case I know the number of column but I want to change the code in a way that read the mesh for unknown number of colmun. I don;t want to use something like while (is >> ID >> x >> y >> z)
here is txt and code,

Coordinates
    1               1               1               0
    2               1  2.22044605e-16               0
    3 -2.22044605e-16               1               0
    4   -0.0101020514   -0.0101020514               0
    5              -1               1               0
    6               1              -1               0
    7  2.22044605e-16              -1               0
    8              -1 -2.22044605e-16               0
    9              -1              -1               0
End Coordinates

Elements
1 9 7 8
2 6 2 7
3 1 3 2
4 5 8 3
5 8 7 4
6 4 7 2
7 8 4 3
8 4 2 3
End Elements


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
void ReadMesh(std::string FileName) {

	int ID;
	int IDE;
	double x;
	double y;
	double z;
	int Node0;
	int Node1;
	int Node2;
	std::ifstream fin(FileName);
	if (!fin) {
		std::cout << "File is not open" << std::endl;
	}
	std::string line;
	bool ToFill1 = false;
	bool ToFill2 = false;
	int icol;

	VecDbl_t aux_coord(2, 0);
	VecIdx_t aux_conec(3, 0);

	while (getline(fin, line)) {


		std::stringstream is(line);

		if (line == "Coordinates") {
			ToFill1 = true;
		}

		if (line == "End Coordinates") {
			ToFill1 = false;
		}

		if (line == "Elements") {
			ToFill2 = true;
		}

		if (line == "End Elements") {
			ToFill2 = false;
		}

		if (ToFill1 == true) {
			while (is >> ID >> x >> y >> z) {
				aux_coord[0] = x;
				aux_coord[1] = y;
				Coordinates_.push_back(aux_coord);

			//}
		}

		if (ToFill2 == true) {
			while (is >> ID >> Node0 >> Node1 >> Node2) {
				aux_conec[0] = Node0-1;
				aux_conec[1] = Node1-1;
				aux_conec[2] = Node2-1;
				Connectivities_.push_back(aux_conec);

			}
		}
	}
	size_t Nnodes = Coordinates_.size();
	size_t Nelms = Coordinates_.size();
	for (size_t i = 0; i < Connectivities_.size(); i++) {
		for (size_t j = 0; j < Connectivities_[i].size(); j++) {
			std::cout << Connectivities_[i][j] << " ";
		}
		std::cout << std::endl;
	}

	for (size_t i = 0; i < Coordinates_.size(); i++) {
		for (size_t j = 0; j < Coordinates_[i].size(); j++) {
			std::cout << Coordinates_[i][j] << " ";
		}
		std::cout << std::endl;
	}

}

Last edited on
change it to push backs, along the lines of:
while(is >> tmp)
data.push back (tmp)

if you know the type, eg all numbers and all -1 then push back tmp-1 into a vector of numbers.
if its a mix of text and such you will have to push into a vector of strings and parse those somehow, with some rules based off the file data and what you know about it.
I have done the first option you said but it doesn't work. it gives me something like this


0 0 1 1
0 0 1 1 1
0 0 1 1 1 0
0 0 1 1 1 0 2
0 0 1 1 1 0 2 1
0 0 1 1 1 0 2 1 2.22045e-16
0 0 1 1 1 0 2 1 2.22045e-16 0
0 0 1 1 1 0 2 1 2.22045e-16 0 3
0 0 1 1 1 0 2 1 2.22045e-16 0 3 -2.22045e-16
0 0 1 1 1 0 2 1 2.22045e-16 0 3 -2.22045e-16 1
0 0 1 1 1 0 2 1 2.22045e-16 0 3 -2.22045e-16 1 0
0 0 1 1 1 0 2 1 2.22045e-16 0 3 -2.22045e-16 1 0 4
0 0 1 1 1 0 2 1 2.22045e-16 0 3 -2.22045e-16 1 0 4 -0.0101021
0 0 1 1 1 0 2 1 2.22045e-16 0 3 -2.22045e-16 1 0 4 -0.0101021 -0.0101021


0 0 0 0
0 0 0 0 8
0 0 0 0 8 6
0 0 0 0 8 6 7
0 0 0 0 8 6 7 1
0 0 0 0 8 6 7 1 5
0 0 0 0 8 6 7 1 5 1
0 0 0 0 8 6 7 1 5 1 6
0 0 0 0 8 6 7 1 5 1 6 2
0 0 0 0 8 6 7 1 5 1 6 2 0
0 0 0 0 8 6 7 1 5 1 6 2 0 2
0 0 0 0 8 6 7 1 5 1 6 2 0 2 1
0 0 0 0 8 6 7 1 5 1 6 2 0 2 1 3
0 0 0 0 8 6 7 1 5 1 6 2 0 2 1 3 4
Last edited on
If each of the set of elements is on its' own line then you can do something like thus using stringstream (not tried).

1
2
3
4
5
6
7
for (string line; getline(is, line); ) {
    istringstream iss(line);

    for (int elem{}; iss >> elem; ) {
        // Process element here
    }
}

and, you have a 2-d construct, right? rows/lines each with columns of stuff..!
so the logic would be:
for(lines)
{
for(is>>elem)
{
tmp.push_back(elem);
}
line.push_back(tmp); //push a vector of data, eg 1 2 3 4 onto a vector of lines from file
tmp.clear() //clear this or it will keep growing, appending each line's junk to the previous line's junk
}
Last edited on
This is working but if I want to skip one row or column how can I do that in for loop? specially I want to skip first column
Last edited on
Implement a column counter. If the column count is 0, you are on the first column.
If on the first column, don't do the push_back.
Last edited on
if you need more than a simple exclude first, you can provide a blacklist of columns to skip. One way is a vector of <bool> for skip/use in each spot. If you run off the end of the vector, you can choose to default keep/discard the rest by default.
eg vector<bool> blacklist(true,10);
blacklist[0] = false;
blacklist[6] = false;
...
in your loops
if(current_index >= blacklist.size() || blacklist[current_index])
push-back
else
do nothing
Last edited on
What file format is this?
It might be worth your time to use something like Wavefront OBJ — very easy to handle and almost all 3D libraries can read it.
The format is .txt
Topic archived. No new replies allowed.