如何遍历存储在separte变量中的数字?

问题描述

所以我得到了这段代码,我输入了三个数字。现在,我想在for循环中显示它们。从最小到最大,从另一个到最大。我该怎么办?

int main()
{

    int num1,num2,num3;
    cout << "Enter first num" << endl;
    cin >> num1;

    cout << "Enter second num" << endl;
    cin >> num2;

    cout << "Enter third num" << endl;
    cin >> num3;
}

我已经这样做了,但是我认为这不是正确的方法。

for(int i = 0; i <= 0; i++) {
    cout << num1;
    cout << num2;
    cout << num3;
}

for(int i = 0; i <= 0; i++) {
    cout << num3;
    cout << num2;
    cout << num1;
}

编辑:

这样好吗?

int main()
{
    int numbers[3];

    cout << "Enter first num" << endl;
    cin >> numbers[0];

    cout << "Enter second num" << endl;
    cin >> numbers[1];

    cout << "Enter third num" << endl;
    cin >> numbers[2];

    for (int i = 0; i <= 2; i++)
    {
        cout << numbers[i];
    }

    for (int i = 2; i >= 0; i--)
    {
        cout << numbers[i];
    }

    return 0;
}

解决方法

您不需要循环,因为它只循环一次,所以您可以使用链式ostream:

cout << num1 << " " << num2 << " " << num3 << "\n";

cout << num3 << " " << num2 << " " << num1 << "\n";

但是,如果要按值对它们进行打印,并且不能使用可以应用排序算法的容器,则需要一些条件。

编辑:这样更好吗?

将其存储在数组中可以更轻松地处理数据,例如,它允许您使用<algorithm>std::sort之类的简单值对它进行排序。

,

鉴于输入似乎除了“一些数字”之外没有其他含义,您应该使用容器,显而易见的选择是:

std::vector<int> nums;

从c ++ 20开始,对于此问题,您根本不需要循环,因为可以使用范围:

#include<ranges>
namespace rs = std::ranges;
namespace rv = std::views;

现在您可以读入如下数字:

rs::copy_n(std::istream_iterator<int>(std::cin),3,std::back_inserter(nums));

我不确定是否要使用用户输入数字的顺序,但是如果要实际最小到最大,可以执行以下操作:

rs::sort(nums);

现在要打印数字:

rs::copy(nums,std::ostream_iterator<int>(std::cout," "));

反之:

rs::copy(nums | rv::reverse," "));

这里是demo

,

您尝试做的事情在编程语言中很常见。即输入数据,进行处理并以一种或另一种形式输出。

如果要多次执行一段代码(大于1的数字),则使用循环。在第一个示例中,您执行了一次循环,使多余的代码行有点多余。

您已经更新了代码,向您展示了如何快速使用数组。这些类型的数组(即int numbers[3];)通常称为C样式的数组,因为它们是从C继承的。在C ++中,我们现在可以使用std::array <int,3> numbers;,它更加适用于C ++的工作方式。 (类型名称的std::部分表示该类型是在标准库名称空间中定义的。该类型是C ++语言标准的一部分。) 这两种类型的问题是它们具有静态(=固定)大小。即大小必须在编译时知道。如果您不知道用户要输入多少个项目,这可能是一个很大的限制。但是,C ++标准定义了其他容器类型,它们可以容纳可变数量的项目。其中std::vector是数组的动态(可变)大小的对等物:它们都将它们的项顺序存储在内存中。

因此,例如,您可以使用循环将用户选择的多个元素添加到(向后= push_back())。

#include <vector>
#include <iostream>
[...]
    std::vector<int> numbers;
    std::cout << "How many numbers do you want to enter?\n";
    int N;
    std::cin >> N;
    numbers.reserve(N); // good practice to reserve memory if you know the number of elements
    for (int i = 0; i < N; ++i) {
        std::cout << "Enter a number: ";
        int number;
        std::cin >> number;
        numbers.push_back(number);
    }
[...]

请注意,不检查输入内容:例如如果用户在第一个问题后输入“ -1”,则事情将会中断。我不会在回答中考虑处理用户错误。

您已经在这里看到一些代码重复:cout,类型定义,cin。您可以将其提取为单独的函数。

#include <string>
[...]
int ReadUserInput(std::string const& message) {
    std::cout << message;
    int value;
    std::cin >> value;
    return value;
}

