用C ++打印关联数组

时间:2011-01-05 08:05:31

标签: c++ arrays associative-array

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

#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

令人惊讶的是 - 这是真的 - 在运行时调用中止......

但我不知道为什么......我该怎么办?究竟是什么意思“通过'...'”?

6 个答案:

答案 0 :(得分:3)

在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;
 }

答案 1 :(得分:2)

尝试:

    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 :(得分:2)

问题在于varargs函数(带有无限数量参数的函数,如printf)与C ++对象不能很好地兼容。在纯粹的C“好”的日子里,varargs工作得很好,因为没有状态对象的概念。您可以根据需要复制某些结构或其他对象中的位而不会遇到任何问题。但是,在C ++中,对象具有构造函数和析构函数,用于控制内部状态。你不能盲目地从其他地方的C ++对象中复制这些位,并期望得到一份工作副本。

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

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

希望这有帮助!

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

试试这个

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

答案 5 :(得分:0)

作为附注,没有真正的理由使用特殊的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;
}