Hi!
I'm trying to count the number of occurrences of each word in a text file. But program put in the file the first symbol of inputed word only (line 34) and don't enter in the for-statement (line 51). What should I serach for in my code in order to find the problem?
Thanks in advance.

#include <fstream.h>
#include <iostream.h>
#include <map.h>
#include <string>
#include <iterator>
#include <cstdlib>
#include <iomanip>
#include <conio.h>

typedef std::map<std::string, int> StrIntMap; // map for counting

void countWords(std::istream& in, StrIntMap& words) // func that count words
{
    std::string s;

    while (in >> s)
    {
        ++words[s];
    }
}

using namespace std;

int main ()
{
  char str [80];

  ofstream out("test.dat");
  if(!out) {
        cout << "Cannot open file.\n";
        return 1;
}

  do {
        cout << "Enter a word (BL to quit):\n";
        cin >> str;
        out << str;
        } while(*str != '\n'); // if empty str inputed -> stop do-while
  out.close();

  ifstream in("test.dat");
    if(!in) {
        cout << "Cannot find file.\n";
        return 1;
}


  StrIntMap w;
  countWords(in, w);

    for (StrIntMap::iterator p = w.begin( ); p != w.end( ); ++p)
    {   std::cout << "\nPress any key to close";
        std::cout << setw(30) << left  << p->first  << " occurred "
                  << setw(10)  << right << p->second << " times.\n";
    }

  std::cout << "\nPress any key to close";

getch();
return 0;
}

Thank you so much.
Could you explain how to make as a sign of completion of input is null string?

Edited 2 Years Ago by Auroch: Grammar

The first thing I notice is that the following accomplishes nothing (unless by "nothing" you wanted an infinite loop):

} while(*str != '\n'); // if empty str inputed -> stop do-while

You're using the >> operator to populate str, and that operator is delimited by whitespace. In other words, '\n' (which constitutes whitespace) will never be stored in str.

While we're here, I see that you're comfortable using C++ string objects in your code. Why use a char array for str rather than a C++ string?

Thank you. This is working code of this problem but it is necessary to set as a sign of completion of input is null string (instead symbol "BL" - line 34). How to realize input closing by the null string?

#include <fstream.h>
#include <iostream.h>
#include <map.h>
#include <string>
#include <iterator>
#include <cstdlib>
#include <iomanip>
#include <conio.h>

typedef std::map<std::string, int> StrIntMap;

void countWords(std::istream& in, StrIntMap& words)
{
    std::string s;

    while (in >> s)
    {
        ++words[s];
    }
}

using namespace std;

int main ()
{
  string str;

  ofstream out("test.dat");
  if(!out) {
        cout << "Cannot open file.\n";
        return 1;
}
  cout << "Enter a word: \n";
  while ( ( cin >> str ) && str != "BL" )
  { out << str << " ";
    cout << "Enter the next word (BL to quit):\n";
    }
  out.close();

  ifstream in("test.dat");
    if(!in) {
        cout << "Cannot find file.\n";
        return 1;
}


  StrIntMap w;
  countWords(in, w);

    for (StrIntMap::iterator p = w.begin( ); p != w.end( ); ++p)
    {   
        std::cout << setw(20) << left  << p->first  << " occurred "
                  << setw(5)  << right << p->second << " times.\n";
    }

  std::cout << "\nPress any key to close";

getch();
return 0;
}

Edited 2 Years Ago by Auroch: Quetion

I just remove line 36. Searching for 'BL' is just the same as searching for null string -I don't think you can make a std::string a null string anyway, it makes no difference. Get rid of the .h in the includes as they are not valid. Get rid off conio.h as well, it is non standard, cin.get() will suffice here.

#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <iterator>
#include <cstdlib>
#include <iomanip>


typedef std::map<std::string, int> StrIntMap;

void countWords(std::istream& in, StrIntMap& words)
{
    std::string s;

    while (in >> s)
    {
        ++words[s];
    }
}

using namespace std;

int main ()
{
  string str;

  ofstream out("test.dat");
  if(!out) {
        cout << "Cannot open file.\n";
        return 1;
}
  cout << "Enter a word BL to quit: \n";
  while ( ( cin >> str ) && str != "BL" )
  { out << str << " ";

    }

  out.close();

  ifstream in("test.dat");
    if(!in) {
        cout << "Cannot find file.\n";
        return 1;
}


  StrIntMap w;
  countWords(in, w);

    for (StrIntMap::iterator p = w.begin( ); p != w.end( ); ++p)
    {   
        std::cout << setw(20) << left  << p->first  << " occurred "
                  << setw(5)  << right << p->second << " times.\n";
    }

  std::cout << "\nPress any key to close";
std::cin.get();
//getch();
return 0;
}

Sample output

cr@cr-Aspire-V5-122P:~/Documents/cpp$ g++ -Wall -pedantic test.cc
cr@cr-Aspire-V5-122P:~/Documents/cpp$ ./a.out
Enter a word BL to quit: 
all work and no play makes jack a   dull boy
all work    and no play makes jack a dull boy
BL
a                    occurred     2 times.
all                  occurred     2 times.
and                  occurred     2 times.
boy                  occurred     2 times.
dull                 occurred     2 times.
jack                 occurred     2 times.
makes                occurred     2 times.
no                   occurred     2 times.
play                 occurred     2 times.
work                 occurred     2 times.

Edited 2 Years Ago by iamthwee

I would also change line 33. to read enter a sentence as it makes more sense.

Edited 2 Years Ago by iamthwee

OK, but it is necessary to close input by pressing "Enter" instead of typing symbols "BL". How to realize this?

You can use getline instead.

E.g.

cout << "Enter a sentence: \n";
  // while ( ( cin >> str ) && str != "BL" )
  // { out << str << " ";

  //   }
  std::getline(cin, str);
  out << str;

Edited 2 Years Ago by iamthwee

Hey Iamthwee, first off thank you for your insight, your explanation makes it more clear to me.
Thanks again!

Edited 2 Years Ago by Auroch

This question has already been answered. Start a new discussion instead.