【问题标题】:C++ how to get ONLY integers from complex stringC ++如何从复杂字符串中仅获取整数
【发布时间】:2015-01-26 06:16:46
【问题描述】:

我有几个字符串,每个字符串包含一个单词和几个整数(一个字符串是整行):

Adam 2 5 1 5 3 4
John 1 4 2 5 22 7
Kate 7 3 4 2 1 15
Bill 2222 2 22 11 111

如您所见,每个单词/数字都用空格分隔。现在,我想将这些数据加载到地图中,其中单词(名称)将是键,值将是行中数字的向量。我已经在单独的临时 stl 容器中有键值,所以任务是只将每行中的整数加载到 2D 向量中,然后将这两个合并到 map 中。 问题是,是否有任何 C++ 函数可以避免单词和空格并仅从字符串中获取整数,或者我必须逐个字符地搜索字符串 here?

我只找到了部分解决方案,无法获得多个数字:

vector<int> out;

for (int i = 0; i < line.length(); i++) {

    if (isdigit(line.at(i))) {  
        stringstream const_char;
        int intValue;
        const_char << line.at(i); 
        const_char >> intValue;
        out.push_back(intValue);
    }
}

【问题讨论】:

  • 名字总是排在第一位吗?
  • 在这个例子中是的,但是在任何地方找到解决方案都会很有用

标签: c++ string integer stdvector


【解决方案1】:

如果每一行的格式都是“字数数数...”,则使用字符串流并通过阅读跳过该单词。

如果当前行在line:

vector<int> out;
istringstream in(line);
string word;
in >> word;
int x = 0;
while (in >> x)
{
    out.push_back(x);
}

【讨论】:

    【解决方案2】:

    split 空格上的字符串,因为这似乎是您的分隔符。然后检查每个子字符串是否包含一个带有strol 的int。

    然后使用stoi将整数子串转换为int。

    如果不能进行stoi转换(字符串不包含数字),会抛出invalid_argument异常,所以不要尝试转换name子字符串。

    #include <iostream>
    #include <vector>
    #include <string>
    #include <sstream>
    #include <cstdlib>
    
    std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
        std::stringstream ss(s);
        std::string item;
        while (std::getline(ss, item, delim)) {
            elems.push_back(item);
        }
        return elems;
    }
    
    
    std::vector<std::string> split(const std::string &s, char delim) {
        std::vector<std::string> elems;
        split(s, delim, elems);
        return elems;
    }
    
    inline bool isInteger(const std::string & s)
    {
       if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ;
    
       char * p ;
       strtol(s.c_str(), &p, 10) ;
    
       return (*p == 0) ;
    }
    
    
    int main()
    {
       std::cout << "Hello World" << std::endl;
    
       std::string example="Adam 2 5 1 5 3 4";
    
       std::vector<std::string> subStrings;
    
       subStrings = split(example, ' ');
    
       std::string sItem;
       for(std::vector<std::string>::iterator it = subStrings.begin(); it != subStrings.end(); ++it) {
            sItem = *it;
            if( isInteger(sItem) ){
                int nItem = std::stoi (sItem);
                std::cout << nItem << '\n';
            }
        }
    
       return 0;
    }
    

    【讨论】:

      【解决方案3】:

      如果名称总是在字符串的开头,则使用 string Class 的 find() 和 substr() 查找名称。

      std::string s = "Adam 2 5 1 5 3 4";
      std::string delimiter = " ";
      s.substr(0, s.find(delimiter)); //To get the name
      s.erase(0, s.find(delimiter)); //To delete the name
      //Repeat the mechanism with a for or a while for the numbers
      

      我没有测试这个解决方案,但我总是使用类似的东西,总是把标签放在第一位。

      如果名称可以在任何地方,如果不检查每个字符,我看不出如何测试它。

      【讨论】:

        【解决方案4】:

        这是一个程序,演示了可以使用的任务方法。

        #include <iostream>
        #include <string>
        #include <vector>
        #include <map>
        #include <sstream>
        #include <iterator>
        
        int main() 
        {
            std::string s( "Adam 2 5 1 5 3 4" );
            std::map<std::string, std::vector<int>> m;
            std::string key;
            std::istringstream is( s );
        
            if ( is >> key )
            {
                m[key] = std::vector<int>( std::istream_iterator<int>( is ),
                                           std::istream_iterator<int>() );
            }
        
            for ( const auto &p : m ) 
            {
                std::cout << p.first << ": ";
                for ( int x : p.second ) std::cout << x << ' ';
                std::cout << std::endl;
            }
        
            return 0;
        }
        

        输出是

        Adam: 2 5 1 5 3 4
        

        【讨论】:

          【解决方案5】:

          假设名称在前,这里有一个函数会读取字符串并添加到地图中。

          #include <map>
          #include <vector>
          #include <sstream>
          #include <string>
          #include <algorithm>
          
          using namespace std;
          
          typedef std::map<std::string, std::vector<int> > StringMap;
          
          void AddToMap(StringMap& sMap, const std::string& line)
          {
              // copy string to stream and get the name
              istringstream strm(line);
              string name;
              strm >> name;
          
              // iterate through the ints and populate the vector
              StringMap::iterator it = sMap.insert(make_pair(name, std::vector<int>())).first;
              int num;
              while (strm >> num)
                  it->second.push_back(num);
          }
          

          上面的函数在第一次读取时向映射添加一个新条目,并在后续读取时填充向量。

          请注意,map::insert 函数返回一个std::pair,其中该对的first 是创建的映射条目的迭代器。所以我们只需获取迭代器,然后从那里 push_back 条目。

          这是一个测试程序:

              int main()
              {
                  vector<std::string> data = { "Adam 2 5 1 5 3 4", "John 1 4 2 5 22 7", 
                                               "Kate 7 3 4 2 1 15", "Bill 2222 2 22 11 111" };
                  StringMap vectMap;
          
                  // Add results to map
                  for_each(data.begin(), data.end(), 
                           [&](const std::string& s){AddToMap(vectMap, s); });
          
                  // Output the results
                  for_each(vectMap.begin(), vectMap.end(),
                           [](const StringMap::value_type& vt)
                           {cout << vt.first << " "; copy(vt.second.begin(), vt.second.end(), 
                            ostream_iterator<int>(cout, " ")); cout << "\n"; });
              }
          

          现场示例:http://ideone.com/8UlnX2

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-26
            • 2016-06-09
            • 2015-07-07
            • 2019-11-26
            • 1970-01-01
            • 2020-02-26
            相关资源
            最近更新 更多