我有几个字符串,每个字符串包含一个字和几个整数(一个字符串是整行):
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);
}
}
答案 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"; });
}
答案 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