代码之家  ›  专栏  ›  技术社区  ›  CodeMonkey

使用字符串构造定义名称

  •  2
  • CodeMonkey  · 技术社区  · 7 年前

    我得到了一些常数 int 我想使用的值,所以我使用了定义。

    问题是我有一些这样的定义名称:

    #define a1  123
    #define a2  6543
    #define a3  12
    ...
    

    代码中是否有一种方法可以通过迭代来用字符串构造名称,然后获取所构造字符串的定义值?我指的是一个伪代码:

    for(int i =0 ; i < 100; i++)
    {
       string name = "a" + i;
       func(GetDefineName(name)); // should call here every time to func with a1,a2 etc.
    }
    

    我习惯了C语言,所以我习惯了C++的一些问题。定义真的是最合适的方法吗?

    5 回复  |  直到 7 年前
        1
  •  2
  •   4386427    7 年前

    代码中是否有一种方法可以通过迭代来用字符串构造名称,然后获取所构造字符串的定义值?

    不,使用defines无法做到这一点。

    您需要将这些值放入某个容器中,以便能够迭代这些值。

    如果您只想存储值,可以使用STD::vector。

    如果您想要同时拥有名称和值,可以使用STD::MAP。比如:

    #include <iostream>
    #include <string>
    #include <map>
    
    #define a0 42
    #define a1 5
    #define a2 15
    #define a3 25
    
    int main() {
        // Define the map
        std::map<std::string, int> m;
    
        // Intialize the map
        m["a0"] = a0;
        m["a1"] = a1;
        m["a2"] = a2;
        m["a3"] = a3;
    
        // Access map using name
        for(size_t i =0 ; i < m.size(); i++)
        {
            std::string name = "a" + std::to_string(i);
            std::cout << m[name] << std::endl;
        }
    
        // Iterate all map elements
        for (auto& x : m)
        {
            std::cout << x.first << ":" << x.second << std::endl;
        }
        return 0;
    }
    
        2
  •  3
  •   Loebl    7 年前

    以开头的行 # 由预处理器评估-编译器不会看到它们,只会看到它们的效果。因此,C++代码不能与预处理器变量交互,因为在编译代码时它们不再存在。

    常数可以这样定义,但是C++提供了更好的方法。例如,可以将它们包装在名称空间中,以避免名称冲突。

    //auto lets the compiler deduce the type for you
    auto const my_var = 4.5; //double
    auto const close_to_pi = 3.4f; //float
    auto const the_answer = 42; //int
    auto const kibibyte = 1024u; //unsigned int
    

    要获得关于类型定义后缀的更多解释,请查看 integer literals floating point literals . 你可能还想继续读下去 constexpr 稍后,当您更舒适地使用C++来探索编译时常量表达式时。

        3
  •  2
  •   Basile Starynkevitch    7 年前

    另一种方法是 生成 一些C++文件,包含你想要的内容。所以你需要设置 build 为此目的。你经常用一些 build automation 工具(如 GNU make , ninja 等等,你可以在需要时配置它来生成一些C++文件(例如在你的文件中添加几行)。 Makefile ,如果您使用 make )生成一些C++代码的程序可以是一些脚本(例如 shell , awk , Python , Guile ,…),一些专门的元程序(例如 moc 对于qt程序),一些其他的预处理器 GPP m4 ,或者你自己的其他C++程序,等等。这种元编程方法自上世纪以来一直与C++和C一起使用(查看Qt)。 moc , bison , SWIG ,…例如)。

    另请参见 this 回答相关问题(用c)。

    您将生成一些包含类似

    #define a1  123
    #define a2  6543
    #define a3  12
    

    (你不想 = 在这种情况下 #define -S)

    或者你可能会产生一些 enum 喜欢

    enum number_en {
     a1= 123,
     a2= 6543,
     a3= 12,
    };
    

    注意,在运行时生成C++代码可能比运行时更有效(因为构建时间)解决方案(例如)。 std::map based )方法。

        4
  •  1
  •   Clonk    7 年前

    宏由预处理器解析,处理器不知道(不能在代码中使用)。

    如果要将名称与值关联,可以使用const map和constexpr表达式:

    constexpr std::string a1="a1";
    constexpr std::string a2="a2";
    constexpr std::string a3="a3";
    
    const std::map<std::string, int> = {
        {a1, 123},
        {a2, 6543},
        {a3, 12} 
    }
    

    为了工作,你需要C++ 11(或以上)。

        5
  •  1
  •   Jarod42    7 年前

    与宏相比,首选常量变量

    constexpr auto a1 = 123;
    constexpr auto a2 = 6543;
    constexpr auto a3 = 12;
    

    然后迭代它们,不需要名字,只要做

    for (auto e : {a1, a2, a3}) {
        func(e);
    }
    

    如果在多个位置迭代,可能需要为列表创建一个变量以避免重复。