Thread: C++ exercise problem

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    9

    C++ exercise problem

    I've been working on a programming exercise and have run into a problem at the end. The goal is to write a program that outputs the number of each lower case letter in the programs own source file in a 2 column table using only 2 char variables and one int. Here is my code.

    Code:
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    
    ifstream instream;
    
    int main ()
    {
    for (char aval = 97; aval <= 122; aval++)
    {
    int count = 0;
    char b;
    instream.open("ASCII.cpp");
    while (!instream.eof())
    	{
    	instream.get(b);
    		if (aval == b)
    		{
    		count++;
    		}
    	}
    cout << aval << " " << count << "\n";
    instream.close();
    }
    return 0;
    }
    Yet when I run it I get a column of letter (as expected) but the second column only shows 0's after the first letter. I think it might have something to do with the scoping of the count variable, but I can't pin the problem down, any help is appreciated.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    while (!instream.eof())
    You shouldn't do this, it's like !feof(). Check the return value of get() instead.

    You need to clear the eof flag for insteam, or re-declare the variable. A fix would be:
    Code:
    ifstream instream.open("ASCII.cpp");
    while (!instream.eof())
    Or:
    Code:
    instream.clear();
    instream.open("ASCII.cpp");
    while (!instream.eof())
    I think it's clear(), anyway.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    すまん Hikaru's Avatar
    Join Date
    Aug 2006
    Posts
    46
    Reading the file completely for every letter is really inefficient. You can use a map instead to store all of the letters and counts by reading the file just one time.
    Code:
    #include <cctype>
    #include <fstream>
    #include <iostream>
    #include <map>
    
    int main()
    {
        std::ifstream is(__FILE__);
    
        if (is)
        {
            typedef std::map<char, int> letterMap;
    
            letterMap letters;
            char ch;
    
            while (is.get(ch))
            {
                if (std::islower(ch))
                {
                    ++letters[ch];
                }
            }
    
            letterMap::iterator iter;
    
            for (iter = letters.begin(); iter != letters.end(); ++iter)
            {
                std::cout << iter->first << ": " << iter->second << "\n";
            }
        }
    
        return 0;
    }

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    In addition, I think reading the entire file 26 times to accomplish the task is overkill.

    Consider making an array of 26 integers, one for each letter.

    Here's some very rough code to get you started:

    Code:
    int count[26];
    
    // initialize all 26 members to zero (you need a for loop)
    
    
    char b;
    while(instream.get(b)){
       if (b >= 'a' && b <= 'z')
          count[b - 'a'] ++;
    }
    
    // Then loop through all the letters and print
    for (char c = 'a', c <= 'z', c++){
    
    }
    There are other ways to do this, including std::vector or std::map.

    I'd also recommend losing the "using namespace std" and just prefixing std:: in the two places you'd need it. It's a better habit to get into.

    Edit: got beaten to the punch.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  5. #5
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    But these are limitations which the OP has to abide by. ... using only 2 char variables and one int

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    . . . and one ifstream object.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Ah. In that case I still wouldn't open and close the file 26 times, I'd open it once, and when get() returned an error, clear() and seekg(0) to get back to the beginning of the file for reading again.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  8. #8
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    One... variable! Yeah, I seriously need a life.

    Code:
    #include <iterator>
    #include <algorithm>
    #include <fstream>
    #include <iostream>
    
    int main(char c)
    {
    	if(c < 'a') c = 'a';
    	std::ifstream i("file.txt");
    	std::cout << c << " "
    		<< std::count(std::istream_iterator <char> (i), std::istream_iterator <char> (), c)
    		<< "\n";
    	if(c == 'z')
    	{
    		return 0;
    	}
    	return main(c+1);
    }
    Last edited by jafet; 09-05-2006 at 04:08 AM.
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  9. #9
    Registered User Rennor's Avatar
    Join Date
    Aug 2006
    Location
    Finland
    Posts
    45
    Quote Originally Posted by jafet
    One... variable! Yeah, I seriously need a life.
    No wonder I love to read this forum

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You've got to wonder what all these "teachers" are thinking to achieve with "can you solve this problem in 'x'" type questions.
    Interesting diversions they may be for experienced programmers, but no way to be teaching newbies how to program.

    Just how many rules has jafet broken?
    - wrong prototype for main
    - recursive call to main
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    11
    In my computer its working fine, except for the fact that it isn't displaying the 'a's and 'b's

  12. #12
    Registered User
    Join Date
    Jul 2006
    Posts
    9
    I agree, the stipulations on this problem seem a bit arbitrary, completeing the task with an array was no problem, but that would be too correct to be right. Thanks everyone for the advice, everything is working fine now.

  13. #13
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    - Implicitly assuming the high-order byte of argc will be less than 'a'
    - Implicitly assuming successful opening of file
    - ...
    Maybe I should try Lisp. It might suit my style better.

    About the assignment; perhaps the class is for embedded software developers? One can only wonder...
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    All those problems with jafet's code (that I can see) could be fixed by using a separate function to do the recursion.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  2. Problem with extremely beginner exercise
    By Molokai in forum C++ Programming
    Replies: 11
    Last Post: 05-08-2007, 09:05 AM
  3. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  4. C++ Primer 4th Edition, Problem with Exercise
    By Kaidao in forum C++ Programming
    Replies: 4
    Last Post: 07-15-2006, 11:13 AM
  5. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM