#c #arrays #for-loop #multidimensional-array #std
#c #массивы #for-цикл #многомерный массив #ЗППП
Вопрос:
Я довольно новичок в программировании на C , и я застрял на том, как печатать значения из определенной строки.
Я имею в виду:
std::string musical_things [][][] = {
{
{"Scale"}, {"Minor Natural"}, {"1","2","b3","4","5","b6","b7"}
},
{
{"Scale"}, {"Major"}, {"1","2","3","4","5","6","7"}
},
};
Итак, когда я пытаюсь получить доступ только к одной полной строке, я получаю адрес памяти.
Если я выполняю цикл, я получаю адрес памяти каждого элемента.
for (int i = 0; i < 10; i )
std::cout << "Output: " << musical_things [i]<< "n" << std::endl;
И я просто пытаюсь понять musical_things [i]
.
Для i = 0 вывод должен быть следующим: {"Scale"}, {"Chromatic"}, {"1","2","3","4","5","6","7"}
.
Комментарии:
1. не существует автоматического способа печати строки массива. Вам нужно сделать это самостоятельно, повторяя отдельные элементы
2. в опубликованном вами коде, который вы повторяете, самым внешним измерением
musical_things[i]
является 2d-массив.musical_things[i][j]
это одномерный массив, и его элементыmusical_things[i][j][k]
представляют собой строки, которые вы можете распечатать с помощьюstd::cout <<
3. однако здесь не следует использовать 3D-массив. Это делает ненужную компиляцию. Скорее напишите структуру, содержащую данные, и используйте
std::vector<my_struct>
4. к сожалению, c не заботится о том, что вы хотите. Нет другого способа распечатать строку вашей матрицы, кроме перебора отдельных строк и их печати
5. «потому что мне придется перегрузить оператор cout » нет, это не недостаток
std::vector
. Вы не можете распечатать вектор так, как хотите, точно так же, как вы не можете распечатать массив так, как хотите. Ваша непосредственная проблема была бы точно такой же с вектором, просто решение оооочень намного проще
Ответ №1:
Для ostream
оператора s нет перегрузки <<
, который делает то, что вы хотите напрямую. Вам нужно перебрать строки и распечатать их:
for (int i = 0; i < 10; i ) {
std::cout << "Output: ";
for (int j = 0; j < 10; j ) {
for (int k = 0; k < 10; k ) {
std::cout << musical_things[i][j][k];
}
std::cout << "n";
}
Я предположил, что все измерения имеют размер 10, чего нет в вашем примере. Управление размерами многомерных c-массивов — это беспорядок, вместо этого вы должны использовать a std::vector
или, скорее, определить структуру, которая содержит данные, которые принадлежат друг другу. Высока вероятность того, что вам действительно нужно только одномерное std::vector<my_struct>
.
Ответ №2:
Обратите внимание, что ваши данные не соответствуют трехмерной модели массива: отдельные массивы имеют разную длину, что заставит компилятор «дополнить» их символами с нулевым значением. Это большое количество дополнений, и, что еще хуже, это нелегко предсказуемо.
Например, самая длинная строка в ваших данных содержит 13 символов, поэтому все строки будут дополнены до этого размера (включая, например "1"
, ). Кроме того, самый длинный список строк содержит 7 строк, поэтому все списки будут дополнены до этого размера. Таким образом, ваш массив {"Scale"}
будет дополнен массивом из 7 строк со строками, которые содержат 13 символов с нулевыми значениями.
Это действительно не то, что вы хотите. Вы можете игнорировать это (вам действительно все равно, выполняет ли компилятор ненужную работу), но это приведет к обратным результатам, когда вы попытаетесь сосчитать свои строки — вам придется каким-то образом игнорировать пустые строки.
Предполагая, что вы хотите это исправить, обратите внимание, что ваши данные представляют собой неровный массив строк, а не трехмерный массив.
std::vector<std::vector<std::vector<std::string>>> musical_things =
{
{
{"Scale"}, {"Minor Natural"}, {"1","2","b3","4","5","b6","b7"}
},
{
{"Scale"}, {"Major"}, {"1","2","3","4","5","6","7"}
},
};
Чтобы создать код, который ее печатает, я решил использовать подход снизу вверх, который легко объяснить.
Прежде всего, я создал функцию, которая печатает строку в нужном вам формате:
void print(std::ostreamamp; stream, const std::stringamp; string)
{
stream << '"' << string << '"';
}
Затем я создал функцию, которая печатает массив строк:
void print(std::ostreamamp; stream, const std::vector<std::string>amp; array)
{
bool first_time = true;
stream << '{';
for (const std::stringamp; s: array)
{
if (!first_time)
stream << ",";
print(stream, s);
first_time = false;
}
stream << '}';
}
Он выполняет итерацию по массиву и вызывает print
функцию для каждой строки. Он не может использоваться operator<<
, потому что вы хотите, чтобы каждая строка была заключена в кавычки.
Он использует first_time
флаг для правильной печати разделителей — на один разделитель меньше, чем количество строк.
Наконец, код, который печатает массив массивов:
void print(std::ostreamamp; stream, const std::vector<std::vector<std::string>>amp; array)
{
bool first_time = true;
for (const autoamp; v: array)
{
if (!first_time)
stream << ", ";
print(stream, v);
first_time = false;
}
}
Это в основном то же самое, но в нем используется другой разделитель, а тип переменной цикла — это const autoamp;
, потому что мне было лень вводить const std::vector<std::string>amp;
(я позволил компилятору вывести это).
Ой, я только что напечатал это! Так что я на самом деле не был ленивым 🙂
Комментарии:
1. Приятель, просто дай мне немного времени, чтобы внимательно прочитать твой ответ и попытаться заставить его работать в моей программе. Для меня это слишком много C сразу, хахаха.
2. Эй, приятель, извини за время, потраченное на проверку твоего ответа. Это ошибка, которую я получил от компилятора: musical_toolkit.cpp : В функции ‘void print(std::ostreamamp;, const std::vector<std::vector<std::__cxx11::basic_string<char> > >amp;)’: musical_toolkit.cpp:11:23: ошибка: недопустимая инициализация ссылки типа ‘const std::vector<std::vector<std::__cxx11::basic_string<char> > >amp;’ из выражения типа ‘const std::vector<std::__cxx11::basic_string<char> >’ print(поток, v);