C++ 将包含多个数字的字符串转换为整数

C++ 将包含多个数字的字符串转换为整数,c++,string,integer,C++,String,Integer,我意识到这个问题在过去可能被问过好几次,但不管怎样,我还是要继续问下去 我有一个程序,可以从键盘输入中获取一串数字。数字将始终以“66 33 9”的形式出现,基本上,每个数字都用空格分隔,用户输入将始终包含不同数量的数字 我知道,如果每个用户输入的字符串中的数字量是恒定的,那么使用“sscanf”就可以了,但我不是这样。另外,因为我是C++新手,我更喜欢处理字符串变量而不是字符数组。< /P> < P>如何将字符串分割成字符串。然后您可以一个接一个地处理它们。尝试先分离字符串,然后处理每个字符串

我意识到这个问题在过去可能被问过好几次,但不管怎样,我还是要继续问下去

我有一个程序,可以从键盘输入中获取一串数字。数字将始终以“66 33 9”的形式出现,基本上,每个数字都用空格分隔,用户输入将始终包含不同数量的数字


我知道,如果每个用户输入的字符串中的数字量是恒定的,那么使用“sscanf”就可以了,但我不是这样。另外,因为我是C++新手,我更喜欢处理字符串变量而不是字符数组。< /P> < P>如何将字符串分割成字符串。然后您可以一个接一个地处理它们。

尝试先分离字符串,然后处理每个字符串。

我假设您要读取整行,并将其作为输入进行解析。因此,首先要抓住这条线:

std::string input;
std::getline(std::cin, input);
现在将其放入
stringstream

std::stringstream stream(input);
和解析

