2

我在最后一天一直在解决这个问题,但我仍然对以下代码的解决方案感到迷茫:

#include <stdio.h>
#include <iostream>
#include <map>

int main()
{
    std::map<char *, char *> ourmap;
    std::map<char *, char *>::iterator ourmap_it;

    ourmap["hello"] = "world";
    ourmap["hello"] = "earth";

    char * key = new char[5];
    key[0] = 'h';
    key[1] = 'e';
    key[2] = 'l';
    key[3] = 'l';
    key[4] = 'o';

    char * key_other = new char[5];
    key_other[0] = 'h';
    key_other[1] = 'e';
    key_other[2] = 'l';
    key_other[3] = 'l';
    key_other[4] = 'o';

    ourmap[key] = "venus";
    ourmap[key] = "mars";
    ourmap[key_other] = "jupiter";

    for (ourmap_it = ourmap.begin(); ourmap_it != ourmap.end(); ++ourmap_it)
    {
        printf("map[%s] %s\n", ourmap_it->first, ourmap_it->second);
    }

    ourmap.clear();
    delete key;
    delete key_other;

    return 0;
}

如果您find对动态键执行 , ,则键不会被覆盖,行为相同。输出解释得更详细一点

map[hello] earth
map[hello] mars
map[hello] jupiter

问题 1

在with和with的情况下,为什么 amap没有find不同的两个值等效。const char *@key@key@key_other


问题2

我应该使用不同的容器吗?或使用不同的代码(以不同的方式定义变量)。


在上面的代码中使用动态键没有意义,但我的实际代码需要动态键,如果键值是从文件中读取的,因为我不知道给定键的大小文件,它必须是动态的。问题是虽然我可以设置键,但我无法取回值。

我正在考虑创建一个我自己的发现,它可以strcmp通过键来确定等价性,但这似乎很老套,所以SO在我拒绝之前先咨询一下。

任何帮助都会很棒。谢谢

4

1 回答 1

8

好的。一些想法。

  1. 您正在导致一些未定义的行为。您为一个字符串分配 5 个字节,然后放入该内存中"hello",但您没有足够的空间来终止它。当您尝试打印它时,会发生未定义的行为。
  2. 您不能保证字符串文字的 2 个实例"hello"具有相同的指针。该标准将该选项留给实施。
  3. std::string我会通过使用 a而不是 a 来解决您的大部分问题char *

让我们修复您代码中的一些错误,并继续讨论它:

int main() {
    std::map<char const *, char const *> ourmap;
    std::map<char const *, char const *>::iterator ourmap_it;

    ourmap["hello"] = "world";  // (1)
    ourmap["hello"] = "earth";  // (2)

    char * key = new char[6];
    key[0] = 'h';
    key[1] = 'e';
    key[2] = 'l';
    key[3] = 'l';
    key[4] = 'o';
    key[5] = '\0';

    char * key_other = new char[6];
    key_other[0] = 'h';
    key_other[1] = 'e';
    key_other[2] = 'l';
    key_other[3] = 'l';
    key_other[4] = 'o';
    key_other[5] = '\0';

    ourmap[key] = "venus"; // (3)
    ourmap[key] = "mars";  // (4)
    ourmap[key_other] = "jupiter"; // (5)

    for (ourmap_it = ourmap.begin(); ourmap_it != ourmap.end(); ++ourmap_it)
        printf("map[%s] %s\n", ourmap_it->first, ourmap_it->second);
}

我在代码中引用了 4 个位置。我们对这些钥匙了解多少。

好吧,我们知道(2) != (3) != (5)。但是我们推断出什么手杖(1) ?= (2)。好吧,通常情况下,(1)和(2)会有所不同。但是,该标准允许(但不要求)编译器合并这两个字符串文字以节省内存。话虽如此,大多数编译器都会这样做,尤其是在一个编译单元内。

所以,让我们假设优化发生了。

所以,让我们运行第 1 步。我们的地图现在看起来像:

"hello" (1) => "world"

让我们运行第 2 步。

 "hello" (1) => "earth"

请注意,我们在地图中仍然只有一个元素,因为(1) == (2).

让我们运行第 3 步。

 "hello" (1) => "earth"
 "hello" (3) => "venus"

我们现在在地图中有两个元素,因为我们使用了两个不同的指针作为我们的键。

我将在这里停下来,但我认为这很清楚。


或者,我们可以使用 std::string。

int main() {
    std::map<std::string, std::string> ourmap;
    std::map<std::string, std::string>::iterator ourmap_it;

    ourmap["hello"] = "world";
    ourmap["hello"] = "earth";

    char * key = new char[6];
    key[0] = 'h';
    key[1] = 'e';
    key[2] = 'l';
    key[3] = 'l';
    key[4] = 'o';
    key[5] = '\0';

    char * key_other = new char[6];
    key_other[0] = 'h';
    key_other[1] = 'e';
    key_other[2] = 'l';
    key_other[3] = 'l';
    key_other[4] = 'o';
    key_other[5] = '\0';

    ourmap[key] = "venus";
    ourmap[key] = "mars";
    ourmap[key_other] = "jupiter";

    for (ourmap_it = ourmap.begin(); ourmap_it != ourmap.end(); ++ourmap_it)
        printf("map[%s] %s\n", ourmap_it->first.c_str(), ourmap_it->second.c_str());
}

在这里,输出是:

map[hello] jupiter

这是因为 std::string 的实现<方式与 a 不同char *。它比较字符串的内容。


只是为了扩展最后一件事。这是正在实现的比较器的示例。

struct comparator {
    bool operator()(const char * lhs, const char * rhs) const {
        return strcmp(lhs, rhs) < 0;
    }
};

int main() {
    std::map<char const *, char const *, comparator> ourmap;
    std::map<char const *, char const *, comparator>::iterator ourmap_it;
...

在这种情况下,就像 std::string 一样,我们会看到以下输出:

map[hello] jupiter
于 2013-05-06T16:40:36.283 回答