WhitneyD
WhitneyD

Reputation: 127

Finding certain characters in a line of string

I want to be able to a string that contains certain characters in a file that contains one string per line.

#include <iostream>
#include <fstream>
#include <string>

int main(){
  string line;
  ifstream infile;
  infile.open("words.txt");

  while(getline(infile, line,' ')){
    if(line.find('z')){
      cout << line;
    }
  }
}

That's my attempt at finding all the string that contains the character z.

The text file contains random strings such as

fhwaofhz
cbnooeht
rhowhrj
perwqreh
dsladsap
zpuaszu

so with my implementation, it should only print out the strings with the character z in it. However, it seems to be reprinting out all the contents from the text file again.

Upvotes: 0

Views: 1110

Answers (3)

Gary Hilares
Gary Hilares

Reputation: 908

Problem:

In your file the strings aren't separated by a space (' ') which is the end delimiter, they are separated by a end of line ('\n'), that is a different character. As a consequence, in the first getline everything goes to line. line contains all the text in the file, including z's, so all the content is printed. Finally, the code exits the while block after running once because getline reaches the end of the file and fails.

If you run this code

#include <iostream>
#include <fstream>
#include <string>

int main(){
  std::string line;
  std::ifstream infile;
  infile.open("words.txt");

  while(getline(infile, line,' ')){
    std::cout << "Hi";
    if(line.find('z')){
      std::cout << line;
    }
  }
}

"Hi" will be only printed once. That is because the while block is only executed once.

Additionaly, see that line.find('z') won't return 0 if not match is found, it will return npos. See it running this code (As it says here):

#include <iostream>
#include <fstream>
#include <string>

int main(){
  std::string line;
  std::ifstream infile;
  infile.open("words.txt");

  while(getline(infile,line)){
    std::cout << line.find('z');
    if(line.find('z')){
      std::cout << line << "\n";
    }
  }
}

Solution:

Use getline(infile,line) that is more suitable for this case and replace if(line.find('z')) with if(line.find('z') != line.npos).

while(getline(infile,line)){
    if(line.find('z') != line.npos){
      std::cout << line << "\n";
    }
  }

If you need to put more than one string per line you can use the operator >> of ifstream.

Additional information:

  1. Note that the code you posted won't compile because string, cout and ifstream are in the namespace std. Probably it was a part of a longer file where you were using using namespace std;. If that is the case, consider that it is a bad practice (More info here).

Full code:

#include <iostream>
#include <fstream>
#include <string>

int main(){
  std::string line;
  std::ifstream infile;
  infile.open("words.txt");

  while(getline(infile,line)){
    if(line.find('z') != line.npos){
      std::cout << line << "\n";
    }
  }
}

Upvotes: 3

Ted Klein Bergman
Ted Klein Bergman

Reputation: 9766

getline extracts characters from the source and stores them into the variable line until the delimitation character is found. Your delimiter character is a space (" "), which isn't present in the file, so line will contain the whole file.

Try getline(infile, line, '\n') or simply getline(infile, line) instead.

Upvotes: 2

anatolyg
anatolyg

Reputation: 28300

The method find returns the index of the found character, where 0 is a perfectly valid index. If the character is not found, it returns npos. This is a special value whcih indicates "not found", and it's nonzero to allow 0 to refer to a valid index. So the correct check is:

if (line.find('z') != string::npos)
{
    // found
}

Upvotes: 1

Related Questions