while(1) {
   int n;
   stream >> n;
   if(!stream)
      break;
   std::cout << "Found integer: " << n << "\n";
}
while(1){
int n;
流>>n;
如果(!流)
打破
std::cout
#包括
#包括
#包括
#包括
使用名称空间std;
int ReadNumbers(常量字符串和s、向量和v){
istringstream为(s);
int n;
while(is>>n){
v、 推回(n);
}
返回v.size();
}
int main(){
字符串s;
向量v;
getline(cin,s),;
读数(s、v);
对于(int i=0;i//获取字符串
std::字符串输入\u str;
std::getline(std::cin,input_str);
//转换成流
std::stringstream输入(输入_str);
//转换为整数的向量
std::向量整数;
复制(std::istream_迭代器(in),std::istream_迭代器(),back_插入器(ints));

无符号值的通用解决方案(处理前缀“-”需要额外的bool):

模板
void convertNumber(初始开始、初始结束、输出结束)
{
typename OutIter::value_type accum=0;
for(;begin!=end;++begin)
{
typename InIter::value_type c=*begin;
如果(c=''){
*out++=accum;accum=0;中断;
}否则,如果(c>='0'&&c对您的问题有以下解决方案:

#include <iostream>
#include <string>
#include <deque>
#include <algorithm>
#include <iterator>

#include "strtk.hpp"

int main()
{
   std::string s = "1 23 456 7890";

   std::deque<int> int_list;
   strtk::parse(s," ",int_list);

   std::copy(int_list.begin(),
             int_list.end(),
             std::ostream_iterator<int>(std::cout,"\t"));

   return 0;
}
#包括
#包括
#包括

#用一个“使用名称空间std;”替换1000“std::”后,包括+1,并提及所需的标题。+1只要保留
std:
前缀。它们的可读性是主观的(我习惯了它们,发现阅读起来更好),但通过完全限定名称来提高清晰度是客观的。@j_random_hacker:我并不担心名称空间污染。但是,让每个名称完全限定可以更容易地看到它的来源。(“哦,这是一个专有的
向量
模板!”)许多年前,在我当时参与的一个项目中,我们决定完全限定所有名称。当时看起来很滑稽,但可能在两周内变得正常。我一直站在争论的两方,永远不会回头。可读性是一个主观问题,可由用法改变。清晰度是客观的。通常错误消息由com处理piler和编译器完全限定了类型。我通常对std::namespace是显式的。事实上,只有在少数情况下我使用using指令,在某些情况下会创建短别名。完全限定的优点是对普通读者来说更容易,名称“find”、“copy”可以是成员/免费的常用名称不经意的读者会直接知道符号何时是STL的一部分。再说一次,除了对答案进行更多的编辑之外,我没有这么大的动力不去改变它:P@j_random_hacker:我希望看到我的
typedef
name
bla_foo_bar_data
istead of
std::vectorIMO通常更喜欢std::string
不是“新字节”的标志,而是成熟的标志。+1因为你回答了前面提到的问题(“整数”),但我认为这实际上在某些方面是朝着不太通用的方向迈出的一步,因为它显然只适用于整数,而不适用于其他类型“typename OutIter::value_type accum=0;”被夸大了)。例如,您将如何处理浮点数?如果您想编写另一个迷你词法,请不要忘记处理科学记数法和Inf、NaN等。它将接受
short[]
std::vector
std::list
或任何其他整数类型(包括实现定义的类型)。普通0将转换为所有这些类型。我使用valuetype的原因是,当用户以
\uu int128[]的身份通过时,我不会意外地溢出
int
和一个数字那么大的字符串。对accum使用value\u type绝对是正确的方法,但我想我不明白为什么不能使用istringstream而不是您自己手工制作的lexer。然后您可以使用任何运算符可以理解的类型。您的意思是parse:
int n;while(stream>>n){std::cout或甚至解析:
for(int n;stream>>n;){std::cout或使用直接初始化:
std::vector ints{std::istream_迭代器{in},std::istream_迭代器{};
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
using namespace std;

int ReadNumbers( const string & s, vector <int> & v ) {
    istringstream is( s );
    int n;
    while( is >> n ) {
        v.push_back( n );
    }
    return v.size();
}

int main() {
    string s;
    vector <int> v;
    getline( cin, s );
    ReadNumbers( s, v );
    for ( int i = 0; i < v.size(); i++ ) {
        cout << "number is " <<  v[i] << endl;
    }
}
#include <string>
#include <vector>
#include <iterator>
#include <sstream>
#include <iostream>

int main() {
   std::string input;
   while ( std::getline( std::cin, input ) )
   {
      std::vector<int> inputs;
      std::istringstream in( input );
      std::copy( std::istream_iterator<int>( in ), std::istream_iterator<int>(),
         std::back_inserter( inputs ) );

      // Log process: 
      std::cout << "Read " << inputs.size() << " integers from string '" 
         << input << "'" << std::endl;
      std::cout << "\tvalues: ";
      std::copy( inputs.begin(), inputs.end(), 
         std::ostream_iterator<int>( std::cout, " " ) );
      std::cout << std::endl;
   }
 }
// get string
std::string input_str;
std::getline( std::cin, input_str );

// convert to a stream
std::stringstream in( input_str );

// convert to vector of ints
std::vector<int> ints;
copy( std::istream_iterator<int, char>(in), std::istream_iterator<int, char>(), back_inserter( ints ) );
template<typename InIter, typename OutIter>
void ConvertNumbers(InIter begin, InIter end, OutIter out)
{
    typename OutIter::value_type accum = 0;
    for(; begin != end; ++begin)
    {
        typename InIter::value_type c = *begin;
        if (c==' ') {
            *out++ = accum; accum = 0; break;
        } else if (c>='0' && c <='9') {
            accum *= 10; accum += c-'0';
        }
    }
    *out++ = accum;
       // Dealing with the last number is slightly complicated because it
       // could be considered wrong for "1 2 " (produces 1 2 0) but that's similar
       // to "1  2" which produces 1 0 2. For either case, determine if that worries
       // you. If so: Add an extra bool for state, which is set by the first digit,
       // reset by space, and tested before doing *out++=accum.
}
#include <iostream>
#include <string>
#include <deque>
#include <algorithm>
#include <iterator>

#include "strtk.hpp"

int main()
{
   std::string s = "1 23 456 7890";

   std::deque<int> int_list;
   strtk::parse(s," ",int_list);

   std::copy(int_list.begin(),
             int_list.end(),
             std::ostream_iterator<int>(std::cout,"\t"));

   return 0;
}