Ignoring certain lines in a txt file when parsing - c++

I want to read files from a txt file and compare some lines with regex.
The first line of the txt file should start with the string #FIRST.
And if the string should start with a '#' the line should be ignored and it should continue. So counter should have the value 1 which it does and it should go to the second if statement if(counter==1). However it doesn't go to the second if statement.
txt file:
#FIRST
#
#haha
I expect the output to be good\ngood after the code is run once.
The output is:
good.
And it should be
good.
good.
.........
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <fstream>
#include <sstream>
int main() {
std::ifstream input("test.txt");
std::regex e("#FIRST");
std::regex b("haha");
int counter;
for (counter = 0; !input.eof(); counter++) {
std::cout << counter << "\n";
std::string line;
if (counter == 0) {
getline(input, line);
if (std::regex_match(line, e)) {
std::cout << "good." << std::endl;
counter++;
} else
std::cout << "bad." << std::endl;
break;
}
getline(input, line);
if (line[0] == '#')
continue;
if (counter == 1) {
getline(input, line);
if (std::regex_match(line, b)) {
std::cout << "good." << std::endl;
} else
std::cout << "bad." << std::endl;
break;
}
}
return 0;
}

The issue is with the break statement in the first if clause. After getting the first line of the input the program encounters the break statement and breaks out of the loop immediately. No further statements are executed within the for loop which I believe is the behavior you are seeing. You will have to restructure the program to be something like:
for loop {
getline()
if (counter == <>) {
// no break
} else if (line[0] == '#') {
continue;
} else {
// whatever else you want to get done
}
}

Related

I want my program to stop accepting input from console when I type STOP in console C++ Program

I am making a C++ program which accepts input from user (even \n) is required but the program should stop when I type STOP, so can anyone help me out. Earlier I was using getline but that also got some issue like when I enter \n two (hit enter two times) it stops the whole code.
So can anyone guide me what to do, I want to capture whole input until user types STOP in console.
Thank you.
#include <iostream>
using namespace std;
int main()
{
cout<<"Main Started\n";
char array[10];
string str;
while(fgets(array,sizeof(array),stdin))
{
str = (string) array;
if(str=="STOP") // This line is not getting executed. Also tried strcmp but of no use
break;
}
cout<<"\nMain Ended\n";
return 0;
}
You can use getline:
#include <iostream>
#include <string>
int main() {
std::cout << "Main Started\n";
std::string str;
while(std::getline(std::cin, str)) {
if(str == "STOP")
break;
}
std::cout << "\nMain Ended\n";
return 0;
}
or operator>>
#include <iostream>
#include <string>
int main() {
std::cout << "Main Started\n";
std::string str;
while(std::cin >> str) {
if(str == "STOP")
break;
}
std::cout << "\nMain Ended\n";
return 0;
}
fgets() includes '\n' in the output, if the read is terminated by ENTER, so you need to check for that, eg:
while (fgets(array, sizeof(array), stdin) != NULL)
{
str = array;
if (str == "STOP" || str == "STOP\n")
break;
}
Or:
while (fgets(array, sizeof(array), stdin) != NULL)
{
if (strcmp(str, "STOP") == 0 || strcmp(str, "STOP\n") == 0)
break;
}
std::getline() (and std::istream::getline()), on the other hand, do not include the terminating '\n' in the output:
while (getline(cin, str))
{
if (str == "STOP")
break;
}

Searching text file for specific user-inputted string