甚至更好,您可以创建一个函数 template 。即函数的模板:编译器将根据推断的类型T为您生成此函数的实现。我现在还使用了std::string_view,它可以查看不同类型的字符串(std::stringchar*

#include <string_view>
[...]
template<typename T>
T ReadUserInput(std::string_view message = "") {
    if (!message.empty()) std::cout << message; //only print is there's an actual message
    T value;
    std::cin >> value;
    return value;
}

接下来,C ++库提供了更多功能,包括许多在编程中常用的algorithms。其中的一个是generator,它反复调用一个函数,其结果用于在容器中分配连续的元素。指向容器中特定元素的对象称为iterator。 C ++标准库提供了一种方便的迭代器类型,可以执行push_backstd::back_inserter。现在可以将以前的代码简化为:

    int const N = ReadUserInput<int>("How many numbers do you want to enter?\n");
    std::vector<int> numbers;
    numbers.reserve(N); // good practice to reserve memory if you know the number of elements
    std::generate_n(back_inserter(numbers),N,ReadUserInputGenerator<int>("Enter a number: "));

“但是等等”,您可能会问,“ ReadUserInputGenerator是什么?”。好吧,要使generate_n工作,您需要将指针/句柄传递给生成器函数,然后对每个元素执行该函数。如果我们仅调用ReadUserInput<int>("Enter a number: "),则该函数将已经被评估。因此,我们需要添加另一个使该生成器起作用的中间函数对象。在通过的过程中,我们为此做一个课程

template<typename T>
class ReadUserInputGenerator {
private:
    std::string_view message;
public:
    ReadUserInputGenerator(std::string_view message = "") : message(message) {}
    T operator()() const { return ReadUserInput(message); }
};

...但是现在我们可以使用lambda expressions

template<typename T>
auto ReadUserInputGenerator = [](std::string_view message = "") {
    return [message]() { return ReadUserInput<T>(message); };
};

(请给经验丰富的读者注意:我不太确定要按值传递string_view。我是根据this得出的)

SOOOOO ,现在我们终于有了输入。接下来,您要对其进行排序。同样,这是一个常见的操作。实际上有many ways to sort a collection a values,可以自己实现这些功能是一个不错的选择……但是,正如我前面提到的,由于这类操作在编程中很常见,因此C ++标准库实际上提供了一种排序算法: {3}}。

std::sort(begin(numbers),end(numbers));

^这里的beginend是指指向向量的开始和结束(或者实际上是结束之后的一个)的迭代器。您只能以这种方式对向量的一部分进行排序。但是,最常见的情况才刚刚开始,因此在C ++ 20中,他们引入了ranges算法,并且前面的语句可以简化为

std::ranges::sort(numbers);

... AAAND 现在已排序...接下来是打印。您可以使用循环打印...但是即使在那您也可以有很多选择。和索引循环:

for (int i = 0; i < numbers.size(); ++i) {
    std::cout << numbers[i] << ' ';
}

基于迭代器的for循环:

for (auto it = cbegin(numbers); it != cend(numbers); ++it) {
    std::cout << *it << ' ';
}

注意:开始和结束之前的'c'表示它是一个std::sort迭代器,即它可能不会修改其指向的对象的内容。

或基于范围的for循环:

for (int number : numbers) {
    std::cout << number << ' ';
}

还有一种特殊的便捷迭代器类型,可以推入cout"const" qualified。您可以使用算法std::ostream_iterator

将向量复制到此迭代器
std::copy(cbegin(numbers),cend(numbers)," "));

请注意,ostream_iterator的第二个参数是定界符,即在每个元素后附加的字符串。当然,还有C ++ 20系列版本。

std::ranges::copy(numbers," "));

... 最终反转。 一种选择是仅反转向量中的所有元素,然后使用上述方法之一再次打印出它们。当然,有一种算法可以做到:std::copy

std::reverse(begin(numbers),end(numbers));

但是,此操作会修改container(vector)的内容,这可能会很昂贵。如果您不想这样做,则必须以相反的顺序遍历向量

for (int i = numbers.size() - 1; i >= 0; --i) {
    std::cout << numbers[i] << ' ';
}

这看起来很复杂,而且很容易出错。 您可以改为使用向量std::reverse,以相反的顺序遍历向量:(您需要在开头/结尾添加“ r”)

for (auto it = crbegin(numbers); it != crend(numbers); ++it) {
    std::cout << *it << ' ';
}

std::copy(crbegin(numbers),crend(numbers)," "));

对于C ++ 20,没有范围操作可以反转向量。但是,他们引入了reverse iterators,用于以特定方式观察向量中的值。一种这样的方式是“以相反的顺序观察”:"views"。因此,在C ++ 20中,您将能够做到:

for (int number : numbers | std::views::reverse) {
    std::cout << number << ' ';
}

std::ranges::copy(numbers | std::views::reverse," ")); 

这两个都不会修改numbers

最终代码可能看起来像这样(C ++ 20之前的版本):

#include <vector>
#include <iostream>
#include <string_view>
#include <iterator>
#include <algorithm>

template<typename T>
T ReadUserInput(std::string_view message = "") {
    if (!message.empty()) std::cout << message; //only print is there's an actual message
    T value;
    std::cin >> value;
    return value;
}

template<typename T>
auto ReadUserInputGenerator = [](std::string_view message = "") {
    return [message]() { return ReadUserInput<T>(message); };
};

int main() {
    int const N = ReadUserInput<int>("How many numbers do you want to enter?\n");
    std::vector<int> numbers;
    numbers.reserve(N); // good practice to reserve memory if you know the number of elements
    std::generate_n(back_inserter(numbers),ReadUserInputGenerator<int>("Enter a number: "));
    std::sort(begin(numbers),end(numbers));
    std::copy(cbegin(numbers)," "));
    std::cout << '\n';
    std::copy(crbegin(numbers)," "));
    std::cout << '\n';
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...