在地图中搜索值的C ++类和方法

时间:2014-10-29 17:46:16

标签: c++

我写了一个最低级别,以便更好地提交我的问题。

我有三个文件:

1)test.hpp

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

class test {
  public:
    test () {}
    ~test () {}
    const char *getPin (const char *);
  private:
    static const std::map<const char *, const char *> pinIndex;
    static std::map<const char *, const char *> initializePins ();

};

2)test.cpp

#include "test.hpp"

const std::map<const char *, const char *> test::pinIndex = test::initializePins ();

std::map<const char *, const char *> test::initializePins () {
  std::map<const char *, const char *> pins;

  pins.insert (
    std::pair<const char *, const char *> (
      "AAAA", "BBBB"
    )
  );

  return pins;
}

const char *test::getPin (const char *pinNumber) {
  if (pinIndex.count (pinNumber) > 0) {
    return pinIndex.at (pinNumber);
  }
  else {
    printf ("Undefined pin %s!\n", pinNumber);
    exit (EXIT_FAILURE);
  }
}

3)main.cpp

#include "test.hpp"

int main () {
  test myExample;

  const char *a = myExample.getPin ("AAAA");

  exit (EXIT_SUCCESS);
}

当我编译并运行它时,我收到此错误:

  

未定义的引脚AAAA!

如果我删除main.cpp并将main函数放在test.cpp文件中,我不会收到任何错误,GetPin会返回正确的值。

知道我做错了什么吗?

谢谢

3 个答案:

答案 0 :(得分:3)

您的问题是您在地图中使用char*指针作为关键值。要在地图中查找条目,实现将对给定密钥使用比较操作(<)。

如果您要比较char*指针,那些几乎永远不会相同,并且与其内容完全无关,这正是您实际想要查找的内容。

解决问题的简单方法是将地图类型更改为

std::map<std::string, std::string>

另一种可能的解决方案是提供一个类,根据内容比较两个char*指针作为地图的第三个模板参数

std::map<char*, char*, MyComparer>

其中MyComparer是s.th.像这样

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

作为解释为什么在将测试移动到单独的编译单元时遇到看似不一致的行为的原因:
如果您在TU中多次出现相同的字符串文字(例如"AAAA"),编译器可以优化它们只存储一次,因此您的所有外观都具有相同的地址。

答案 1 :(得分:1)

无法保证“AAAA”与您程序中其他位置使用的“AAAA”具有相同的地址。因此,由于地图将比较指针值,因此无法保证找到“AAAA”。

使用std::map<std::string, std::string>代替std::map<const char *, const char *>,您的问题应该得到解决。

答案 2 :(得分:0)

您的解决方案非常简单:

#include <iostream>
#include <map>
#include <string>

int
main ()
{
  std::map<std::string, std::string> pins { { "AAAA" , "BBBB" }, { "CCCC" , "DDDD" } };

  auto lookup = pins.find("AAAA");
  if (lookup != pins.end())
    std::cout << "Pin AAAA found!" << std::endl;
  else
    std::cerr << "Pin AAAA not found!" << std::endl;

  return 0;
}

一些建议:

  1. 切勿在C ++代码中使用c-strings。这不是更快,但更重要的是处理。 std :: string总是知道长度并且在比较中表现更好。
  2. 尽可能少写,因为KISS(保持简单愚蠢)90%是最好的主意。