【问题标题】:How to read in user entered comma separated integers?如何读入用户输入的逗号分隔整数?
【发布时间】:2014-02-17 19:20:19
【问题描述】:

我正在编写一个程序,提示用户:

  1. 数组大小
  2. 要放入数组的值

第一部分很好,我创建了一个动态分配的数组(必需)并将其设置为用户想要的大小。

我被困在下一部分。用户需要输入一系列用逗号分隔的整数,例如:1,2,3,4,5

如何获取这些整数并将它们放入我的动态分配数组中?我读到默认情况下 cin 接受由空格分隔的整数,我可以将其更改为逗号吗?

请用最简单的方式解释一下,我是编程初学者(对不起!)

编辑:对于所有的答案,TY 都这么多。问题是我们没有涵盖向量...有没有只使用我拥有的动态分配数组的方法?

到目前为止,我的功能看起来像这样。我在 main.js 中创建了一个默认数组。我打算将它传递给这个函数,创建新数组,填充它,并更新指针以指向新数组。

int *fill (int *&array, int *limit) {

cout << "What is the desired array size?: ";                                  
while ( !(cin >> *limit) || *limit < 0 ) {
    cout << "  Invalid entry. Please enter a positive integer: ";
    cin.clear();
    cin.ignore (1000, 10);
}

int *newarr;                                                                            
newarr = new int[*limit]
    //I'm stuck here
}

【问题讨论】:

  • c++有split()吗?
  • 恐怕最简单的方式需要一些编码。你的开场白表明你已经在路上了,看看你到目前为止有什么会很有帮助。

标签: c++ cin


【解决方案1】:

所有现有的答案都很好,但都是针对您的特定任务的。因此,我写了一个通用的代码,允许以标准方式输入逗号分隔值:

template<class T, char sep=','>
struct comma_sep { //type used for temporary input
    T t; //where data is temporarily read to
    operator const T&() const {return t;} //acts like an int in most cases
};
template<class T, char sep>
std::istream& operator>>(std::istream& in, comma_sep<T,sep>& t) 
{
    if (!(in >> t.t)) //if we failed to read the int
        return in; //return failure state
    if (in.peek()==sep) //if next character is a comma
        in.ignore(); //extract it from the stream and we're done
    else //if the next character is anything else
        in.clear(); //clear the EOF state, read was successful
    return in; //return 
}

示例用法http://coliru.stacked-crooked.com/a/a345232cd5381bd2:

typedef std::istream_iterator<comma_sep<int>> istrit; //iterators from the stream
std::vector<int> vec{istrit(in), istrit()}; //construct the vector from two iterators

由于您是初学者,现在这段代码可能对您来说太多了,但我想为了完整起见我会发布此代码。

【讨论】:

  • 嗯,有一个奇怪的怪癖,它会解析空格分隔的输入。我不知道我是否要禁止这样做。
  • 这看起来不对 - 它正在提取值加上逗号(或@Mooing Duck 提到的空格),而最后一个值(没有分隔符)被某些东西终止。
  • @DieterLücking:else in.clear() 使得最后一个值确实被正确提取,并且终止字符留在缓冲区中。检查显示测试结果的链接。如果你能想到一个错误案例,我会看看我能做什么
  • 除了stringstream之外,最好为cin添加一个case。
  • @user2876962 不,我的代码从std::istream&amp; 派生的任何内容中读取,命名为in...哦!我的示例创建了一个stringstream 是的。你想要这个是什么意思? coliru.stacked-crooked.com/a/ff7c6acbde576e48
【解决方案2】:

先验,您应该检查逗号是否存在,并且 如果不是,则声明错误。出于这个原因,我会处理 单独的第一个数字:

std::vector<int> dest;
int value;
std::cin >> value;
if ( std::cin ) {
    dest.push_back( value );
    char separator;
    while ( std::cin >> separator >> value && separator == ',' ) {
        dest.push_back( value );
    }
}
if ( !std::cin.eof() ) {
    std::cerr << "format error in input" << std::endl;
}

请注意,您不必先询问尺寸。数组 (std::vector) 将自动扩展自身 需要,前提是内存可用。

最后:在一个真实的例子中,你可能想阅读 逐行,以便在以下情况下输出行号 格式错误,并从此类错误中恢复并继续。 这有点复杂,特别是如果你想 能够在换行符之前或之后接受分隔符 特点。

【讨论】:

  • +1 std::cin.eof() 可能不好,它 cin 交互使用 - 另一方面,输入格式(OP)没有明确定义。
  • @DieterLücking 也许吧。从逻辑上讲,您希望向量的大小由条目数决定;不必预先输入它是不必要的,而且非常米老鼠。这样做最简单的方法是读取到文件末尾:如果输入是键盘,则 ^D 在 Unix 下会起作用,在 Windows 下会用 ^Z(当然在行首)。或者:您要求所有输入都在一行中,使用std::getline,然后使用std::istringstream,或者使用某种关键字来表示结束。最后一个对于初学者来说可能太复杂了。
【解决方案3】:

您可以使用getline()方法如下:

#include <vector>
#include <string>
#include <sstream>

int main() 
{
  std::string input_str;
  std::vector<int> vect;

  std::getline( std::cin, input_str );

  std::stringstream ss(str);

  int i;

  while (ss >> i)
  {
    vect.push_back(i);

    if (ss.peek() == ',')
    ss.ignore();
  }
}

