Если бы у меня был массив let, то для меня было бы 15 элементов, чтобы сделать его 2-мерным массивом с 5x3? Или, если бы у меня была строка с 15 буквами, можно было бы превратить ее в массив 2d с 5x3?
Это то, что у меня есть (используя переменные, но используя 5 как a и 3 как b в консоли)
void finishMap(string map, int a, int b)
{
string finalMap[a][b];
for(int i = 0; b>i; i++)
{
for(int x = 0; a>x; x++)
{
finalMap[a][b] += {{map[x]}, {i}};
}
}
}
Также довольно новый для c++, поэтому, если вы видите что-то, что мне не должно быть, скажите мне: 3
Я использую char arrays (c строк) в своем ответе, потому что я думаю, что они полезны, чтобы проиллюстрировать работу массивов - и действительно, не стоит использовать std :: string в вашем случае. std::string
скрывает много базовых гаек и болтов, поэтому я бы рекомендовал сначала поиграть со строками C, чтобы понять, как работает std::string
. Также ознакомьтесь с этим руководством: http://www.cplusplus.com/doc/tutorial/arrays/
2-мерный массив имеет тот же макет памяти, что и 1-й массив. Что касается макета памяти, char[3][5]
совпадает с char[3*5]
, то такой же, как char[15]
. Вы можете использовать 1-й массив как 2-мерный массив, используя char[column+row*width]
. Единственная разница, если вы используете индексы, заключается в том, что компилятор запоминает, сколько измерений существует и будет выполнять весь расчет column+row*width
для вас.
Возьмем следующий пример:
char temp[5] = "abcd"; //need 5 for string termination char '\0'
for(int i = 0; i < 4; ++i) {
std::cout << temp[i];
}
std::cout << "\n\n";
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
std::cout << temp[j+2*i];
}
std::cout << std::endl;
}
Будет печать:
abcd
ab
cd
Okey, поэтому я использовал что-то немного отличное от того, что я упомянул. Я сделал, чтобы пользователь вводил 3 строки из 5 букв длины, которые я выяснил, как добавить в массив 2d. Если у вас такая же проблема, как и у меня, мой код:
int main()
{
string path;
int a, b;
cin >> a >> b;
string finalMap[a][b];
for(int i = 0; b>i; i++){
cin >> path;
for(int x = 0; a>x; x++){
finalMap[x][i] = (path[x]);
}
}
for(int x = 0; b>x; x++)
{
for(int y = 0; a>y; y++)
{
cout << finalMap[y][x];
}
cout << endl;
}
return 0;
}
Спасибо, что попробовали, действительно ценю это.
finalMap[x][i]
оценивается аналогично finalMap[x*b + i]
, что означает, что вы обращаетесь к массиву столбец за столбцом. Современному оборудованию это не нравится, это может означать много дополнительных кеш-пропусков, что может привести к значительному снижению производительности. Поэтому рекомендуется поменять порядок координат: замените finalMap[a][b]
на finalMap[b][a]
и проделайте то же самое с двумя другими строками, которые обращаются к finalMap
.
Вы можете попробовать использовать reinterpret_cast
. Полный пример:
#include <iostream>
using namespace std;
typedef char mtrx[5][3];
int main(){
char data[15] = "Some String";
mtrx &m = *reinterpret_cast<mtrx*>(&data);
m[1][2] = '*';
cout << data << endl;
return 0;
}
data
или m
( data[5]='x'
совпадает с m[1][2]='x'
), они оба ссылаются на одну и ту же память Только не выходи за пределы досягаемости.
Вы всегда можете получить доступ к массиву в шагах. Вот возможный пример использования шаблонов для ограничения массива 1D как 2D-массив:
template <typename T, unsigned int N1, unsigned int N2>
struct strider
{
using array_type = T[N1 * N2];
array_type & data_;
Strider(array_type & data) : data_(data) {}
T & operator()(std::size_t i1, std::size_t i2)
{
return data_[i1 * N2 + i2];
}
};
template <unsigned int N1, unsigned int N2, T>
strider<T, N1, N2> stride(T (&a)[N1, N2]) { return {a}; }
Применение:
int a[15] = {};
strider<int, 3, 5> s(a);
s(1, 2) = 20;
assert(a[7] == 20);
stride<5, 3>(a)(4, 2) = 10;
assert(a[14] == 10);
Я перегрузил operator()
для плавного доступа, так как в отличие от operator[]
он может иметь подписи arbirary.
С некоторой дополнительной работой вы можете сделать ранг чередующегося вида вариативным.
string finalMap[a][b];
string finalMap[a][b];
но на самом деле это не делает то, что он думает.