Как я могу перебирать переменные по их именам?

Предположим, у меня есть N переменных с плавающей запятой x0, x1, x2, ..., xn.

Я в основном хочу пройтись по каждому из них и суммировать их все в конечной переменной sum.

Я нахожусь в контексте, когда я не могу использовать структуры данных, такие как массивы, векторы и т. д. Если это поможет, в моем контексте N всегда меньше 10.

Можно ли для этого сделать петлю for?


Моя первая мысль заключалась в том, чтобы использовать макросы, такие как конкатенация (##) или что-то в этом роде, но я думаю, что это не подойдет для моего случая.

Я пишу шейдер, у меня нет доступа к структурам данных. Это как C, но без структур данных.

Daniel 19.11.2022 06:05

Почему нельзя использовать массивы или векторы?

Barmar 19.11.2022 06:06

У вас не может быть циклов в макросах.

Barmar 19.11.2022 06:06

Я не знаком с шейдерами.

Barmar 19.11.2022 06:06

Я думал о макросе concat, затем в своем цикле for я бы использовал что-то вроде (x ## i), но это не работает.

Daniel 19.11.2022 06:07

Конкатенация происходит во время компиляции, она не может ссылаться на переменные времени выполнения.

Barmar 19.11.2022 06:08

Я только что посмотрел шейдеры, там написано, что они обычно работают на графическом процессоре. У них часто есть инструкции по векторной обработке, вы должны уметь их использовать.

Barmar 19.11.2022 06:10

Как насчет этого? Объявите указатель float* и выделите несколько необходимых байтов. Затем вы индексируете их, увеличивая указатель на единицу.

Virux 19.11.2022 06:11

Является ли код шейдера на самом деле C или C++, как предполагают теги в вопросе? Код шейдера обычно пишется на таких языках, как GLSL, которые отличаются от обычных C или C++.

kotatsuyaki 19.11.2022 06:21

@kotatsuyaki ты прав, это не то же самое, но очень похоже. Я использую HLSL. В любом случае, мой вопрос касается C/C++.

Daniel 19.11.2022 06:27

@Daniel - Напишите генератор кода, который генерирует код, который вы ищете. Запустите генератор кода (и вы можете использовать что угодно, векторы, массивы и т. д., когда вы разработали генератор кода). Затем он сгенерирует код, и вы просто вставите его в свое приложение.

PaulMcKenzie 19.11.2022 06:58
x0, x1, ..., xn — это n+1 переменные, а не n
fabian 19.11.2022 09:42

«Я нахожусь в контексте, в котором я не могу использовать структуры данных, такие как массивы» — и какой это может быть контекст? Пакет переменных с именами вроде x0, x1... это, конечно, запах кода.

user7860670 19.11.2022 09:51

@Daniel Комментарии фактически добавляют к вопросу соответствующую информацию. Как гласит вопрос, разумным предположением было бы предположить, что вы имеете дело со злым учителем. Если бы ваш первый комментарий был частью вопроса, был бы возможен совершенно другой ответ: Некоторые шейдеры действительно позволяют использовать массивы

fabian 19.11.2022 10:15

вам может потребоваться объявить переменные в функции и манипулировать ее кадром стека

incompetent 19.11.2022 10:43
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
2
16
97
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

не уверен, соответствует ли это вашим потребностям, но вы можете попробовать что-то вроде:

#define SUM_X0 (x0)
#define SUM_X1 (SUM_X0 + x1)
#define SUM_X2 (SUM_X1 + x2)
#define SUM_X3 (SUM_X2 + x3)
#define SUM_X4 (SUM_X3 + x4)
#define SUM_X5 (SUM_X4 + x5)
#define SUM_X6 (SUM_X5 + x6)
#define SUM_X7 (SUM_X6 + x7)
#define SUM_X8 (SUM_X7 + x8)
#define SUM_X9 (SUM_X8 + x9)

int main(int argc, char* argv[]) {

    int x0, x1, x2, x3, x4, x5;
    if (scanf("%d %d %d %d %d %d", &x0, &x1, &x2, &x3, &x4, &x5) != 6) {
        printf("error");
        return 1;
    }

    printf("%d\n", SUM_X0);
    printf("%d\n", SUM_X1);
    printf("%d\n", SUM_X2);
    printf("%d\n", SUM_X3);
    printf("%d\n", SUM_X4);
    printf("%d\n", SUM_X5);

    return 0;
}

Есть ли способ сделать это циклом for и получить переменную по индексу for? Я предполагаю, что это невозможно, так как макросы запускаются во время компиляции...

Daniel 19.11.2022 06:28

@Daniel, вы не можете перебирать независимые переменные, вы должны использовать какой-то массив (либо в стиле c, либо в стиле C++)

Iłya Bursov 19.11.2022 06:59

Старая версия ответа лучше соответствует моему вопросу! Спасибо!

Daniel 19.11.2022 07:02

Старая версия @Daniel не работает должным образом

Iłya Bursov 19.11.2022 07:25

Это продвигает наихудший вид копипасты и на самом деле не делает ничего отдаленно похожего на запрос «перебирать переменные по их именам».

user7860670 19.11.2022 09:52

Опция 1

Просто выделите память, используя что-то другое, кроме массивов. Массивы или массивоподобные структуры данных были бы наиболее естественными для использования здесь, но поскольку тот, кто создал эту задачу, хотел усложнить вашу жизнь, установив эти ограничения, вы могли бы просто использовать функции, которые просто предоставляют вам память, которую вы могли бы использовать. использовать для хранения элементов.

В C вы бы использовали malloc, но в C++ использование распределителя для этого предпочтительнее.

/**
 * Execute the desired logic with \p inputText as content of the input
 */
void Test(char const* inputText)
{
    std::allocator<float> allocator;

    size_t const n = 9;

    auto deleter = [n, &allocator](float* mem) {allocator.deallocate(mem, n); };

    // notAnArray makes sure the memory gets freed by calling allocator.deallocate(<allocated memory>, n)
    std::unique_ptr<float[], decltype(deleter)> notAnArray{ allocator.allocate(n), deleter };

    std::istringstream input{inputText};

    size_t count = 0;

    for (; count != n; ++count)
    {
        if (!(input >> notAnArray[count]))
        {
            break;
        }
    }

    std::cout << count << "  elements read\n";

    float sum = 0;
    for (size_t i = 0; i != count; ++i)
    {
        sum += notAnArray[i];
    }

    std::cout << "sum = " << sum << "\n------------------------\n";
}

int main()
{
    Test("1 2 3 4 5 6 7 8 9 10");
    Test("");
    Test("5 4 32 1");
}

Вариант 2

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

Вы можете просто создать структуру, содержащую переменные, которая гарантирует, что они будут храниться одна за другой в памяти, что позволит вам использовать указатель на первую переменную-член, как если бы это был первый элемент массива:


constexpr size_t MaxCount = 9;

struct NotAnArray
{
    float x0;
    float x1;
    float x2;
    float x3;
    float x4;
    float x5;
    float x6;
    float x7;
    float x8;
};

static_assert((offsetof(NotAnArray, x8) - offsetof(NotAnArray, x0)) == (sizeof(float) * (MaxCount - 1)));

/**
 * Execute the desired logic with \p inputText as content of the input
 */
void Test(char const* inputText)
{
    NotAnArray storage;
    float* const notAnArray = &storage.x0;

    std::istringstream input{inputText};

    size_t count = 0;

    for (; count != MaxCount; ++count)
    {
        if (!(input >> notAnArray[count]))
        {
            break;
        }
    }

    std::cout << count << "  elements read\n";

    float sum = 0;
    for (size_t i = 0; i != count; ++i)
    {
        sum += notAnArray[i];
    }

    std::cout << "sum = " << sum << "\n------------------------\n";
}

@Downvoter Желательно объяснение загрузки. Без него невозможно улучшиться; у других читателей нет возможности узнать, что не так...

fabian 19.11.2022 10:10

Другие вопросы по теме