I'm trying to write a program which opens a text file full of words (a "dictionary" minus the definitions) and stores these values in strings to compare them against a user input to determine whether the user input is spelled correctly.
I go the program to work and do what I wanted, but I can't seem to figure out one specific detail. I want the program to continue running until the user enters "exit" as an input. The only problem is that my program continues spewing out either "input is spelled correctly" or "input is not spelled correctly" ad infinitum without giving the user a chance to input more values in.
How do I make it so the program only outputs one of these two options only once and then prompts the user for another input instead of a never-ending stream of the same statement? Thank you in advanced!
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string line; //holds values from txt file
string input; //holds user-inputted values
ifstream inputFile; //fstream operator declaration
bool isFound = false; //bool value to indicate if the string has been found
inputFile.open("dict.txt", ios::in);
if (inputFile)
{
cout << "Enter word to spellcheck (or exit to end)\n";
getline(cin, input);
while (input != "exit")
{
while (getline(inputFile, line))
{
if (input == line)
{
isFound = true;
break;
}
else
{
isFound = false;
}
}
inputFile.close();
if (isFound)
{
cout << input << " is spelled correctly.\n";
}
else
{
cout << input << " is not spelled correctly.\n";
}
}
if (input == "exit")
{
cout << "Ending program...\n";
}
}
else
{
cout << "Cannot open file\n";
}
return 0;
}
Inside the body of the
while (input != "exit")
loop the user is never asked to update the value of input. Moving getline(cin, input) into the while condition like this:
while (getline(cin, input) && input != "exit")
will solve that problem.
Then next problem is the handling of the dictionary file. It is closed in the middle of the loop, so subsequent reads from it will instantly fail. OP could reset the read pointer to the beginning of the file with inputFile.seekg(0);, but why reread the file every time.
Instead read the dictionary file into a std::set with more or less the same code as used in the search:
std::set<std::string> dictionary;
while (getline(inputFile, line))
{
dictionary.insert(line);
}
at the beginning of the program and search the set for the user's input in the loop.
if (dictionary.find(input) != dictionary.end())
{
cout << input << " is spelled correctly.\n";
}
else
{
cout << input << " is not spelled correctly.\n";
}
This should do the trick, you just need to move your getline block in the while loop, and move the file close statement outside the while loop:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
using namespace std;
int main()
{
string line; //holds values from txt file
string input; //holds user-inputted values
ifstream inputFile; //fstream operator declaration
bool isFound = false; //bool value to indicate if the string has been found
inputFile.open("dict.txt", ios::in);
if (inputFile)
{
while (input != "exit")
{
// Rewind file back to beginning every time
inputFile.clear();
inputFile.seekg(0,std::ios::beg);
cout << "Enter word to spellcheck (or exit to end)\n";
getline(cin, input);
while (getline(inputFile, line))
{
if (input == line)
{
isFound = true;
break;
}
else
{
isFound = false;
}
}
if (isFound )
{
cout << input << " is spelled correctly.\n";
}
else
{
if (input != "exit"){ // Don't print message if exiting
cout << input << " is not spelled correctly.\n";
}
}
}
if (input == "exit")
{
cout << "Ending program...\n";
}
inputFile.close();
}
else
{
cout << "Cannot open file\n";
}
return 0;
}

problems with seekg after getlines[which exhausts file] on ifstream

I am trying to write a program to print last line of file, and I came up with following. Where I am doing SEEKs in the file, but this code runs in an infinite loop. If I comment out (1) and enable (2), code works fine. I wasn't able to figure out the reason.
#include <iostream>
#include <fstream>
int main()
{
std::string line;
int count = 0;
long int seek_length = -1l;// should be -100l
std::ifstream ifile("D:\\cprog\\test.csv");// --(1)
while(true){
seek_length *= 2;
count = 0;
//std::ifstream ifile("D:\\cprog\\test.csv"); //-- (2)
ifile.seekg(seek_length, std::ios_base::end);
while(std::getline(ifile,line)){
++count;
}
if(count > 1)
break;
}
std::cout << line << '\n';
}
Compiler: g++ (GCC) 4.9.2 (MINGW)
You need to clear the error state on your stream before reading again:
ifile.clear();
Otherwise, the first time it encounters EOF, the stream gets into an error state and all subsequent reads will fail.
Beware that if you do this and your file only contains 1 (or 0) lines, your code in its present form will loop forever.
Final working code is following, the problem can be solved in one of the following ways.
#include <iostream>
#include <fstream>
int main()
{
std::string line;
int count = 0;
long int seek_length = -100l;
std::ifstream ifile("D:\\cprog\\test.csv");
#if 0
while(true){
seek_length *= 2;
count = 0;
ifile.seekg(seek_length, std::ios_base::end);
if( ifile.tellg() < 0 ){
ifile.clear();
ifile.seekg(0l, std::ios_base::beg);
while(std::getline(ifile,line));
break;
}
else
{
while(std::getline(ifile,line)){
++count;
}
if(count > 1)
break;
}
ifile.clear();
}
#else
char ch;
ifile.seekg(0l, std::ios_base::end);
do
{
ch = ifile.peek();
ifile.seekg(-1l, std::ios_base::cur);
std::cout << ch <<'~' << ifile.tellg() <<'\n';
}while(ch != '\n' && ifile.tellg() > -1 );
if(ifile.tellg() < 0 )
ifile.seekg(0l, std::ios_base::beg);
else
ifile.seekg(2l, std::ios_base::cur);
ifile.clear();
std::getline(ifile,line);
#endif
if(line.empty())
std::cout<<"------- EMPTY LINE -----\n";
else std::cout << line << '\n';
}

