Предположим, у меня есть N переменных с плавающей запятой x0
, x1
, x2
, ..., xn
.
Я в основном хочу пройтись по каждому из них и суммировать их все в конечной переменной sum
.
Я нахожусь в контексте, когда я не могу использовать структуры данных, такие как массивы, векторы и т. д. Если это поможет, в моем контексте N всегда меньше 10.
Можно ли для этого сделать петлю for
?
Моя первая мысль заключалась в том, чтобы использовать макросы, такие как конкатенация (##
) или что-то в этом роде, но я думаю, что это не подойдет для моего случая.
Почему нельзя использовать массивы или векторы?
У вас не может быть циклов в макросах.
Я не знаком с шейдерами.
Я думал о макросе concat, затем в своем цикле for я бы использовал что-то вроде (x ## i
), но это не работает.
Конкатенация происходит во время компиляции, она не может ссылаться на переменные времени выполнения.
Я только что посмотрел шейдеры, там написано, что они обычно работают на графическом процессоре. У них часто есть инструкции по векторной обработке, вы должны уметь их использовать.
Как насчет этого? Объявите указатель float*
и выделите несколько необходимых байтов. Затем вы индексируете их, увеличивая указатель на единицу.
Является ли код шейдера на самом деле C или C++, как предполагают теги в вопросе? Код шейдера обычно пишется на таких языках, как GLSL, которые отличаются от обычных C или C++.
@kotatsuyaki ты прав, это не то же самое, но очень похоже. Я использую HLSL. В любом случае, мой вопрос касается C/C++.
@Daniel - Напишите генератор кода, который генерирует код, который вы ищете. Запустите генератор кода (и вы можете использовать что угодно, векторы, массивы и т. д., когда вы разработали генератор кода). Затем он сгенерирует код, и вы просто вставите его в свое приложение.
x0, x1, ..., xn
— это n+1
переменные, а не n
«Я нахожусь в контексте, в котором я не могу использовать структуры данных, такие как массивы» — и какой это может быть контекст? Пакет переменных с именами вроде x0, x1... это, конечно, запах кода.
@Daniel Комментарии фактически добавляют к вопросу соответствующую информацию. Как гласит вопрос, разумным предположением было бы предположить, что вы имеете дело со злым учителем. Если бы ваш первый комментарий был частью вопроса, был бы возможен совершенно другой ответ: Некоторые шейдеры действительно позволяют использовать массивы
вам может потребоваться объявить переменные в функции и манипулировать ее кадром стека
не уверен, соответствует ли это вашим потребностям, но вы можете попробовать что-то вроде:
#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, вы не можете перебирать независимые переменные, вы должны использовать какой-то массив (либо в стиле c, либо в стиле C++)
Старая версия ответа лучше соответствует моему вопросу! Спасибо!
Старая версия @Daniel не работает должным образом
Это продвигает наихудший вид копипасты и на самом деле не делает ничего отдаленно похожего на запрос «перебирать переменные по их именам».
Просто выделите память, используя что-то другое, кроме массивов. Массивы или массивоподобные структуры данных были бы наиболее естественными для использования здесь, но поскольку тот, кто создал эту задачу, хотел усложнить вашу жизнь, установив эти ограничения, вы могли бы просто использовать функции, которые просто предоставляют вам память, которую вы могли бы использовать. использовать для хранения элементов.
В 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");
}
Этот подход более хакерский и основан на том, что вы можете не использовать структуры данных, но пользовательские типы не исключены из использования.
Вы можете просто создать структуру, содержащую переменные, которая гарантирует, что они будут храниться одна за другой в памяти, что позволит вам использовать указатель на первую переменную-член, как если бы это был первый элемент массива:
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 Желательно объяснение загрузки. Без него невозможно улучшиться; у других читателей нет возможности узнать, что не так...
Я пишу шейдер, у меня нет доступа к структурам данных. Это как C, но без структур данных.