【问题标题】:cout operator << doesn't work for vector<char> [duplicate]cout 运算符 << 不适用于 vector<char> [重复]
【发布时间】:2022-01-20 00:49:36
【问题描述】:

为什么这个向量没有打印出来?

 void str_read(std::vector<char> str);

 int main() {
     std::vector<char> str;
     str_read(str);
     std::cout << str << std::endl;

     return -1;
 }

 void str_read(std::vector<char> str) {
     while (1) {
         char ch;
         scanf("%c", &ch);
         if (ch == '\n');
         break;
     }   
 }

我收到一个错误:

error: no type named 'type' in 'struct std::enable_if<false, void>'

【问题讨论】:

  • 在评估来自编译器的错误消息时,您希望解决错误列表中的第一个错误。不是最后一个。第一个之后的任何一个都很有可能是第一个错误的结果。
  • 还有一个问题。 str_read 按值接受参数,所以你对函数内部的向量所做的任何事情都会在函数结束时丢失。
  • if(ch == '\n');那个分号可能会给你带来一些问题。
  • 您的错误消息的原因是没有接受std::vector 作为参数的operator&lt;&lt;()。如果您引用了编译器发出的 FIRST 错误消息,而不是 LAST (许多),那将会有所帮助。当编译器在发出错误消息后继续运行时,它往往处于某种混乱状态——这种混乱往往会增加,因此错误消息与后续代码的关系较小。

标签: c++ ostream


【解决方案1】:

您收到错误是因为没有为std::vector 定义标准operator&lt;&lt;。如果你想这样做,你必须自己实现它。

即便如此,str_read() 接收std::vector 按值,因此它接收到调用者vector副本,因此它所做的任何修改将被复制到该副本,因此在str_read() 退出时丢失。这意味着永远不会填充 main() 中的 vector

试试这个:

#include <iostream>
#include <vector>
#include <string>

std::ostream operator<<(std::ostream &out, const std::vector<char> &vec) {
    for(auto ch : vec) {
        out << ch;
    }
    return out;

    /* alternatively:
    return out.write(vec.data(), vec.size());
    */ 
}

void str_read(std::vector<char> &str) {
    char ch;
    while (cin.get(ch) && ch != '\n') {
        str.push_back(ch);
    }   
}

int main() {
    std::vector<char> str;
    str_read(str);
    std::cout << str << std::endl;
}

话虽如此,为什么不直接使用std::string 而不是std::vector&lt;char&gt;?为std::string 定义了一个标准operator&lt;&lt;,还有一个标准std::getline() 函数用于将字符读入std::string 直到'\n'

#include <iostream>
#include <string>

int main() {
    std::string str;
    std::getline(cin, str);
    std::cout << str << std::endl;
}

【讨论】:

    【解决方案2】:

    这里有 3 个大问题。

    • 您是按值传递向量,而不是按引用传递。因此,对函数中的向量所做的任何更改都将保留在作为该函数调用堆栈的一部分初始化的向量的本地。在您返回时将被删除。所以把签名改成str_read(std::vector&lt;char&gt;&amp; str)
    • 您正在逐个字符地进行stdin 捕获。 AFAIK scanf 虽然会读取换行符,但会将其留在缓冲区中,而不是将其附加到您的字符串中。从外观上看,您要做的就是从stdin 中读取一个字符串,将其存储在一个字符数组中,然后将该字符数组打印出来。不要过度设计东西。只需使用std::cin 并将其存储在一个字符串中,就像
    std::string captured_string;
    std::getline(std::cin, captured_string);
    

    然后你可以直接std:cout &lt;&lt; captured_string &lt;&lt; "\n";

    • 如果您坚持将字符存储在向量中,我不明白您为什么需要这样做,您可以使用std::vector&lt;uint8_t&gt; char_array(captured_string.begin(), captured_string.end())。但是,std::cout &lt;&lt; char_array &lt;&lt; "\n" 仍然不起作用。这有两个原因,第一个是std::vector&lt;T, allocator&gt; 没有&lt;&lt;std::ostream 过载。第二个是当您将字符串转换为字符数组时,它们的含义并不相同。

    我认为您误解了您在课堂上所学的有关将字符串存储为字符数组的内容。它们确实存储为数组,但数组类型和字符串类型有本质的不同,并不等价。

    如上所示,从stdin 捕获字符串无论如何都会将其存储在char*std::string 中。您可以直接使用它,而无需将字符串转换为字符数组。

    本质上,您的程序会衰减到这个

    #include <iostream>
    #include <string>
    
    int main()
    {
      std::string captured_string;
      std::getline(std::cin, captured_string);
      std::cout << captured_string << "\n";
      return EXIT_SUCCESS;
    }
    

    编辑

    我刚刚意识到您的目标可能是逐个字符地打印字符串。在这种情况下,您不需要将其转换为数组。有多种方法可以做到这一点,但最不容易混淆并且可能是最简单的方法是使用基于范围的 for 循环。

    int main()
    {
      std::string captured_string;
      std::getline(std::cin, captured_string);
      for (auto& ch: captured_string) // containers in the standard library support range based for loops.
        std::cout << ch << "\n"; // print each character in the string on a new line
      return EXIT_SUCCESS;
    }
    

    【讨论】:

      【解决方案3】:

      首先解释一下

      错误:'struct std::enable_if' 中没有名为 'type' 的类型

      coutcharacter-oriented 流输出,不接受vector&lt;char&gt; 类型的输出格式。

      Vector 是指定类型的元素数组。如果要使用向量,可以先在其中存储值:

      vector<char> str;
      str.push_back('H');
      

      然后将数组的一个元素打印到标准输出cout

      cout << str[0] <<endl;
      

      第二个问题是你的函数str_read被定义为void,它没有值,所以在cout的标准输出中也找不到。

      您似乎想将字符作为输入放入vector 并打印出来。如果将函数定位为void,则需要更改strby reference的值

      下一个问题,我看到您的 while 循环中断时间不正确,并且没有与 if 结合使用。不应在 if 语句后添加分号。

      if (ch == '\n')break;
      

      最后,如果你选择通过引用来改变str的值,你需要在函数中实现这个,如上所述,当你键入ch的值时,你需要使用str.push_back(ch)来存储它。

      【讨论】:

        【解决方案4】:

        当您尝试显示时,您的“str”变量中没有任何内容。无论如何,您也不会将向量初始化为任何变量以供函数读取。

        【讨论】:

        • 如果程序被编译,那么在运行时不会有任何输出,因为向量是空的,但这是一个关于编译错误而不是任何可能的运行时行为的问题。
        猜你喜欢
        • 2020-01-25
        • 2013-11-30
        • 1970-01-01
        • 1970-01-01
        • 2020-07-13
        • 2015-06-13
        • 2012-01-14
        • 1970-01-01
        • 2012-10-24
        相关资源
        最近更新 更多