Hello, I'm very, very new to C++ and I'm taking computer science course right now for fun. I really want to learn C++ but I'm having a lot of trouble with this new homework assignment and I'm hoping I just take it one step at a time so I completely understand it.

I've read a lot of the topic here to help me out, but most topics that fall under this category are too complex for my understanding.

The entire problem involves reading one text file with "search words" in it and then counting the number of times these search words show up in a second text file.

From what I know of C++, I want to start by taking all of the words from the search words file (words.txt) and place them into an array which will be used for later (I can't open the search file more than once). I know how to open the file from a program I found online:

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
    while (! myfile.eof() )
    {
      getline (myfile,line);
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

I've been trying my best to work with a for loop nested in the while loop, but I just can't figure out how to do it. I get an error with each effort. My attempts at the for loop are placed right after the getline (myfile,line); and look something like this:

for(i=0;i<line.length();i++){
myfile >> word[i];
}

I delcare word as a string so it looks like:

string word[1000];

I don't even know if that is possible, but it my compiler doesn't appreciate it very much. Is there a better way of doing this? Or even just another way I could attack this problem so I can continue on?

Also, there are actually only 8 words in the file, but I can't get it to work with using the numbers 0 and 7 even.

Any help would be greatly appreciated.

Thank you.

Recommended Answers

All 26 Replies

Hello, I'm very, very new to C++ and I'm taking computer science course right now for fun. I really want to learn C++ but I'm having a lot of trouble with this new homework assignment and I'm hoping I just take it one step at a time so I completely understand it.

I've read a lot of the topic here to help me out, but most topics that fall under this category are too complex for my understanding.

The entire problem involves reading one text file with "search words" in it and then counting the number of times these search words show up in a second text file.

From what I know of C++, I want to start by taking all of the words from the search words file (words.txt) and place them into an array which will be used for later (I can't open the search file more than once). I know how to open the file from a program I found online:

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
    while (! myfile.eof() )
    {
      getline (myfile,line);
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

I've been trying my best to work with a for loop nested in the while loop, but I just can't figure out how to do it. I get an error with each effort. My attempts at the for loop are placed right after the getline (myfile,line); and look something like this:

for(i=0;i<line.length();i++){
myfile >> word[i];
}

I delcare word as a string so it looks like:

string word[1000];

I don't even know if that is possible, but it my compiler doesn't appreciate it very much. Is there a better way of doing this? Or even just another way I could attack this problem so I can continue on?

Also, there are actually only 8 words in the file, but I can't get it to work with using the numbers 0 and 7 even.

Any help would be greatly appreciated.

Thank you.

I've typed some code. Try it.

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  char line[100];
  int i=0;
  
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
    while (! myfile.eof() )
    {
      if(i<100)//check out of bounds runtime error
          myfile.get(line[i++]);
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

I gave it a try, but when I placed this outside the code:

cout << line[2] << endl;

nothing popped up in the window. And the third letter is not a space (neither is the second or fourth for that matter)

Here is what the file looks like:

cats
dog
mouse
frog
the
pipe
two
three

And that's the entire file of words that need to be read. Is there anyway to make an array that would be like:

string word[7];

where word[0] would be cats and word[7] would be three?

Thanks for helping though, zhelih.

I gave it a try, but when I placed this outside the code:

cout << line[2] << endl;

nothing popped up in the window. And the third letter is not a space (neither is the second or fourth for that matter)

Here is what the file looks like:

cats
dog
mouse
frog
the
pipe
two
three

And that's the entire file of words that need to be read. Is there anyway to make an array that would be like:

string word[7];

where word[0] would be cats and word[7] would be three?

Thanks for helping though, zhelih.

Try that, i think it is OK:

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string lines[10];
  char word[10];
  int i=0;
 
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
//read 5 words
    for(i=0; i<5; ++i) {
        myfile.get(word, 10);//token is \n
        string[i]=word;
   }

        
    myfile.close();
  }
 
  else cout << "Unable to open file"; 
 
  return 0;
}

I've never worked with string so that is a bit hard for me.

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
int main () {
  char line[100];
  string words[10];
  int i=0;
 
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
	  for(i=0; i<5; ++i) {
          myfile.getline(line, 10);
		  words[i]=line;
		  strcpy(line, "");
    }
    myfile.close();
  }
 
  else cout << "Unable to open file"; 


  for(i=0; i<5; ++i)
	  cout<<words[i]<<endl;
 
  return 0;
}

This is working, 100% percent.

In my mind, I'm giving you the biggest high five ever.

Thanks a ton for the help. There's still a lot left for me to do in the program, I'll be back when I run into my next wall.

Thank you.

Here is my code so far:

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

int main () {
 char line[100];
 string words[10];
 int i=0;

 ifstream myfile ("word_list.txt");
 if (myfile.is_open())
 {
	 for(i=0; i<8; i++){
		 myfile.getline(line,10);
		 words[i]=line;
		 strcpy_s(line, "");
	 }
	 myfile.close();
 }

 else cout << "Unable to open file" << endl;

 //The search words have been stored in an array called words[i]

 for(i=0; i<8; i++){
	 cout << words[i] << endl;
	 }

 //Now the search words are displayed on the screen

 int j = 0;
 string poem[16];
  ifstream checkfile ("script.txt");
  if (checkfile.is_open())
  {
    while (! checkfile.eof() )
    {
		for(j=0; j<17; j++){
			getline (checkfile,poem[j]);
			cout << poem[j] << endl;
		}
    }
    checkfile.close();
  }

  else cout << "Unable to open file" << endl; 


 //A new file called script.txt is now opened and stored in the array poem[16]

int k = 0;
int word_appearances = 0;

for(i=0; i<8; i++){
	for(j=0; j<17; j++){
		getline(cin, poem[j], '\n');
		for(k = poem[j].find(words[i], 0); k != string::npos; k = poem[j].find(words[i], k)){
			word_appearances++;
			k++;
		}
	}
}

cout << word_appearances << endl;

 return 0;
}

Everything seems to be going okay... except for the last part when I'm trying to get the word_appearances to count how many of the search words are in the poem written inside script.txt. Here is the code I found online that I tried to use, does anyone know what I'm doing wrong?

string input;
int i = 0;
int cat_appearances = 0;

getline(cin, input, '\n');

for(i = input.find("cat", 0); i != string::npos; i = input.find("cat", i))
{
    cat_appearances++;
    i++;  // Move past the last discovered instance to avoid finding same
          // string
}
cout<<cat_appearances;

The above code for finding the word cat in a string works just fine. Any ideas?


Everything seems to be going okay... except for the last part when I'm trying to get the word_appearances to count how many of the search words are in the poem written inside script.txt.

You need only two for() loops to iterate over the strings i.e. something like below.

int word_appearances = 0;

        // i must be less than 10 and some string is needed at the index (i)
	for(i=0; i < 10 && words[i].length(); i++)
	{
                // j must be less than 16 and some string is needed at the index (j)
		for(j=0; j < 16 && poem[j].length(); j++)
		{
                        // are the words are identical 
			if(poem[j] == words[i])
			{
                                // yes they are
				cout << "match: " << words[i] << endl;
				word_appearances ++;
			}
		}
	}

	cout << word_appearances << endl;

I know how to open the file from a program I found online:

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
    while (! myfile.eof() )
    {
      getline (myfile,line);
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

That code that you found won't work properly anyway, because it uses eof() to check if it's at the end of a file. eof() only returns 'true' after a failed attempt at reading the file, which means you'll get the last line twice.

I've typed some code. Try it.

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  char line[100];
  int i=0;
  
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
    while (! myfile.eof() )
    {
      if(i<100)//check out of bounds runtime error
          myfile.get(line[i++]);
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

Horrid "solution", if you can call it that.

Try that, i think it is OK:

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string lines[10];
  char word[10];
  int i=0;
 
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
//read 5 words
    for(i=0; i<5; ++i) {
        myfile.get(word, 10);//token is \n
        string[i]=word;
   }

        
    myfile.close();
  }
 
  else cout << "Unable to open file"; 
 
  return 0;
}

Also horrible. You're mixing chars and strings, using weird input methods, and hardcoding in the number of loops it's going to take. Just because it works doesn't mean it's correct.

I've never worked with string so that is a bit hard for me.

Then why are you trying to help someone who's using string ?

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
int main () {
  char line[100];
  string words[10];
  int i=0;
 
  ifstream myfile ("word.txt");
  if (myfile.is_open())
  {
	  for(i=0; i<5; ++i) {
          myfile.getline(line, 10);
		  words[i]=line;
		  strcpy(line, "");
    }
    myfile.close();
  }
 
  else cout << "Unable to open file"; 


  for(i=0; i<5; ++i)
	  cout<<words[i]<<endl;
 
  return 0;
}

This is working, 100% percent.

Yikes.

This is a much, much better method of inputting your words:

string words[100];
int i = 0;

if (myfile)
{
   while ( (myfile >> words[i]) && (i < 100) )
   {
      i++;
   }
}
else
{
   cout << "Unable to open file" << endl;
   exit(0); // remember to QUIT if the file can't be opened!
}

myfile >> words[i] basically grabs words that are separated by whitespace (including newlines). This means that it doesn't matter if all your words in your text file are in the same line, on separate lines, double-spaced; it doesn't matter. The second benefit of using this is that it returns false if the read was unsuccessful (for example, if it's reached EOF), so it can be used as a while() loop condition. This eliminates the need to use the eof() function. Finally, I added a second condition in the while() loop to prevent buffer overruns in the case of files that have more than 100 words.

Thank you a ton for your help. I was able to do the entire first version of my program with your help. I'm currently working on the harder "Second" version of this program for the class and things were looking really good, but I've hit a snag.

I need to find a way to know if a string has an asterik in it. I've found a few really roundabout ways online how to do it. But is there any way to tell if a string has asteriks or not as well as the position of these asteriks (sometimes there are multiple asteriks).

I haven't learned anything about position yet in strings, I know you can you a position function or something like that. And the tutorials online are really getting over my head. I don't understand how to use:

char at(int position)

Any tips?

>I need to find a way to know if a string has an asterik in it.
Very simple.

size_t pos;
pos = myString.find('*');

In the above example, 'pos' is set to the position of the first asterisk in the string. If it wasn't found, pos == string::npos will be true.

Thanks for your help again, but I still don't understand the entire thing well enough to solve my problem.

Here's an example that if someone could do out for me, I think I could understand how to do it for my program.

Let's say that:

string MyString = "The rabbit likes to ea! carro!s";

And I want to change the exclamation points to the letter t for both the exclamation points. I know now how to find the position of the first exclamation point, but how would I go on after that.

Thanks for your help.

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

int main()
{
  string MyString = "The rabbit likes to ea! carro!s";
  cout << MyString << '\n' ;
  replace_copy( MyString.begin(), MyString.end(), 
                MyString.begin(), '!', 't' ) ;
  cout << MyString << '\n' ;
}

You can also use the size_t value returned from find() to reference the character in the string. For example:

string MyString = "The rabbit likes to ea! carro!s";
size_t pos = MyString.find('*');
MyString[pos] = 't';

That would change the first '!' to a 't'. If you wanted to replace all of them, you'd have to pass pos as a second argument to find() (so that it starts searching where it left off), and then you'd make a loop. However, as vijayan so nicely pointed out, it's much easier to do a lot of find/replace with the STL function replace_copy .

Alright, I'm still having a lot of trouble with my manipulation of this program.

Here's a closer scenario to what I need to do.

I have an array called search_words[7]

I also have an array called words[1000]

So far, my program is able to count every time one word from the search_word array is in the words array.

Some of the search_words; however, have exclamation points in them.

So an example of this search_words array would be:

cats
dog
mouse
hors!
ch!ck!n
!h!
green
pepsi

These exclamation points are supposed to represent any letter. They can be a, L, *, 4, etc. I've tried deleting the exclamation points and I've tried the replace method, but neither of these seem to be doing me so much good. The deleting method ruins the word sometimes (like ch!ck!n). And the replacing method is hard for me to solve when there are two exclamation points since the way I've been doing it says that I just replace the exclamation points with the same letter. I'm thinking the best way to do this might just be to break apart these strings even further. Something along the lines of, taking ch!ck!n and breaking it into ch, !, ck, !, and in, and then checking the position of ch, ck, and in. Does anyone have any tips on that idea? Or maybe even another way of looking at it.

Sorry I have to be so cryptic with everyone. Our entire class has this project to do and there's been a lot of trouble with people copying other people's programs. You get an F in the class if someone else uses your code because everyone is supposed to have something different.

But your help is much appreciated.

> my program is able to count every time one word from the search_word array is in the words array.
> Some of the search_words; however, have exclamation points in them...

use the same logic, but while comparing strings, make sure that an '!' in the search_word matches any char in the corrospong position in the word.

bool equals( const std::string& search_word,
             const std::string& word )
{
  if( search_word.size() == word.size() )
  {
    for( std::size_t i=0 ; i<search_word.size() ; ++i )
    {
      if( ( search_word[i] != '!' ) &&
          ( search_word[i] != word[i] ) ) return false ;
    }
    return true ;          
  }
  else return false ;
}

I'm sorry vijayan. Could you just explain what's going on in that code for me. This is well above my head. I'm really just learning all of this for the first time.

Thanks.

Basically when you compare 2 strings, you have to compare each individual character. Therefore, you need a loop.

Inside the loop, you only want to compare characters from search_words that aren't exclamation marks.

If you'll just focus on this line:

if( ( search_word[i] != '!' ) && ( search_word[i] != word[i] ) )

Look carefully at what it does. First, it checks to see if it's an exclamation mark. If so, it'll match everything, and so you don't compare it. If it isn't an exclamation mark, it compares it.

If the characters don't match, the function returns false.

The rest of the code is pretty simple. There's a loop that goes through the entire string. The beginning of the function is merely optimization:

if( search_word.size() == word.size() )

Because obviously if the strings aren't the same length then there's no point in comparing them.

Hope that made sense.

// search_word is one word from the search_words array
// word is one word from the words array
// equals returns true if there is a match, false otherwise
bool equals( const std::string& search_word, 
             const std::string& word )
{
  if( search_word.size() == word.size() )
  {
    // test char by char for all the chars
    for( std::size_t i=0 ; i<search_word.size() ; ++i )
    {
      if( ( search_word[i] != '!' ) &&
          // if any char (which is not '!' ) in the search_word 
          // is different from the corrosponding char in word
          // there is no match; return false
          ( search_word[i] != word[i] ) ) return false ;
    }
    // if every character (other than !) in search_word
    // matches the corrosponding char in word and
    // both have the same number of chars, there is a match
    return true ;
  }
  else return false ; // different sizes, no match
}

I'm really starting to understand more and more with your help. The problem currently is:

when words = within

and search_words = !h!

the counter is supposed to go up one since there is a match, any tips on this dilemma?

Also, if anyone wants to see my full code, I can send it to you via PM, but I cannot post it here due to the chance that someone might find and copy it.

My code can find substrings based off code I found online which looked like this:


string input;
int i = 0;
int cat_appearances = 0;

getline(cin, input, '\n');

for(i = input.find("cat", 0); i != string::npos; i = input.find("cat", i))
{
    cat_appearances++;
    i++;  
}
cout << cat_appearances << endl;

I just need a way for these exclamation points to be a place holder of some sort. Just so for !h!, "within" would increase the counter by one but words like "hope" would not increase the counter since there isn't a letter before the h.

EDIT:

Here's some code that I'm working with to try to get this. I think if I can understand this, I'll be all set with the program:

string search = "!h!"; //The search word
string check[2]     //The array to  be checked
check[0] = "They"   //Should increase counter by one
check[1] = "here"   //Should NOT increase counter
check[2] = "within" //Should increase counter by one
int counter = 0;    //Counter will count how many times the search word is in the array check[2]

size_t pos = search.find('!');
search[pos] = 't';

cout << search << " " << pos << endl;

well, you need to try for matches for all possible substrings in word.

bool match( const std::string& search_word,
                      const std::string& word )
{
  if( search_word.size()  <= word.size() )
  {
    std::size_t N =  word.size() -  search_word.size() ;

    // pos is the position where the substring starts
    for( std::size_t pos=0 ; pos <= N ; ++pos )
    {
      std::size_t i = 0 ;
      for(  ; i<search_word.size() ; ++i )
      {
        if( ( search_word[i] != '!' ) &&
            ( search_word[i] != word[pos+i] ) ) break ;
      }
      // if the entire search_word has been matched
      if( i == search_word.size() ) return true ;          
    }
  }
  return false ;
}

I'm sorry, I'm still not understanding. For some reason my compiler thinks this code is bad. It says

error C2601: 'match' : local function definitions are illegal

and

this line contains a '{' which has not yet been matched

may I have a clarification on what's going on wrong?

int main () {

string search_word = "!h!";
string word = "within";

bool match(const std::string& search_word, const std::string& word)
{
	if(search_word.size() <= word.size())
	{
		std::size_t N = word.size() - search_word.size();

		for(std::size_t pos=0; pos <= N; ++pos)
		{
			std::size_t i = 0;
			for( ; i<search_word.size(); ++i)
			{
			if( (search_word[i] != '!' ) && ( search_word[i] != word[pos+i] )) break;
			}
		if(i == search_word.size()) cout << "return true" << endl;
		}
	}
cout << "return false" << endl;
}
return 0;
}

>> may I have a clarification on what's going on wrong?

You had misplaced the match() function inside the main() function, that is prohibited.
You also had taken out the return statements from the match() function, now they are restored.

So try the following ...

bool match(const std::string& search_word, const std::string& word)
{
	if(search_word.size() <= word.size())
	{
		std::size_t N = word.size() - search_word.size();

		for(std::size_t pos=0; pos <= N; ++pos)
		{
			std::size_t i = 0;
			for( ; i<search_word.size(); ++i)
			{
			if( (search_word[i] != '!' ) && ( search_word[i] != word[pos+i] )) break;
			}

		    if(i == search_word.size()) 
                         return true;
		}
	}
   
   return false;
}

int main () {

string search_word = "!h!";
string word = "within";

// Do the search by calling the function ...
bool bMatch = match(search_word, word);

// The bool value is now either true or false, so here you can test 
// whether there was a match and output the result

if(true == bMatch)
{
    cout << "A match .." << endl;
}
else
{
     cout << "no match .." << endl;
}

return 0;
}

ALL set!

I really can't thank everyone enough for your help. My program is working just fine and I got the desired answer and everything. I'm going to have my teacher check it out, and make sure everything is good, so I don't want to close this topic for good just in case there are a few things that I might need clarification about. I'm supposed to be able to fully explain my program to someone who knew as much as I did about programming before I got help.

Thanks again.

well, you need to try for matches for all possible substrings in word.

bool match( const std::string& search_word,
                      const std::string& word )
{
  if( search_word.size()  <= word.size() )
  {
    std::size_t N =  word.size() -  search_word.size() ;

    // pos is the position where the substring starts
    for( std::size_t pos=0 ; pos <= N ; ++pos )
    {
      std::size_t i = 0 ;
      for(  ; i<search_word.size() ; ++i )
      {
        if( ( search_word[i] != '!' ) &&
            ( search_word[i] != word[pos+i] ) ) break ;
      }
      // if the entire search_word has been matched
      if( i == search_word.size() ) return true ;          
    }
  }
  return false ;
}

But that code only checks for all possible matches at the beginning and end of a string. I was under the assumption that a search word like some!g would match something , which your function does not.

If I were implementing this, I would probably parse the search string for '!', and split it into a vector of substrings, then search the word sequentially for each one (keeping track of the location of the previous string to keep them in order).

Actually, the ! can only represent one character. So som!g wouldn't count for something, but som!t would count for something. I'll keep taking a look at it to check and make sure things are okay.

Actually, the ! can only represent one character. So som!g wouldn't count for something, but som!t would count for something. I'll keep taking a look at it to check and make sure things are okay.

Ah, okay. The way you explained it previously made it sound like '!' was supposed to match all possible expressions.

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.