繁体   English   中英

如何从用户(这是一个列表)获取输入并将值存储在 C++ 中的数组中?

[英]How to take input from user ( which is a list ) and store values in array in c++?

测试用例 1:{1、2、3、4、5}

测试用例 2:{5, 8, 9}

有没有比这更好的解决方案来将值存储在 C++ 中的数组中?

注意:我们不知道编译时要创建的数组的大小。

#include<iostream>
#include<sstream>
#include<vector>
using namespace std;

int main(){
  string s;
  cin.ignore();
  getline(cin,s);
  string t;
  stringstream x(s);
  vector<int>v;
  while(getline(x,t,' ')){
      if(t[0]!='{' && t[0]!='}'&& t[0]!=','){
           v.push_back(stoi(t));
        }
   }
 int size=v.size();
 int arr[size];
 for(int i=0;i<size;i++) arr[i]=v[i];
// for(int i=0;i<size;i++) cout<<arr[i]<<" ";
}

是的,可以采用未知数量的整数。 我们可以使用std::vector

我们可以为此编写一个函数。 在这里,我们将拆分字符串并返回一个std::vector 在 C++ 中,我们可以利用 RVO,返回值优化。 您可以在此处阅读有关复制省略和 RVO 的信息。 基本上它说,当按值从函数返回容器时,复制字节不会有问题。 现在它甚至是推荐的方法。

因此,您可以(并且应该)从函数返回一个std::vector 编译器会注意它以优化的方式工作。

但首先,请看下面的例子:

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>

std::vector<int> parseInts(std::string str) {

    // Put the string into a stream
    std::istringstream iss{ str };

    // Return the vector of ints 
    return { std::istream_iterator<int>(iss), {} };
}

int main() {
    // Test data
    std::string test{ "1 2 3 4 5 6 7 8 9 10" };

    // Get the vector with the ints
    std::vector ints = parseInts(test);

    // Show output
    for (const int i : ints) 
        std::cout << i << "\n";
    return 0;
}

我们有一个名为parseInts的函数, parseInts包含 2 行代码。

首先,我们将字符串放入std::istringstream 这样,就可以从新流中提取 int,例如

std::istringstream iss{ str };
int i1, i2;
iss >> i1 >> i2;

提取运算符 >> 将从流(字符串)中“提取”以空格分隔的整数值。

但是,如果我们看一下,我们会看到,那么我们需要知道字符串中的整数个数,然后重复写“>>”。 为了对相同数量的项目重复执行操作,比如整数,我们在 C++ 中有迭代器。 使用迭代器,您可以迭代容器中的相似元素。 如果你假设一个字符串是一个容器,你当然可以迭代其中的整数。 有可用的迭代器可以为我们执行此操作。

在流的情况下,我们有std::istream_iterator 这个东西将迭代输入流中某种类型的所有空格分隔项并返回值。

这个迭代器返回的许多值最好存储在std::vector ,因为它是一个动态增长的容器。 非常适合我们,因为我们事先不知道流中的整数数量。

如果我们查看std::vector ,我们会发现它有一个所谓的范围构造函数。 请参阅此处:范围构造函数(编号 5)

使用范围构造函数,我们定义了一个std::vector类型的变量,并用“begin”和“end”迭代器初始化它。 此范围内的值将被放入向量中。

如果我们在示例中定义std::vector类型的变量,我们可以这样写:

std::vector<int> intv{ std::istream_iterator<int>(iss), std::istream_iterator<int>() };

或者

std::vector<int> intv( (std::istream_iterator<int>(iss)), std::istream_iterator<int>() );

请注意第一个参数的大括号。 这对于防止最棘手的解析问题是必要的。 你不想定义一个函数,而是一个变量。

但无论如何我们都不会使用它。 因为,使用统一初始化和 {} 初始化器作为默认初始化器,我们可以使用默认值作为第二个参数。 现在我们可以写:

std::vector<int> intv(std::istream_iterator<int>(iss), {});

所以,接下来,我们可以使用 CTAD, 类模板参数推导 基本上,编译器从构造函数中的参数知道它将构造的容器的数据类型。 所以,没必要写。

现在:

std::vector intv(std::istream_iterator<int>(iss), {});

这看起来已经很不错了,您现在可以返回变量 intv。

但还有更多。 编译器知道函数的类型以及它应该返回什么。 因此,您可以使用花括号初始化器并返回它,编译器知道您想要返回std::vector<int>

所以最后的声明是:

return { std::istream_iterator<int>(iss), {} };

我希望它有帮助。

很抱歉对一行代码进行了冗长的描述。

所以,现在,为了阅读更多的行,你可以写:

int main() {

    // Her we will store the data
    std::vector<std::vector<int>> data{};

    // Read lines. Stop input with CRTL Z in an empty new line
    for (std::string line{}; std::getline(std::cin, line); ) {

        // Put the string into a stream
        std::istringstream iss{ line };

        // Split the values and add the values to the vector
        data.emplace_back(std::vector{ std::istream_iterator<int>(iss), {} });
    }

    // Show output
    for (const std::vector<int>& vi : data) {
        for (const int i : vi) std::cout << i << " ";
        std::cout << "\n";
    }
}

通过在结束后的空行中键入 CRTL Z 来停止输入。

请尝试输入:

1 2 3 4
5 6 7 8
CTRL Z

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM