[英]Extracting Numbers from Mixed String using stringstream
我正在尝试使用 stringstream从像 Hello1234 这样的字符串中提取数字。 我已经编写了用于在输入时提取数字的代码,例如:
你好 1234 世界 9876 你好 1234
给出1234 9876作为输出,但它不读取同时具有字符串和数字的混合字符串。 我们如何提取它? - 例如: Hello1234应该给出1234 。
这是我的代码,直到现在:
cout << "Welcome to the string stream program. " << endl;
string string1;
cout << "Enter a string with numbers and words: ";
getline(cin, string1);
stringstream ss; //intiazling string stream
ss << string1; //stores the string in stringstream
string temp; //string for reading words
int number; //int for reading integers
while(!ss.eof()) {
ss >> temp;
if (stringstream(temp) >> number) {
cout << "A number found is: " << number << endl;
}
}
如果您不限于使用std::stringstream
的解决方案,我建议您查看正则表达式。 例子:
int main() {
std::string s = "Hello 123 World 456 Hello789";
std::regex regex(R"(\d+)"); // matches a sequence of digits
std::smatch match;
while (std::regex_search(s, match, regex)) {
std::cout << std::stoi(match.str()) << std::endl;
s = match.suffix();
}
}
输出:
123
456
789
在进行流提取之前,只需将字符串中的任何字母字符替换为空格即可。
std::string str = "Hello 1234 World 9876 Hello1234";
for (char& c : str)
{
if (isalpha(c))
c = ' ';
}
std::stringstream ss(str);
int val;
while (ss >> val)
std::cout << val << "\n";
输出:
1234
9876
1234
您可以将以下代码与任何类型的流一起使用 - 包括stringstream
。 它从流读取到第一个数字。 数字被放回流中,然后像往常一样读取数字。 实时代码。
#include <iostream>
using namespace std;
istream& get_number( istream& is, int& n )
{
while ( is && !isdigit( static_cast<unsigned char>( is.get() ) ) )
;
is.unget();
return is >> n;
}
int main()
{
int n;
while ( get_number( cin, n ) )
cout << n << ' ';
}
笔记
关于regex
- 似乎人们忘记/忽略了基础知识,并且出于某种原因(c++ 纯粹主义?),即使是最基本的问题也更喜欢使用大锤。
关于速度- 如果你从图片中取出流,你就无法击败基本的 c。 下面的代码比正则表达式解决方案快几十倍,至少比迄今为止的任何答案快几倍。
const char* get_number( const char*& s, int& n )
{
// end of string
if ( !*s )
return 0;
// skip to first digit
while ( !isdigit( static_cast<unsigned char>( *s ) ) )
++s;
// convert
char* e;
n = strtol( s, &e, 10 );
return s = e;
}
//...
while ( get_number( s, n ) )
//...
添加我的版本:
#include <iostream>
#include <string>
#include <sstream>
int main(){
std::string s;
std::getline(std::cin, s);
std::stringstream ss;
int number;
for(const char c: s){
if( std::isdigit(static_cast<unsigned char>(c)) ){ //Thanks to Aconcagua
ss << c;
} else if ( ss >> number ) {
std::cout << number << " found\n";
}
ss.clear();
}
if(ss >> number)
{
std::cout << number << " found\n";
}
return 0;
}
问题本身非常琐碎,作为程序员,我们大多数人每天都在解决此类问题。 我们知道任何给定的问题都有很多解决方案,但作为程序员,我们试图为任何给定的问题找出最好的解决方案。
当我遇到这个问题时,已经有很多有用且正确的答案,但为了满足我的好奇心,我尝试对所有其他解决方案进行基准测试,以找出最佳解决方案。
我在上面找到了最好的一个,并且觉得还有一些改进的空间。
所以我在这里发布我的解决方案和基准代码。
#include <chrono>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
#define REQUIER_EQUAL(x, y) \
if ((x) != (y)) { \
std::cout << __PRETTY_FUNCTION__ << " failed at :" << __LINE__ \
<< std::endl \
<< "\tx:" << (x) << "\ty:" << (y) << std::endl; \
; \
}
#define RUN_FUNCTION(func, in, out) \
auto start = std::chrono::system_clock::now(); \
func(in, out); \
auto stop = std::chrono::system_clock::now(); \
std::cout << "Time in " << __PRETTY_FUNCTION__ << ":" \
<< std::chrono::duration_cast<std::chrono::microseconds>(stop - \
start) \
.count() \
<< " usec" << std::endl;
//Solution by @Evg
void getNumbers1(std::string input, std::vector<int> &output) {
std::regex regex(R"(\d+)"); // matches a sequence of digits
std::smatch match;
while (std::regex_search(input, match, regex)) {
output.push_back(std::stoi(match.str()));
input = match.suffix();
}
}
//Solution by @n314159
void getNumbers2(std::string input, std::vector<int> &output) {
std::stringstream ss;
int number;
for (const char c : input) {
if (std::isdigit(static_cast<unsigned char>(c))) { // Thanks to Aconcagua
ss << c;
} else if (ss >> number) {
output.push_back(number);
}
}
}
//Solution by @The Failure by Design
void getNumbers3(std::string input, std::vector<int> &output) {
istringstream is{input};
char c;
int n;
while (is.get(c)) {
if (!isdigit(static_cast<unsigned char>(c)))
continue;
is.putback(c);
is >> n;
output.push_back(n);
}
}
//Solution by @acraig5075
void getNumbers4(std::string input, std::vector<int> &output) {
for (char &c : input) {
if (isalpha(c))
c = ' ';
}
std::stringstream ss(input);
int val;
while (ss >> val)
output.push_back(val);
}
//Solution by me
void getNumbers5(std::string input, std::vector<int> &output) {
std::size_t start = std::string::npos, stop = std::string::npos;
for (auto i = 0; i < input.size(); ++i) {
if (isdigit(input.at(i))) {
if (start == std::string::npos) {
start = i;
}
} else {
if (start != std::string::npos) {
output.push_back(std::stoi(input.substr(start, i - start)));
start = std::string::npos;
}
}
}
if (start != std::string::npos)
output.push_back(std::stoi(input.substr(start, input.size() - start)));
}
void test1_getNumbers1() {
std::string input = "Hello 123 World 456 Hello789 ";
std::vector<int> output;
RUN_FUNCTION(getNumbers1, input, output);
REQUIER_EQUAL(output.size(), 3);
REQUIER_EQUAL(output[0], 123);
REQUIER_EQUAL(output[1], 456);
REQUIER_EQUAL(output[2], 789);
}
void test1_getNumbers2() {
std::string input = "Hello 123 World 456 Hello789";
std::vector<int> output;
RUN_FUNCTION(getNumbers2, input, output);
REQUIER_EQUAL(output.size(), 3);
REQUIER_EQUAL(output[0], 123);
REQUIER_EQUAL(output[1], 456);
REQUIER_EQUAL(output[2], 789);
}
void test1_getNumbers3() {
std::string input = "Hello 123 World 456 Hello789";
std::vector<int> output;
RUN_FUNCTION(getNumbers3, input, output);
REQUIER_EQUAL(output.size(), 3);
REQUIER_EQUAL(output[0], 123);
REQUIER_EQUAL(output[1], 456);
REQUIER_EQUAL(output[2], 789);
}
void test1_getNumbers4() {
std::string input = "Hello 123 World 456 Hello789";
std::vector<int> output;
RUN_FUNCTION(getNumbers4, input, output);
REQUIER_EQUAL(output.size(), 3);
REQUIER_EQUAL(output[0], 123);
REQUIER_EQUAL(output[1], 456);
REQUIER_EQUAL(output[2], 789);
}
void test1_getNumbers5() {
std::string input = "Hello 123 World 456 Hello789";
std::vector<int> output;
RUN_FUNCTION(getNumbers5, input, output);
REQUIER_EQUAL(output.size(), 3);
REQUIER_EQUAL(output[0], 123);
REQUIER_EQUAL(output[1], 456);
REQUIER_EQUAL(output[2], 789);
}
int main() {
test1_getNumbers1();
// test1_getNumbers2();
test1_getNumbers3();
test1_getNumbers4();
test1_getNumbers5();
return 0;
}
我的平台上的示例输出
Time in void test1_getNumbers1():703 usec Time in void test1_getNumbers3():17 usec Time in void test1_getNumbers4():10 usec Time in void test1_getNumbers5():6 usec
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.