Reading Text File

I want to read a text file using following function, This functions are in class Mesh which takes std::string mesh_name in the constructor. Also the mesh name_ is class variable.

1
2
3
4
5
6
Mesh::Mesh(std::string mesh_name){

mesh_name_=mesh_name;
ReadMesh();

}


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
int Mesh::ReadMesh() {
	char line[1024];
	int num;
	double x, y, z;
	int numnodes_read = 0;
	VecInt_t numnodes;
	VecDbl_t aux;
        VecVecDbl_t mymesh;
	std::ifstream s(mesh_name_);
	s.getline(line, 1024);
	FindThisWord(s, "Start");
	for (;;) {

		if (TakeOutSpaces(s) == 1) {
			s.getline(line, 1024);
			continue;
		}
		if (!(s >> num)) {
			s.clear();
			break;
		}
		numnodes.push_back(num);
		char buf[100];
		s >> x >> y >> z;
		aux.push_back(x);
		aux.push_back(y);
		aux.push_back(z);
		s.getline(buf, 100);
		numnodes_read++;

	}
	mymesh.push_back(aux);

	FindThisWord(s, "end");

	return numnodes_read;
}


and the function FindThisWord

1
2
3
4
5
6
7
8
9
10
11
void FindThisWord(ifstream& s, const char* word)
{
    char buf[1024];
    char* pbuf;
    do {
        s >> buf;
        for (pbuf = buf; *pbuf; pbuf++) *pbuf = tolower(*pbuf);
    } while (!s.eof() && !strstr(buf, word));
    if (s.eof())
        std::cout<<"can't find word ***" << word << "*** in input file\n"<<std::endl;
}


The problem is when debugger arrives to FindThisWord function it stacks there. thanks for your help in advance.
Last edited on
a likely cause: do not use eof()
say
while(s>>buf)
{

}


your logic is probably wrong too. try strcmp, not strstr. strstr (substring) will find a match if you looked for "THE" and found OTHER
strcmp is exact match comparison.
@jonnin Thanks for your answer, but I changed that, that was not the problem.
Well, for one thing it should be "start" instead of "Start" since you are lowercasing the string you compare to.
If that's not it then you need to at least show us TakeOutSpaces and give a small example of the input.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
int TakeOutSpaces(ifstream& s)
{
    char c;
    while (1) {
        if (!s.get(c)) return -1;
        if (c == '#') return 1;
        if (c != ' ' && c != ':' && c != '=' && c != '\n' && c != '\r') {
            s.putback(c);
            return 0;
        }
    }
}


MESH "Testcase" dimension 2 ElemType Triangle Nnode 3

Start
1 0 1 0
2 1 1 0
3 0 0 0
4 1 0 0
End

This seems to work, although I'm not entirely sure what you are trying to do.

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
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <cctype>
using namespace std;

using VecInt_t    = vector<int>;
using VecDbl_t    = vector<double>;
using VecVecDbl_t = vector<VecDbl_t>;

bool SkipJunk(ifstream& s) {
    char c;
    do {
        if (!(s >> c)) // reads first non-space char
            return false; // eof
        if (c == '#') {
            s.ignore(9999, '\n');
            c = ':';
        }
    } while (c == ':' || c == '=');
    s.putback(c);
    return true;
}

void FindWord(ifstream& s, const char* word) {
    char buf[1024];
    while (s >> buf) {
        for (char *p = buf; *p; p++) *p = tolower(*p);
        if (strstr(buf, word)) return;
    }
    cout << "can't find word ***" << word << "*** in input file\n\n";
}

class Mesh {
    string mesh_name_;
    VecVecDbl_t mymesh;
public:
    Mesh(std::string mesh_name);
    void ReadMesh();
};

Mesh::Mesh(std::string mesh_name) {
    mesh_name_ = mesh_name;
    ReadMesh();
}

void Mesh::ReadMesh() {
    char line[1024];
    int num;
    double x, y, z;
    VecDbl_t aux;
    std::ifstream s(mesh_name_);
    s.getline(line, 1024);
    FindWord(s, "start");
    while (SkipJunk(s)) {
        if (!(s >> num)) {
            s.clear();
            break;
        }
        s >> x >> y >> z;
        aux.push_back(x);
        aux.push_back(y);
        aux.push_back(z);
    }
    mymesh.push_back(aux);
    FindWord(s, "end");
}

int main() {
    Mesh m("mesh.txt");
}

Thanks for your answer but when I run your code it says can't find the word Start.
its something subtle.
maybe like 54 is skipping the start keyword in your file, but not his..

try printing out what it is comparing each iteration of the loop, the words, even if they don't match, that you are passing into strstr.
Last edited on
jonnin has a good idea.
Also remember that "start" in the FindWord call needs to be all lowercase since FindWord first converts the input word to lowercase.
Thanks for your answer. It didn't work, but at the end define a bool variable like book tofill=flase, and then if line=start tofill=true. It worked.
Unless I'm missing something re the input file, this seems vastly overcomplicated for reading a file of the provided structure. Using:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <fstream>
#include <iostream>
#include <string>

int main() {
	std::ifstream ifs("mesh.txt");

	if (!ifs)
		return (std::cout << "Cannot open file\n"), 1;

	for (std::string line; std::getline(ifs, line) && line != "Start";);

	for (double x, y, z; ifs >> x >> x >> y >> z; ) {
		// Process x y z here
		std::cout << x << "  " << y << "  " << z << '\n';
	}
}


displays:


0  1  0
1  1  0
0  0  0
1  0  0


from the provided file above.
Topic archived. No new replies allowed.