Создание определения имен с использованием строк - PullRequest
0 голосов
/ 28 мая 2018

Я получил несколько постоянных int значений, которые я хотел бы использовать, поэтому я использовал #define.

Проблема в том, что у меня есть некоторые определяемые имена, такие как:

#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 ]

0 голосов
/ 28 мая 2018

Предпочитать переменную const над MACRO

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

Затем, чтобы перебирать их, имя не нужно, просто выполните

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

Возможно, вы захотите создать переменную для спискачтобы избежать повторения, если вы повторяете в нескольких местах.

0 голосов
/ 28 мая 2018

Другой подход - создать некоторый файл C ++, содержащий то, что вы хотите.Так что для этой цели вам необходимо настроить build .Вы часто используете какой-либо инструмент для автоматизации сборки (например, GNU make , ninja и т. Д.), И вы можете настроить его для генерации некоторого файла C ++ при необходимости(например, добавив несколько строк в ваш Makefile, если вы используете make).Программа, генерирующая некоторый код на C ++, может быть скриптом (например, в shell , awk , Python , Guile , ...),какая-то специализированная метапрограмма (например, moc для программ на Qt), какой-то другой препроцессор, такой как GPP или m4 , или ваша собственная другая программа на C ++ и т. д. Такой подход метапрограммированияобычно используется с C ++ и C с прошлого столетия (для примера смотрите Qt moc , bison , SWIG , ...)

См. Также этот ответ на связанный вопрос (с 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 на основе ) подходы.

0 голосов
/ 28 мая 2018

Есть ли способ в коде каким-то образом перебрать их, чтобы создать их имя со строками, а затем получить определенное значение этих построенных строк?

Нет, нет никакого способачтобы сделать это, используя define.

Вам нужно будет поместить значения в некоторый контейнер, чтобы иметь возможность перебирать значения.

Если вы просто хотите сохранить значения, вы можете использовать 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;
}
0 голосов
/ 28 мая 2018

Макрос анализируется препроцессором и неизвестен процессору (вы не можете использовать их в своем коде).

Если вы хотите связать имя со значением, вы можете использовать карту константи выражение 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 (или выше), чтобы это работало.

0 голосов
/ 28 мая 2018

Строки, начинающиеся с #, оцениваются препроцессором - компилятор их не видит, только их эффекты.Поэтому код 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

Чтобы получить более подробные объяснения суффиксов, определяющих тип, взгляните на целочисленные литералы и литералы с плавающей точкой.Возможно, вы также захотите почитать о constexpr позже, когда вам удобнее работать с C ++ для изучения выражений с постоянными времени компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...