我有一個逗號分隔整數,我想將它們存儲在std::vector<int>
。目前我正在手動執行此操作。是否有任何內置函數執行上述功能?什麼是最快的方式存儲逗號分隔詮釋在std :: vector
編輯:含
我在趕時間,忘了把全部細節 其實我有字符串(準確的Unicode字符串)的CSV例如「1,2,3,4,5」 現在,我想將它們存儲在std::vector<int>
中,所以在上述情況下,我的向量將有五個元素推入它。目前我正在通過手動執行此操作,但其速度很慢,並且代碼很雜亂
我有一個逗號分隔整數,我想將它們存儲在std::vector<int>
。目前我正在手動執行此操作。是否有任何內置函數執行上述功能?什麼是最快的方式存儲逗號分隔詮釋在std :: vector
我在趕時間,忘了把全部細節 其實我有字符串(準確的Unicode字符串)的CSV例如「1,2,3,4,5」 現在,我想將它們存儲在std::vector<int>
中,所以在上述情況下,我的向量將有五個元素推入它。目前我正在通過手動執行此操作,但其速度很慢,並且代碼很雜亂
爲了簡單起見,您可以純粹在STL中使用(易於閱讀,不需要複雜的庫),編碼速度快,但在執行速度方面速度並不快(儘管您可能稍微調整它一樣,在矢量預保留空間:
std::vector<int> GetValues(std::wstring s, wchar_t delim)
{
std::vector<int> v;
std::wstring i;
std::wstringstream ss(s);
while(std::getline(ss,i,delim))
{
std::wstringstream c(i);
int x;
c >> x;
v.push_back(x);
}
return v;
}
(無轉發(&&
)或的atoi保持代碼便攜式)
這個在數據乾淨的情況下可以使用,那麼'1 ghghg,2 fjfjfjf,3 djdjdjd,4'你的代碼會在沒有抱怨的情況下讀取它,你需要在閱讀值x表示沒有希望ng行(空格除外)。 –
就我個人而言,我會創建一個結構並讓該向量包含該結構的實例。 像這樣:
struct ExampleStruct
{
int a;
int b;
int c;
};
vector<ExampleStruct> structVec;
可悲的是,STL不允許你對一個分隔符分開的字符串。您可以使用boost做雖然它:(需要近期C++編譯器,如2010 MSVC或GCC 4.5)
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace std;
int main(int argc, char** argv)
{
string input = "1,2,3,4";
vector<string> strs;
boost::split(strs, input, boost::is_any_of(","));
vector<int> result;
transform(
strs.begin(), strs.end(), back_inserter(result),
[](const string& s) -> int { return boost::lexical_cast<int>(s); }
);
for (auto i = result.begin(); i != result.end(); ++i)
cout << *i << endl;
}
如果您要使用爲此,你可以使用Boost Tokenizer和Escaped List Separator:http://www.boost.org/doc/libs/1_47_0/libs/tokenizer/escaped_list_separator.htm – Ferruccio
這可能不是最好的提升使用率。你實際上迭代了兩次輸入。一旦將輸入分割爲一個字符串矢量,然後再次將字符串轉換爲數字。如果您使用[boost :: tokenizer](http://www.boost.org/doc/libs/1_36_0/libs/tokenizer/tokenizer.htm),則可以在一次傳遞中獲得相同的效果。 –
感謝您的建議,確實非常相關。我之前沒有使用'boost:tokenizer',我會仔細看看。 –
它可能不是最有效的方式,但這裏有一個辦法做到這一點使用TR1正則表達式功能(我也用的C++ 0x lambda語法此示例中,但顯然它也可以做到不說):
#include <iostream>
#include <algorithm>
#include <vector>
#include <regex>
#include <iterator>
#include <cstdlib>
std::vector<int> GetList(const std::wstring &input)
{
std::vector<int> result;
std::wsregex_iterator::regex_type rex(L"(\\d+)(,|$)");
std::wsregex_iterator it(input.begin(), input.end(), rex);
std::transform(it, std::wsregex_iterator(), std::back_inserter(result),
[] (const std::wsregex_iterator::value_type &m)
{ return std::wcstol(m[1].str().c_str(), nullptr, 10); });
return result;
}
這個怎麼樣?
#include <string>
#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>
struct PickIntFunc
{
PickIntFunc(std::vector<int>& vecInt): _vecInt(vecInt),_pBegin(0){}
char operator() (const char& aChar)
{
if(aChar == ',' || aChar == 0)
{
_vecInt.push_back(atoi(std::string(_pBegin,&aChar).c_str()));
_pBegin = 0;
}
else
{
if(_pBegin == 0)
{
_pBegin = &aChar;
}
}
return aChar;
}
const char* _pBegin;
std::vector<int>& _vecInt;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> vecInt;
char intStr[] = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20";
std::for_each(intStr,intStr+sizeof(intStr),PickIntFunc(vecInt));
// Now test it
std::for_each(vecInt.begin(),vecInt.end(), [] (int i) { std::cout << i << std::endl;});
return 0;
}
的快速和骯髒的方法是使用C串庫的strtok()函數,和的atoi():
void Split(char * string, std::vector<int>& intVec)
{
char * pNext = strtok(string, ",");
while (pNext != NULL)
{
intVec.push_back(atoi(pNext));
pNext = strtok(NULL, ",");
}
}
根據需要插入自己的輸入數據的驗證。
參見:
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
還有寬字符串版本:
http://msdn.microsoft.com/en-us/library/2c8d19sb%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/aa273408%28v=vs.60%29.aspx
編輯: 注意strtok()
會修改你的原始字符串,那麼通行一個副本如果需要的話。
如果目標是運行時速度,那麼我認爲速度更快。小心,strtok只能在單線程環境下工作。由於代碼可能會在初始化過程中運行,所以我猜這樣做很好。 –
Saem問題如上面的@Necrolis:輸入1 jjfjfjf,2 fjfjfj,3 gjgjgjg,4被解析爲垃圾不在那裏,而不是使用'atoi()',你可以使用'boost :: lexical_cast
strtok是那些'邪惡'函數之一,其結果可能會與您期望的不同。「a,b,c」加載三個元素。「a ,, b」只加載兩個元素,在使用函數的時候記住這一點 – EvilTeach
嘗試這種情況:
它將讀取的任何類型(即可以是用>>分隔)(用你選擇的字符)
注意:讀取對象後,對象和分隔符之間只能有空格。因此對於像ObjectSepReader<std::string, ','>
這樣的東西,它將讀取由','分隔的單詞列表。
這使得簡單的使用我們的標準算法:
#include <vector>
#include <sstream>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
std::stringstream data("1,2,3,4,5,6,7,8,9");
std::vector<int> vdata;
// Read the data from a stream
std::copy(std::istream_iterator<ObjectSepReader<int, ','> >(data),
std::istream_iterator<ObjectSepReader<int, ','> >(),
std::back_inserter(vdata)
);
// Copy data to output for testing
std::copy(vdata.begin(), vdata.end(), std::ostream_iterator<int>(std::cout," "));
}
祕密級,使其工作。
template<typename T,char S>
struct ObjectSepReader
{
T value;
operator T const&() const {return value;}
};
template<typename T,char S>
std::istream& operator>>(std::istream& stream, ObjectSepReader<T,S>& data)
{
char terminator;
std::string line;
std::getline(stream, line, S);
std::stringstream linestream(line + ':');
if (!(linestream >> data.value >> terminator) || (linestream.tellg() != line.size()+1) || (terminator != ':'))
{ stream.setstate(std::ios::badbit);
}
return stream;
}
把一些代碼來演示你的確切問題' – iammilind
你是否在'std :: vector'中存儲整數和逗號? – Donotalo
逗號分隔列表的來源是什麼?流?一個字符串?你目前使用的方法是什麼? – Sven