text parser problem

Started by
7 comments, last by asdqwe 16 years, 3 months ago
I'm trying to make a text tool that: 1) reads a file ("test.txt") letter-by-letter then outputs the file in the console window; 2) searches the file for a word ("part") and if found, writes "found" in file "result.txt". The source is:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void main()
{
	string st1("");
	ifstream fin("test.txt");
	ofstream fout("result.txt");
	char str[100]; //stores getline()'s string
	while (fin.eof()==0)
	{
		st1=fin.get();
		cout<<st1;
		if (fin.getline(str,10,' ')=="part")
		{
			fout<<"found";
		}
	}

}
But I can't get it to work. What am I doing wrong?
Advertisement
At first glance it looks like you're reading a character, and then a line which means you're only printing the first letter of each line and only checking for 'part' in the 2nd character->end of line...
Yeah, that's the first problem. Inside your loop, you're using fin.get() to get a single character (which advances the file position by 1) and then you read a whole word (until a space). getline() also advances the file cursor by some amount, so the next get() will not read the 2nd character as you require.

You have two solutions for that, either only read 1 character at a time, or only read one line at a time. Don't mix both in one. If you really wanna do those two things separately, then have two loops. But be sure to reset the file cursor position to the beginning (use the seekg() function), and also reset the EOF flag using clear() - or else fin.eof() will always return true even after you seek to the beginning of the file.

There's a really good online resource you can use on the C++ standard library, I highly recommend you do.

http://www.cplusplus.com/reference/iostream/istream/getline.html

Another problem is the way you check for "part". Read the documentation above for getline() - it doesn't return a char string. Instead it sets the string you passed in, namely 'str' in your case. That's what you should be comparing to "part". Something like this:

fin.getline(str,10,' ');
if (strcmp(str, "part") == 0)

One problem with your approach of using ' ' as the delimiter (it reads the file up until it finds that character), meaning getline() will spit out words ending with spaces, is if the world you're looking for is at the end of the line, getline() will keep reading until it finds a space. So your string will not be one word in that case, but rather two together.

A better approach to this problem that I would do is something like this:
-use fin.getline(str, 100); to get one line at a time instead of a word at a time.
-create a 'string' object and assign 'str' to it
-use that string object containing the current line, and use its find() function to look anywhere in that string for the substring you're looking for (i.e. "part")

One last thing. Don't forget to close your files at the end of your program!

fin.close();
fout.close();

Hope that helps, and I hope I didn't make it too complicated to understand. Good luck.
Quote:Original post by shurcool
One last thing. Don't forget to close your files at the end of your program!

fin.close();
fout.close();
SC++L file stream objects clean up after themselves (including closing themselves if they are open) when they are destroyed, so there's no need to do it manually (not in this case at least - and if you do find yourself needing to do it manually, it's probably worth taking another look at your code design to see if you can let the RAII idiom do the work for you).
That's a good point, I didn't realize that. Thanks.

But I guess it's still good for the OP to understand that it's important to close files after you're done working with them, whether that happens automatically or you have to do some work to ensure that it does.
Thanks a lot shurcool, I even found another (more complicated:)) way around, without std::string:
#include <iostream>#include <fstream>using namespace std;void main(){	ifstream fin("test.txt");	ofstream fout("result.txt");	char str[1000];	fin.clear();	while (fin.eof()==0)	{		fin.getline(str, 500, '\n');		if (strstr(str, "word") != NULL)		{			fout<<"word was found";		}	}}
You're welcome, and that code looks good. Nice and simple.

Just one note, you don't really have to call clear() right after you open the file. It's only really neccessary if you iterate through the whole file and get to the end, and want to continue working with the file after that (since it resets the eof flag).
#include <iostream>#include <fstream>#include <string>using namespace std;//int, not void. C++ does not allow main to have void as return type.int main(){	string str;	ifstream fin("test.txt");	ofstream fout("result.txt");	while (getline(fin, str))	{		if (str.find("word") != string::npos)		{			fout << "word was found";		}	}}


A more idiomatic way of doing it.
Thanx Lajnold!

This topic is closed to new replies.

Advertisement