C ++如何从复杂的字符串中获取整数

时间:2014-11-27 15:36:29

标签: c++ string integer stdvector

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

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

如您所见,每个单词/数字都用空格分隔。现在,我想将这些数据加载到地图中,其中word(name)将成为关键,值将是行中数字的向量。我已经在分离的临时stl容器中有键值,因此任务是只将每行的整数加载到2D向量,然后将这两个合并到map中。 问题是,是否有任何C ++函数,它可以避免单词和空格,只从字符串中获取整数,或者我必须像char-by-char一样搜索字符串 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);
    }
}

5 个答案:

答案 0 :(得分:2)

如果每一行都有“字号编号...”格式,请使用字符串流并通过阅读跳过该字。

如果当前行位于line

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

答案 1 :(得分:2)

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

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

如果不能执行stoi转换(字符串不包含数字),则抛出invalid_argument异常,因此不要尝试转换名称substring。

#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;
}

答案 2 :(得分:1)

使用字符串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

我不测试这个解决方案,但是我首先使用类似于标签的东西。

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

答案 3 :(得分:1)

假设名称首先出现,这是一个将读取字符串并添加到地图的函数。

#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对是创建的映射条目的迭代器。所以我们只需要获取迭代器,然后从那里推送条目。

这是一个测试程序:

    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

答案 4 :(得分:1)

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

#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