Find in C++ if a line from file contains a specific character

I've read the lines from a textfile and i want to check if that line contains the $ sign.
That's what i got so far:
int main() {
ifstream data_store;
string line;
data_store.open("c:\\test.txt");
while (!data_store.eof())
{
getline(data_store, line);
if (line.find("$"))
cout << "1: " << line << endl;
}
data_store.close();
system("PAUSE");
return 0;
}
Furthermore how can i output them to a file ?
To check if a line contains something using std::string::find to need to check the returned value from find to make sure it is a valid return. To do that we compare it against std::string::npos as that is what find() will return if it does not find anything. This is the reason it finds every line as std::string::npos is still considered true when evaluated as a bool. So refactoring your code you would have:
while (getline(data_store, line))
{
if (line.find("$") != std::string::npos)
cout << "1: " << line << endl;
}
I also changed the while loop as using eof is not how to control a while loop. for more information on that see Why is “while ( !feof (file) )” always wrong?
As far as outputting the string to a file see: How to write std::string to file?
It's a minor thing, but a variant of #NathanOliver's solution, is to use a for loop:
ifstream data_store("c:\\test.txt");
for ( string line; getline(data_store, line); ) {
if ( line.find("$") != string::npos )
cout << "1: " << line << endl;
}
// ...
The benefit here is that line is now local only to the loop, which is what it should be since that is the only place it is used.
I did it yesterday forgot to update.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool contains_number(const string &c);
int main()
{
int count = 0;
{
string line1[100];
ifstream myfile("D:/Users/Jarvan/Desktop/test.txt");
int a = 0;
if (!myfile)
{
cout << "Error opening output file" << endl;
system("pause");
return -1;
}
while (!myfile.eof())
{
getline(myfile, line1[a], '\n');
if (contains_number(line1[a]))
{
count += 1;
cout << line1[a] << "\n";
}
else cout << "\n";
}
}
cout << count <<endl;
system("pause");
return 0;
}
bool contains_number(const string &c)
{
return (c.find_first_of("$") != string::npos);
}

Removing words between < and > signs in a string c++

I'm not sure where to go from here. I know something needs to go after ifstr.get(c). It copies the exact words that I have in my text file called project.txt but I just need to remove any words that have the chars < or >?
Any help would be great. Thanks:)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
string line;
char c;
ifstream ifstr("project.txt");
ofstream ofstr("past.txt");
if(ifstr.fail()){
cout<<"error!"<<endl;
} // if
ifstr.get(c);
while(!ifstr.eof()) {
cout<<c;
ifstr.get(c);
ofstr<<line<<endl;
} // while
cout<<endl<<"copy complete"<<endl;
ifstr.close();
ofstr.close();
system ("pause");
return 0;
} // main
Pseudo-code (iostream-esque conditions) for the question in title (also removes the angle brackets):
char c;
while (read_char_succeeded(&c))
if (c == '<')
while (read_char_succeeded(&c) && c != '>')
;
else
write_char(c);
Just another shot in the dark:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream ifstr("project.txt");
ofstream ofstr("past.txt");
if(ifstr.fail()){
cout << "error!" << endl;
} // if
bool skipOutput = false;
do
{
string word;
ifstr >> word;
if(!word.empty() && word[0] == '<')
{
skipOutput = true;
}
if(!skipOutput)
{
ofstr << word << " ";
// replicate the output to stdout
cout << word;
}
if(word[word.length()-1] != '>')
{
skipOutput = false;
}
} while(!ifstr.eof());
cout << endl << "copy complete" << endl;
ifstr.close();
ofstr.close();
//system ("pause"); Doesn't compile with my system
return 0;
} // main
If you're really just want to filter out words enclosed within '<' and '>' characters this should be sufficient. If you have more complex parsing rules for your <> tags you should elaborate your question.
I'm not sure, that this is what you wanted. Please take a look at the code!
//we create a boolean value, to know if we started skipping
bool skipStarted = false;
while(ifstr.get(c))
{
//if its a '<' and we havent started skipping jet,
//then we start skipping, and continue to the next char.
if(c=='<' && !skipStarted)
{
skipStarted = true;
continue;
}
//if its a '>' and we started skipping,
//then we finish skipping, and continue to the next char.
if(c=='>' && skipStarted)
{
skipStared = false;
ifstr.get(c);
if(c==' ')
continue;
}
//if we are skipping, then we go to the next char.
if(skipStarted)
continue;
//otherwise we simply output the character.
ofstr<<c;
}