【问题标题】:Printing Associative Array in C++在 C++ 中打印关联数组
【发布时间】:2011-06-03 20:50:51
【问题描述】:

我已经声明了一个关联数组,现在想打印它:

#include <map>
#include <string>
#include <cstdio>

using namespace std;

int main() {
    map<string, int> m;

    m["Peter"] = 4;
    m["John"] = 3;
    m["Katie"] = 3;

    map<string, int>::iterator curr,end;

    for(curr = m.begin(), end = m.end(); curr != end; curr++) {
        printf("%s : %i\n", curr->first, curr->second);
    }
    return 0;
}

我的编译器出现错误:

main.cpp: In function ‘int main()’:
main.cpp:24: warning: cannot pass objects of non-POD type ‘const struct std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ through ‘...’; call will abort at runtime

还有惊喜 - 这是真的 - 在运行时调用中止......

但我不知道为什么...我应该解决什么问题? “通过‘...’”到底是什么意思?

【问题讨论】:

    标签: c++ arrays associative-array


    【解决方案1】:

    尝试:

        printf("%s : %i\n", curr->first.c_str(),  curr->second);
    

    c_str() 方法将 std::string 转换为 c 风格的字符串 (char*)。

    ... 指的是printfvararg 原型:

    int printf(const char *format, ...);
    

    不支持传递 c++ 对象。


    顺便说一句,您应该使用++curr 而不是curr++。这是一些防止重复引用的 c++ 魔法。

    【讨论】:

      【解决方案2】:

      在 C++ 中使用 std::cout,尤其是在 STL 中:

      std::cout << curr->first << " : " << curr->second << std::endl;
      

      顺便说一句,不需要再定义另一个名为“end”的变量。因此,您可以改写您的 for 循环,如下所示:

       for(map<string, int>::iterator curr = m.begin(); curr != m.end() ; curr++) 
       {
             std::cout << curr->first << " : " << curr->second << std::endl;
       }
      

      【讨论】:

      • 在容器长度不变的情况下(如本例),只计算一次end并没有错。
      【解决方案3】:

      您正在尝试 printf std::string 类。使用 cout,printf 仅适用于整数类型

      【讨论】:

        【解决方案4】:

        问题在于可变参数函数(带有无限数量参数的函数,如 printf)不能很好地与 C++ 对象配合使用。在纯 C 的“好”时代,可变参数工作得很好,因为没有状态对象的概念。您可以按照您认为合适的方式从某个结构或其他对象中复制这些位,而不会遇到任何问题。但是,在 C++ 中,对象具有构造函数和析构函数,它们用于控制内部状态。您不能只是盲目地从其他地方的 C++ 对象中复制这些位并期望得到一个工作副本。

        可变参数函数的问题在于,在可变参数函数内部,该函数从参数列表中检索参数的典型方式是盲目地复制字节。这破坏了各种不变量,因此 C++ 规范明确指出这会导致未定义的行为。在这种情况下,“未定义的行为”意味着“编译器将在您发生真正糟糕的事情之前终止程序。”

        您收到此错误的原因是您传递给 printf 的参数之一是 std::string,这是一个真正的 C++ 对象,具有重要的构造函数、析构函数和复制函数。由于我上面提到的原因,编译器告诉你这是不行的。要解决此问题,您需要将其他内容传递给函数,正如此处其他一些海报所建议的那样。或者,您应该只使用 std::cout 进行打印,因为它是完全类型安全的并且不使用可怕的可变参数函数。

        希望这会有所帮助!

        【讨论】:

          【解决方案5】:

          您正在混合使用 C 和 C++,您正在使用 const struct std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; 类型的对象调用 C 语言 stdio print 函数(这是 curr-&gt;first 映射键 - 字符串的类型)

          试试这个

          cout <<  curr->first <<  curr->second << endl;
          

          【讨论】:

            【解决方案6】:

            作为旁注,没有真正的理由使用特殊的end 变量来检查容器的结束:首先,end() 通常是一个内联函数,只是返回结束指示,其次,任何像样的无论如何,编译器都会对此进行优化。我会这样写你的代码:

            typedef map<string, int> Score;
            
            Score sc;
            // ... set values ...
            
            for(Score::const_iteator curr = sc.begin(); curr != sc.end(); ++curr) {
                cout << curr->first << ": " << curr->second;
            }
            

            【讨论】:

              猜你喜欢
              • 2011-09-19
              • 2011-01-20
              • 1970-01-01
              • 2019-05-28
              • 1970-01-01
              • 2018-06-04
              • 2022-11-27
              • 2017-09-18
              • 2013-09-23
              相关资源
              最近更新 更多