Thread: Convert string_iterator to string

  1. #1
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463

    Convert string_iterator to string

    I have a piece of code that is converting Roman Numerals to int.

    Code:
    int RomanToInt(const string & Roms){
      if (Roms.size() == 0)
        return 0;
    
      unordered_map<string,int> Rom_Map = {{"I",1},
                                           {"V",5},
                                           {"X",10},
                                           {"L",50},
                                           {"C",100},
                                           {"D",500},
                                           {"M",1000},
                                           {"IV",4},
                                           {"IX",9},
                                           {"XL",40},
                                           {"XC",90},
                                           {"CD",400},
                                           {"CM",900}};
      auto first = Roms.begin();
      auto second = next(first);
      auto third = next(second);
    
      auto res = 0;
    
      while (first != Roms.end()){
        auto cChar = string{*first};
    
        string dChar = "";
        if (second != Roms.end())
          dChar = string{*first} + string{*second};
    
        if (Rom_Map.find(dChar) != Rom_Map.end()){
          res += Rom_Map.at(dChar);
          first = third;
        }
        else if (Rom_Map.find(cChar) != Rom_Map.end()){
          res += Rom_Map.at(cChar);
          first = second;
        }
    
        second = next(first);
        third = next(second);
      }
    
      return res;
    }
    
    }
    Since I'm declaring the first type as string in my unordered_map, I have to convert the string_iterator to std::string.This looks kind of inefficient. Is there a more efficient way to do this?

    Code:
    // different way to do this? 
    auto cChar = string{*first};
    dChar = string{*first} + string{*second};
    "All that we see or seem
    Is but a dream within a dream." - Poe

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by nimitzhunter
    Since I'm declaring the first type as string in my unordered_map, I have to convert the string_iterator to std::string.This looks kind of inefficient. Is there a more efficient way to do this?
    I do not think you can avoid it: you are iterating over characters, but searching the map for strings.

    By the way, although it works for me (and presumably works for you), I believe that next(first) and next(second) actually results in undefined behaviour if Roms.begin() and next(first) resulted in a one-past-the-end iterator, respectively. I suggest re-arranging the code to avoid this, e.g.,
    Code:
    int RomanToInt(const string & Roms)
    {
        if (Roms.empty())
        {
            return 0;
        }
    
        static const auto Rom_Map = unordered_map<string, int>{{"I", 1},
                                                               {"V", 5},
                                                               {"X", 10},
                                                               {"L", 50},
                                                               {"C", 100},
                                                               {"D", 500},
                                                               {"M", 1000},
                                                               {"IV", 4},
                                                               {"IX", 9},
                                                               {"XL", 40},
                                                               {"XC", 90},
                                                               {"CD", 400},
                                                               {"CM", 900}};
    
        auto result = 0;
    
        auto first = Roms.begin();
        while (first != Roms.end())
        {
            auto valid = false;
    
            auto second = next(first);
            if (second != Roms.end())
            {
                auto found = Rom_Map.find(string{*first} + *second);
                if (found != Rom_Map.end())
                {
                    valid = true;
                    result += found->second;
                    first = next(second);
                }
            }
    
            if (!valid)
            {
                auto found = Rom_Map.find(string{*first});
                if (found != Rom_Map.end())
                {
                    valid = true;
                    result += found->second;
                    first = second;
                }
            }
    
            if (!valid)
            {
                // Throw an exception?
                break;
            }
        }
    
        return result;
    }
    Last edited by laserlight; 01-05-2016 at 12:42 AM.
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 11
    Last Post: 06-16-2011, 11:59 AM
  2. convert a vector<string> into a string
    By Joelito in forum C++ Programming
    Replies: 7
    Last Post: 02-26-2011, 06:42 PM
  3. Replies: 40
    Last Post: 06-03-2010, 12:45 PM
  4. Replies: 5
    Last Post: 05-09-2010, 10:58 AM
  5. convert char** (c string array) to std::string[]
    By umen242 in forum C++ Programming
    Replies: 2
    Last Post: 11-11-2008, 05:52 AM