Thread: For those knowing STL maps...

  1. #1
    Registered User
    Join Date
    Sep 2002
    Posts
    92

    For those knowing STL maps...

    Hi all,
    For all those who are knowleadgeable enough I have a question for you. I am creating a program for my assignment in my Data Structures course and a piece of this assignment requires me to take in a file and analyze the existence and frequency of letters in my file. This is what I have so far:
    Code:
      map<char, int> m;                                                                                   
      map<char, int>::iterator MI;                                                                        
                                                                                                          
      char ch;                                                                                            
      char c;  
    // Open file                                                                                        
      ifstream infile(argv[1], ios::in);                                                                  
      if (!infile) {                                                                                      
        cerr << "File could not be opened" << endl;                                                       
        exit(1);                                                                                          
      }
    // Populate map with letters and count the number of times it appears                               
      while(infile.get(ch)){                                                                              
        c = ch;                                                                                           
        int sum = 0;                                                                                      
        // check if the buffer variable ch is a key in the map                                            
        for(MI = m.begin(); MI != m.end(); MI++)                                                          
          {                                                                                               
            if(MI->first == c){                                                                           
              // ch MUST be an existing key, simply increment                                             
              // corresponding counter value                                                              
              sum = MI->second;                                                                           
              m[c] = sum++;                                                                               
            }                                                                                             
            else {                                                                                        
              // ch MUST be a new key and thus we need to                                                 
              // allocate a new map for this key/value pair                                               
              m[c] = 1;                                                                                   
            }                                                                                             
          }  
      }                                                                                                   
      infile.close();                                                                                     
                                                                                                          
      // output contents of map m                                                                         
      for (MI = m.begin(); MI != m.end(); MI++)                                                           
      {                                                                                                   
        cout << "key: " << MI->first;                                                                     
        cout << "value: " << MI->second << endl;                                                          
      }
    My program compiles and I do not know if I am missing something logically but as far as I can tell, it is not even entering the nested for loop. Please help.

  2. #2
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Code:
    for(MI = m.begin(); MI != m.end(); MI++)
    My knowledge of STL maps is basically nil, but I can see a potential problem with this line. Before you have added any items to the map, wouldn't m.begin() be the same as m.end()? That would stop the loop ever running.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  3. #3
    The Defective GRAPE Lurker's Avatar
    Join Date
    Feb 2003
    Posts
    949
    Originally posted by bennyandthejets
    Code:
    for(MI = m.begin(); MI != m.end(); MI++)
    My knowledge of STL maps is basically nil, but I can see a potential problem with this line. Before you have added any items to the map, wouldn't m.begin() be the same as m.end()? That would stop the loop ever running.
    Almost right. begin() would be the first element, or basically the last element, too. end() is the last element + 1 (one AFTER the end of the map). The program loops through this for once. Be sure to use the insert() function to put pairs into the map.
    Last edited by Lurker; 11-29-2003 at 09:33 PM.
    Do not make direct eye contact with me.

  4. #4
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    I appaud your use of the STL here, but you can make life easyer with just an array of 256 int's set to 0 that you index by char.

    The first problem you have is you are searching for your chars like you might from a simple array, and map provides the find() method (indeed this is the point of a map);

    Code:
    if((MI = m.find(ch)) == m.end()) {
        m[ch]=0;
    } else {
        MI->second++;
    }
    We can simpify this, because the [] operator will create a default constructed object if it does not already exist in the map. Raw int's don't have default constructors, I don't know what a map does in this situation but we can fix this easily enough.

    Code:
    class zint {
        int n;
    public:
        zint() : n(0) {}
        zint(int nn) : n(nn) {}
        operator int(){return n;}
    };
    ...
        std::map<char, zint> m;
    ...
        while(infile.get(ch)) m[ch]++;
    lurker: on an empty stl container begin()==end()

  5. #5
    Veni Vidi Vice
    Join Date
    Aug 2001
    Posts
    343
    Make a check to se if the container is empty first or else the for loop will not work. As grip pointed out
    on an empty stl container begin()==end()
    Code:
    ...
    ...
    int sum = 0;                                                                                      
    // check if the buffer variable ch is a key in the map
            
    if (m.empty())
       m[c] = 1;
    else
    { 
                                
       for(MI = m.begin(); MI != m.end(); MI++)
       ...
       ...
       ...
    
    }
    
    01000111011011110110111101100100 011101000110100001101001011011100110011101110011 01100100011011110110111001110100 01100011011011110110110101100101 01100101011000010111100101110011 0110100101101110 01101100011010010110011001100101
    Good things don´t come easy in life!!!

  6. #6
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    This code:
    Code:
    / Populate map with letters and count the number of times it appears                               
      while(infile.get(ch)){                                                                              
        c = ch;                                                                                           
        int sum = 0;                                                                                      
        // check if the buffer variable ch is a key in the map                                            
        for(MI = m.begin(); MI != m.end(); MI++)                                                          
          {                                                                                               
            if(MI->first == c){                                                                           
              // ch MUST be an existing key, simply increment                                             
              // corresponding counter value                                                              
              sum = MI->second;                                                                           
              m[c] = sum++;                                                                               
            }                                                                                             
            else {                                                                                        
              // ch MUST be a new key and thus we need to                                                 
              // allocate a new map for this key/value pair                                               
              m[c] = 1;                                                                                   
            }                                                                                             
          }  
      }
    Can be reduced to:
    Code:
    while(infile.get(ch))
       m[ch]++;
    HTH
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Very elegant, Sang-drax.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    Funny thing is that I ended up doing the exact same thing today to check some indexing code. I don't it's right that Sang should take all of the credit It's in the beginning of Stroustrup's book. The ++ thing that is.

  9. #9
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Originally posted by grib
    Raw int's don't have default constructors,
    Yes they do! (in a way)
    Try:
    Code:
    int p = int();
    cout << p;
    cout << int();
    This is very useful in template containers, such as maps.
    A map<int> will always initialize the values with 0.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems with strings as key in STL maps
    By all_names_taken in forum C++ Programming
    Replies: 3
    Last Post: 01-17-2006, 11:34 AM
  2. Hash_map, STL maps query
    By alvifarooq in forum C++ Programming
    Replies: 15
    Last Post: 06-07-2005, 09:07 AM
  3. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  4. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM
  5. STL - Maps
    By jhebert in forum C++ Programming
    Replies: 1
    Last Post: 09-03-2003, 05:13 PM