[英]how to take user input, do math to that input, and store the results in an array? in 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.