【问题标题】:How do I get user input from cin into C++11 std::array如何将用户输入从 cin 获取到 C++11 std::array
【发布时间】:2014-09-14 18:08:58
【问题描述】:

如何将用户输入到std::array

这是我拥有的,但它不会编译。

std::array<char, 10> myArray{"hello"} ;
std::cout << "Enter your name: ";
std::cin >> myArray;

如果输入的字符超过 10 个,请截断并忽略它们。我还需要清除 cin 缓冲区以允许稍后进行其他输入。

【问题讨论】:

  • 如果输入超过 10 个字符,您希望发生什么?
  • 截断并忽略它们。我还需要清除 cin 缓冲区以允许稍后进行其他输入。

标签: c++ arrays c++11


【解决方案1】:

对于您当前的示例,您应该使用std::string 而不是std::array&lt;char, 10&gt;。但是,如果您仍然想读取一个数组,您可以按如下方式进行:

#include <iostream>
#include <array>

int main() {
    std::array<int, 10> arr;
    for(int temp, i = 0; i < arr.size() && std::cin >> temp; ++i) {
        arr[i] = temp;
    }

    for(auto&& i : arr) {
        std::cout << i << ' ';
    }
}

输出:

$ ./a.out
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19

基本思想是循环直到数组大小,然后使用其operator[] 将其插入到数组中。您将std::cin &gt;&gt; temp 保留在循环条件中以捕获插入过程中的错误。请注意,标准库中没有为您执行此操作的内置函数。

如果你发现自己经常这样做,你可以把它移到你自己的函数中:

#include <iostream>
#include <array>

template<typename T, size_t N>
std::istream& input_array(std::istream& in, std::array<T, N>& arr) {
    unsigned i = 0u;
    for(T temp; i < arr.size() && in >> temp; ++i) {
        arr[i] = std::move(temp);
    }
    return in;
}

int main() {
    std::array<int, 10> arr;
    input_array(std::cin, arr);
}

您不应该为 std 命名空间内的东西重载 operator&gt;&gt;,因为这是未定义的行为。

如果你想避免临时的,你可以修改函数如下:

template<typename T, size_t N>
std::istream& input_array(std::istream& in, std::array<T, N>& arr) {
    for(unsigned i = 0u; i < arr.size() && in >> arr[i]; ++i) { 
        // empty body
    }
    return in;
}

【讨论】:

  • 只是我很挑剔:辅助函数会从temparr[i] 进行不必要的复制。
  • @GabrielGarcia 这是不可避免的。您可以使用std::move 要求进行移动,但归根结底,必须进行复制或移动。
  • 也许是这个? while (i &lt; N &amp;&amp; in) in &gt;&gt; arr[i++];
  • @GabrielGarcia 稍加修改即可。我已经编辑了答案以考虑到这一点。
  • 发现自 C++11 以来,提取失败的预期行为是将传递的引用归零(不确定此行为是否是用户重载 >> 所预期的)。这意味着我提出的代码可以将用户数组中的元素清零。我想这没关系,考虑到它与标准 >> 重载的行为相同。见:en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt
【解决方案2】:

只需使用适合工作的工具:

std::string name;
std::cout << "Enter your name: ";
std::getline(std::cin, name);

Live demo

【讨论】:

  • Jeffrey 尽管这对于某些目的是正确的,但 OP 并没有问这个。
  • @cell 我认为(我可能弄错了)他在问如何接收字符串输入。这个假设是在请求输入之前写入标准输出的标签上做出的:“输入你的名字:”。我还假设他在某处读到他应该使用char[] 来实现适当的~性能~,然后他可能读到了一些关于std::array 的内容并将它们放在一起;这太可怕了。
  • @cell 万一我错了,我很想听听他试图用那个固定大小的数组做什么的语义是什么,以及其他一些小事情,比如更短的字符串还应该在数组中存储空字符或者溢出等等......
  • Jeffrey 好的,但我认为来自莫斯科的弗拉德的回答以更恰当的方式回答了 OP 的要求。
  • @cell 没问题。欢迎来到堆栈溢出。您可以通过单击答案旁边的向上箭头来对您认为有用的答案进行投票;您还可以(在获得一些初始声誉之后)通过单击向下箭头来对您认为无用的答案投反对票。您可以对问题做同样的事情,以帮助社区对写得很好的问题进行分类。其他信息可以找到here。别忘了开始the tour;你会得到一个徽章! :)
【解决方案3】:

需要 &lt;iostream&gt;&lt;limits&gt; 标头。

std::cin.get(myArray.data(), myArray.size());
// get() will actually read up to myArray.size() - 1 chars
// and add a null character at the end ('\0')

if (std::cin.fail()) {
    // could not read any characters or EOF occurred
} else {
    // drop rest of line that was read to buffer
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    // number of characters read: std::cin.gcount()

    // ... use myArray ...
}

方法参考:

http://en.cppreference.com/w/cpp/io/basic_istream/get

http://en.cppreference.com/w/cpp/io/basic_ios/fail

http://en.cppreference.com/w/cpp/io/basic_istream/ignore

http://en.cppreference.com/w/cpp/io/basic_istream/gcount

【讨论】:

    【解决方案4】:

    您可以将整行放入缓冲区,然后将该缓冲区的前 10 个字节(如果小于 10 则将整个缓冲区)提取到您的数组中。这也解决了std::cin上没有任何垃圾的问题。

    std::array<char, 10> myArray{"hello"} ;
    
    std::string s;
    std::getline( std::cin, s );
    if ( !std::cin )
         throw.....   // input was closed before a line was entered
    
    std::size_t len = std::min( myArray.size(), s.size() );
    std::copy(s.begin(), s.begin() + len, myArray.begin() );
    

    请注意,这不会在 myArray 中创建以 null 结尾的字符串。如果您想这样做,则复制一个额外的字符(并使len 最多为myArray.size() - 1)。

    可能需要包含&lt;array&gt;&lt;iostream&gt;&lt;algorithm&gt;

    【讨论】:

      【解决方案5】:

      std::cin 在这种情况下需要一个字符指针 (char*)。所以你需要使用.data()

      std::array<char, 50> arr{"Hello, "};
      size_t hello_length = strlen(arr.data());
      
      std::cout << "Enter your name: ";
      std::cin >> std::setw(10) >> (arr.data() + hello_length);
      
      std::cout << arr.data() << std::endl;
      

      【讨论】:

      • @MatthiasB,不会添加std::setw 帮助吗?
      【解决方案6】:

      在 C++ 中,数组的指针是第一个元素的地址。
      对于std::array,我们可以通过数组的指针获取输入。

      std::cin >> myArray.begin();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-31
        • 2018-05-19
        • 2012-05-23
        • 2021-02-28
        • 2017-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多