代码取自this答案并处理。

【讨论】:

  • 不需要getline()或stringstream,直接在cin上使用ignore()即可。
  • 另一方面,你通常不想在这里使用peek,因为它不会跳过空格(这会更好)。
  • 当然,如果缺少逗号,相关代码将无法检测到错误。
  • @JamesKanze:另一方面,任何其他类型的输入都会将下一个字符留在缓冲区中,这需要使用peek
  • @MooingDuck 使用&gt;&gt; 提取字符,然后可以检查',',这是想要的。 (但处理分隔符,而不是终止符,可能有点棘手。这就是为什么我单独处理第一个值,然后将',' 视为必需的前缀。不是唯一的解决方案,但也不是太复杂。)
【解决方案4】:

Victor 的回答有效,但超出了必要的范围。您可以直接在 cin 上调用 ignore() 以跳过输入流中的逗号。

这段代码的作用是读取输入数组大小的整数,在整数向量中为该数量的元素保留空间,然后循环到指定的元素数量,交替从标准输入读取整数和跳过分隔逗号(对 cin.ignore() 的调用)。一旦它读取了请求的元素数量,它就会将它们打印出来并退出。

#include <iostream>
#include <iterator>
#include <limits>
#include <vector>

using namespace std;

int main() {
    vector<int> vals;
    int i;
    cin >> i;
    vals.reserve(i);
    for (size_t j = 0; j != vals.capacity(); ++j) {
        cin >> i;
        vals.push_back(i);
        cin.ignore(numeric_limits<streamsize>::max(), ',');
    }
    copy(begin(vals), end(vals), ostream_iterator<int>(cout, ", "));
    cout << endl;
}

【讨论】:

  • 一个有趣的想法:使用istream_iterator 阅读。 (您需要为它定义一个特殊类型,CommaSeparatedInt,但它应该是可行的。)
  • 我想过这个问题,但是由于 OP 说他是初学者并且想要一个简单的答案,因此对于他的问题可能会是一个过于复杂的答案。
  • 是的。我说了一个有趣的想法,不适合初学者。
【解决方案5】:
#include <iostream>
using namespace std;

int main() {
    int x,i=0;
    char y;               //to store commas
    int arr[50];
    while(!cin.eof()){
        cin>>x>>y;
        arr[i]=x;
        i++;
    }

    for(int j=0;j<i;j++)
        cout<<arr[j];     //array contains only the integer part
    return 0;
}

【讨论】:

    【解决方案6】:

    可以使用 C+11 中的新 std::stoi 函数稍微简化代码。它在转换时处理输入中的空格,并且仅当特定标记以非数字字符开头时才引发异常。因此,此代码将接受输入

    " 12de, 32, 34 45, 45 , 23xp,"

    容易但拒绝

    " de12, 32, 34 45, 45 , 23xp,"

    仍然存在一个问题,您可以看到,在第一种情况下,它会在将“34 45”截断为 34 的末尾显示“12、32、34、45、23”。可能是一种特殊情况添加以将此作为错误处理或忽略令牌中间的空格。

    wchar_t in;
    std::wstring seq;
    std::vector<int> input;
    std::wcout << L"Enter values : ";
    
    while (std::wcin >> std::noskipws >> in)
    {
        if (L'\n' == in || (L',' == in))
        {
            if (!seq.empty()){
                try{
                    input.push_back(std::stoi(seq));
                }catch (std::exception e){ 
                    std::wcout << L"Bad input" << std::endl;
                }
                seq.clear();
            }
            if (L'\n' == in) break;
            else continue;
        }
        seq.push_back(in);
    }
    
    std::wcout << L"Values entered : ";
    std::copy(begin(input), end(input), std::ostream_iterator<int, wchar_t>(std::wcout, L", "));
    std::cout << std::endl;
    

    【讨论】:

      【解决方案7】:
      #include<bits/stdc++.h>
      using namespace std;
      int a[1000];
      int main(){
          string s;
          cin>>s;
          int i=0;
          istringstream d(s);
          string b;
          while(getline(d,b,',')){
              a[i]= stoi(b);
              i++;
          }
          for(int j=0;j<i;j++){
              cout<<a[j]<<" ";
          }
      }
      

      这段代码适用于 C++ 11 及以后版本,它很简单,我使用了 stringstreams 以及 getline 和 stoi 函数

      【讨论】:

        【解决方案8】:

        您可以使用 scanf 代替 cin 并将逗号放在数据类型符号旁边

        #include<bits/stdc++.h>
        using namespace std;
        int main()
         {
            int a[10],sum=0;
            cout<<"enter five numbers";
            for(int i=0;i<3;i++){
            scanf("%d,",&a[i]);
            sum=sum+a[i];
            }
            cout<<sum;
        }
        

        【讨论】:

          【解决方案9】:

          首先,将输入作为字符串,然后解析字符串并将其存储在向量中,您将获得整数。

          vector<int> v;
          string str;
          cin >> str;
          stringstream ss(str);
          for(int i;ss>>i;){
              v.push_back(i);
              if(ss.peek() == ','){
                  ss.ignore();
              }
          }
          for(auto &i:v){
              cout << i << " ";
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-02-07
            • 2013-02-12
            • 2023-03-15
            • 1970-01-01
            • 2012-07-15
            • 1970-01-01
            相关资源
            最近更新 更多