Thread: No errors just doesn't do what its supposed to.

  1. #16
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    The only thing I can find researching this is if I could get my ignore.dat file to write one word per line:
    word
    another
    things
    help

    Instead of how it is writing now: word another things help

    I could maybe use a getline function?

    If that would be concievable let me know. I have no clue how to get ignore.dat to write one word per line, I cant find anything on that. and the getline function is kinda blurry to me as I am a beginner.

    Thanks

  2. #17
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You write the ignored words to the file using: fileOut << word; but you don't add the line feed (endl) so that each added word would be on a separate line.

    However, you read the ignored words' list with getline. This means that each word you want to ignore, is actually a string made up of all the added words in this sequence. (No wonder there's no matches in other files.)

    You can either change the way you add the words (endl) or how you read them (while (fileIn >> word)), to read one whitespace delimited word at a time.

  3. #18
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    Dont think of this as rude but... This is the last assignment and its due tomorrow morn. here is the specifications:

    Write a c++ program to read a file (designated by the user) and count the occurences and frequency of the words in a file. You are to ignore all whitespace and punctuation. The program should ask the user for a filename. It should also read a file - ignore.dat - which contains a list of words (one per line) to ignore in the counting process. The output of your program should be each word, the number of occurences, and the percentage of occurences, displayed in decsending order of frequency.

    Now if you look at my code you will find I am not even close to following all of the requirements. But its hard to move on to those if my ignore is not working. When my program runs and counts it will count everyword in the text file and not ignore any matches in the ignore.dat file. I dont want anyone to do all of my homework for me. At the moment I just need help with this ignoring words problem.

    Thanks

  4. #19
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    Thanks I got it to write ignore.dat one word per line!! So simple .. but not for a newbie

  5. #20
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    It still counts every word in the test file though I swear I am going to cry.

  6. #21
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Read the ignore.dat file with >> operator if you don't know how the file will be laid out.

  7. #22
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Write a c++ program to read a file (designated by the user) and count the occurences and frequency of the words in a file.
    Can you even do this? You might want to use a map.

    Consider this example, which does not take into words of differing cases, or punctuation:
    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <map>
    
    int main()
    {
    	std::map<std::string, int> word_counts;
    	std::ifstream in("test.txt");
    	std::string str;
    	while (in >> str)
    	{
    		++word_counts[str];
    	}
    	in.close();
    	for (std::map<std::string, int>::iterator i = word_counts.begin();
    		i != word_counts.end(); ++i)
    	{
    		std::cout << i->first << ": " << i->second << "\n";
    	}
    }
    test.txt might contain something like:
    Code:
    how much wood would a wood chuck chuck if a wood chuck would chuck wood
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #23
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    laserlight I spent a good 5 minutes trying to figure out how I could use that in my program. I will put more time in on it as you are now the second person to suggest maps. You laid it out in a better manner than the other person did though.

    thanks

    ps this is all very complex to me I hardly understand the program I have wrote.

  9. #24
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Another example with maps.

    Run the program like this:
    programname <fileCount> <fileIgnore>.
    This will count the words in fileCount, that do not appear in fileIgnore.

    Code:
    #include <cstdlib>
    #include <iostream>
    #include <map>
    #include <string>
    #include <fstream>
    using namespace std;
    
    bool readWords( const string& fileName, map<string,int>& words ) {
      ifstream in( fileName.c_str() );
      if ( in ) {
        string word ;
        while( in >> word ) {
          words[word]++;
        }
        return true ;
      }
      return false ;
    }
    
    size_t countWords( map<string,int>& words, map<string,int>& ignore ) {
      size_t n = 0 ;
      for ( map<string,int>::iterator i=words.begin(); i!=words.end(); ++i ) {
        string word = i->first ;
        if ( ignore.find( word ) == ignore.end() ) {
          n += i->second ;
        }
      } 
      return n ;
    }
    
    int main( int argc, char* argv[] ) {
      if ( argc == 3 ) {
        string fileCount = argv[1] ;
        string fileIgnore = argv[2] ;    
        map<string,int> words, ignore ;
        if ( readWords(fileCount,words) && readWords(fileIgnore,ignore) ) {
          cout << countWords(words,ignore) << endl ;
        }
        else {
          cout << "Error reading files" << endl ; 
        }
      }
      else {
        cout << "pass 2 arguments: <fileCount> <fileIgnore>" << endl ;
      }
      return 0 ;
    }

  10. #25
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, for the case of ignored words, I suggest using a set. You should not have repeated ignored words, and a set would allow logarithmic search time to check if a word should be ignored.

    Here's another example:
    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <map>
    #include <set>
    
    int main()
    {
    	std::map<std::string, int> word_counts;
    	std::set<std::string> ignored_words;
    
    	std::string str;
    	// read set of ignored words
    	std::ifstream in("ignore.txt");
    	while (in >> str)
    	{
    		ignored_words.insert(str);
    	}
    	in.close();
    	in.clear();
    
    	// find and count frequencies of words not ignored
    	in.open("test.txt");
    	while (in >> str)
    	{
    		if (ignored_words.find(str) == ignored_words.end())
    		{
    			++word_counts[str];
    		}
    	}
    	in.close();
    
    	// display words found and their frequencies
    	for (std::map<std::string, int>::iterator i = word_counts.begin();
    		i != word_counts.end(); ++i)
    	{
    		std::cout << i->first << ": " << i->second << "\n";
    	}
    }
    The ignore.txt file might have (with a user error, note the repeated 'much')
    Code:
    much chuck much
    Of course, you have to account for upper/lower case strings and punctuation yourself. This would mean more checking, perhaps even the use of stringstreams, before settling on what is a valid 'word', and entering it to the proper set or map.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #26
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    So I compile with g++ map.cpp
    Then i type a.out and it prints ass 2 arguments: <fileCount> <fileIgnore>

    You want me yo run it like: "a.out 3 4" ?

    I can see me being annoying with this question and it just shows how dumb I am with c++.

    EDIT
    AHH I see
    a.out test.txt ignore.dat

    that actually works

  12. #27
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    Alrighty all new one here. Still doesn't work but I think this is much better. If anyone has insight as to why this is not working let me know.

    Code:
    #include <iostream>
    #include <string>
    #include <map>
    #include <vector>
    #include <fstream>
    #include <utility>
    int main(int argc, char** argv) {
    	if( argc != 3 ) {
    		std::cout<<"Usage: "
    			<<argv[0]<<" file.txt ignore.dat"<<std::endl;
    		std::exit(1);
    	}
    	std::ifstream fin(argv[2]);
    	if(!fin) {
    		std::cout<<argv[2]<<" open failed. no pony for you"<<std::endl;
    		std::exit(1);
    	}
    	std::string word;
    	std::vector<std::string> ignored;
    	while(fin>>word) {
    		ignored.push_back(word);
    	}
    	fin.close();
    	fin.open(argv[1]);
    	if(!fin) {
    		std::cout<<argv[1]<<" open failed. no pony for you"<<std::endl;
    		std::exit(1);
    	}
    	std::map<std::string, int> pony;
    	std::map<std::string, int>::iterator i;
    	std::pair<std::map<std::string, int>::iterator, bool> hah;
    	while(fin>>word) {
    		i = pony.find(word);
    		if(i == pony.end()) {
    			hah = pony.insert(std::pair<std::string, int>(word, 1));
    		}
    		else {
    			(i->second)++;
    		}
    	}
    
    	for( std::map<std::string, int>::iterator beg = pony.begin();
    		beg != pony.end(); ++beg ) {
    		if( std::find(ignored.begin(), ignored.end(), beg->first) == ignored.end() ) {
    			std::cout<<beg->first<<':'<<beg->second<<std::endl;
    		}
    	}
    	return 0;
    }

  13. #28
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    Ok I ran this from my PC here at home (I had been using telnet to the linux machines at school) and it worked flawlessly. Now when I telnet into school its a no go. No compile errors. The program runs and states that it cannot open file.txt.

    Exact error comes from my program: file.txt open failed. no pony for you

    I have tried on other linux boxes and it works for my friends puters. But not the schools.

    This assignment is due tomorrow and it counts heavily on my grade. I am in a position in the class that I will not fail but jeez, I do not want to get a bad grade. I am not sure how he will take the fact that it doesnt run. Perhaps he will know why and be able to fix it for me.

    But in the mean time I post this here for any suggestions.

    Thanks
    Jxmiller

  14. #29
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The program runs and states that it cannot open file.txt.
    The answer is that after you have read from the file with the ignored words, fin is in an eof state. This state needs to be cleared, or you would not be able to read from the next file since it is assumed to be at end of file. So, you need an fin.clear() before your fin.open(argv[1]).

    You didnt actually check for ignored words, but yeah, I still think a std::set<std::string> would be better than a std::vector or std::set for storing your list of ignored words.

    As for the actual entering of words, notice what I did. When I use operator[] to access the map, if the key doesnt already exist, it will be created, with a default value. For the case of primitive types, the default value is 0. Then I increment the element's value, hence the value would be 1. On subsequent accesses with the key, the value will just be incremented as usual.

    This means that this entire block:
    Code:
    while(fin>>word) {
    	i = pony.find(word);
    	if(i == pony.end()) {
    		hah = pony.insert(std::pair<std::string, int>(word, 1));
    	}
    	else {
    		(i->second)++;
    	}
    }
    Can be simplified to:
    Code:
    while(fin>>word) {
    	++pony[word];
    }
    And yes, pony isnt exactly the best name for a list of words.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #30
    Registered User
    Join Date
    Jun 2006
    Posts
    20
    You, are a genius. If you were here I would kiss you. My wife would just simply have to deal with it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. global namespace errors
    By stubaan in forum C++ Programming
    Replies: 9
    Last Post: 04-02-2008, 03:11 PM
  2. errors using my parser- MSVC++ 6, bhtypes.h
    By AeroHammer in forum C++ Programming
    Replies: 6
    Last Post: 01-25-2005, 07:11 PM
  3. opengl Nehe tutorial errors when compiling
    By gell10 in forum Game Programming
    Replies: 4
    Last Post: 07-14-2003, 08:09 PM
  4. executing errors
    By s0ul2squeeze in forum C++ Programming
    Replies: 3
    Last Post: 03-26-2002, 01:43 PM