I'm doing an assignment for school which is to simulate the grep command in C++. We are to take in a word to search, an input file to search through, and output file to output the results. The only text that should be in the output file is the contents of each line that had the search word in it, with a line number of where it was in the input file. We are supposed to use the functions of <fstream>.

I'm a beginner to c++ and am having trouble wrapping my head around this problem. I don't know how to output just the line which has the word nor how to input a way of tracking line numbers.

What I have so far:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
	string keyword, inputFile, outputFile, line;
	unsigned keywordCount = 0;

	cout << "Enter word to search for: " << endl;
	cin >> keyword;
	cout << "Enter file to search through: " << endl;
	cin >> inputFile;
	cout << "Enter file to output results to: " << endl;
	cin >> outputFile;

	ifstream in( inputFile.c_str() );
	if( !in ) {
		cout << "Could not open: " << inputFile << endl;
		return EXIT_FAILURE;
	}

	ofstream out;
	out.open( outputFile.c_str() );
	if( !out ) {
		cout << "Could not open: " << outputFile << endl;
		return EXIT_FAILURE;
	}

	while( getline( in,line ) ) {
		if( line.find( keyword ) ){
			out << line;
			++keywordCount;
		}
	}
	

	cout << keywordCount;
}

Any help is appreciated.

Recommended Answers

All 7 Replies

>>if( line.find( keyword ) ){

Should be this: if( line.find( keyword ) != string::npos ){ >>how to input a way of tracking line numbers.
Just add an integer to count the lines as they are read. Something like this:

int linecount = 0;
...
cout << "line: " << linecout << " " << line << '\n';

Thank you Ancient Dragon. I revised the search like so:

while( getline(in,line) ) {
		++lineCount;
		if( line.find( keyword ) != string::npos ){
			++keywordCount;
			out << lineCount << "\t" << line << '\n';
		}
	}
	out << "\nWords found: " << keywordCount;

This outputs the correct lines and line numbers. Only problem now is the 'keywordCount' is not picking up all the words. I think this may be becuase it is only counting one word per line, not multiple. Any way around this?

After you find a word, search again starting just after the first letter of the found word.

I am currently in high school and I am also learning c++ (noobie).
I was interested in this thread because, I have never tried coding a function that could search a string in an input file and output the results into an output file. This is my first attempt.

This piece of code may look difficult because of its size...but its actually very simple and logic.

void IOSearchString()
{
	string SearchString, InputFilePath, OutputFilePath, InputFileLine;

	cout << "Welcome!" << endl
		 << "Please enter a string you wish to find:" << endl;
	cin >> SearchString;

	cout << endl << "Please enter the input file's path and name" << endl
		 << "(e.g c://InputFilePath//InputFileName.txt)" << endl;
	cin >> InputFilePath;

	ifstream InputFile(InputFilePath);
	if(!InputFile.is_open() || InputFile.bad())
	{
		cout << endl << "Error! Failed to open: " + InputFilePath << endl;
		system("Pause");
		exit(1);
	}

	cout << endl << "Please enter the output file's path and name:" << endl;
	cin >> OutputFilePath;

	ofstream OutputFile(OutputFilePath);
	if(!OutputFile.is_open() || OutputFile.bad())
	{
		cout << endl << "Error! Failed to create/find: " + OutputFilePath << endl;
		system("Pause");
		exit(1);
	}

	if(InputFile.good() && OutputFile.good())
	{
		int CountFound = 0;
		cout << endl << "Searching for: " + SearchString << endl;
		for(int LineCount = 1; getline(InputFile, InputFileLine); ++LineCount)
		{
			for(int i = 0; i != InputFileLine.length(); ++i)
			{
				if(InputFileLine.substr(i, SearchString.length()) == SearchString)
				{
					OutputFile << "Line " << LineCount << ":" << InputFileLine << endl;
					i = InputFileLine.length() - InputFileLine.substr(i, SearchString.length()).length();
					++CountFound;
				}
			}
		}
		cout << endl << "Searching completed!" << endl;

		if(CountFound <= 0)
		{
			cout << "Found: 0" << endl;
		}
		else if(CountFound > 0)
		{
			cout << "Found: " << CountFound << endl;
		}
	}
	else
	{
		cout << endl << "Error! Stream is not good for i/o operations!" << endl;
		system("Pause");
		exit(1);
	}

	InputFile.close();
	OutputFile.close();

	string YesNo;
	cout << endl << "Would you like to make a new search?" << endl
		 << "(Y = Yes | N = No)" << endl;
	cin >> YesNo;
	if(YesNo == "Y" || YesNo == "y")
	{
		system("cls");
		IOSearchString();
	}
	else
	{
		exit(0);
	}
}

Anyways, I hope you learned something new from my code. If you have any questions related to my code, feel free to ask.

>>for(int LineCount = 1; !InputFile.eof(); ++LineCount)

That is the wrong way to read input file because eof() doesn' work like that for( line LineCount = 0; getline(InputFile, InputFileLine); ++LineCount) The >> operator doesn't accept space in the input, while getline() does. That assumes InputFileLine is of type std::string.

>>for(int LineCount = 1; !InputFile.eof(); ++LineCount)

That is the wrong way to read input file because eof() doesn' work like that for( line LineCount = 0; getline(InputFile, InputFileLine); ++LineCount) The >> operator doesn't accept space in the input, while getline() does. That assumes InputFileLine is of type std::string.

Oh, thanks I didn't know that. :0
Fixing!

Also, we frown on people posting working answers for others that they can simply use to pass their course. We call that cheating. Therefore, from now on, please help then find their own solution, not post a solution for them.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.