Как использовать многомерный массив char или string в цикле - PullRequest
1 голос
/ 30 ноября 2011

Я так новичок в C ++ и просто не могу понять, как использовать какие-либо многомерные массивы. Я хочу сделать что-то подобное:

input number of product: number; //the products' name can be 7 with NULL char. (max 6)
char arr[number][7];

Это работает. Но когда я хочу сделать это в цикле for (i):

cin>>arr[i][7];

и я не знаю, что, черт возьми, делает компилятор?

Я просто хочу это:

arr[0][7]=apple;
arr[1][7]=orange;

Так, пожалуйста, как я могу это сделать?

Ответы [ 6 ]

3 голосов
/ 30 ноября 2011
#include <string>
#include <vector>

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

Обратите внимание, что вы бы получили такой ответ за 10 миллисекунд 3 разными людьми, если вы предоставили короткий, работающий пример кода (перевод кода 1: 1 более эффективен, чем «продуманные» примеры, которые вы могли бы распознать)

Здесь выgo:

std::vector<std::string> strings

strings.push_back("apple");    
strings.push_back("banana");

// or
std::string s;

std::cin >> s; // a word
strings.push_back(s);

// or
std::getline(std::cin, s); // a whole line
strings.push_back(s);

// or:
// add #include <iterator>
// add #include <algorithm>

std::copy(std::istream_iterator<std::string>(std::cin),
     std::istream_iterator<std::string>(),
     std::back_inserter(strings));

Возможна также прямая адресация:

std::vector<std::string> strings(10); // 10 empty strings

strings[7] = "seventh";

Редактировать в ответ на комментарии:

const char* eighth = "eighth";

if (strings[7] != eighth)
{  
      // not equal
}

// If you really **must** (read, no you don't) you can get a const char* for the string:

const char* sz = strings[7].c_str(); // warning: 
         // invalidated when `strings[7]` is modified/destructed
1 голос
/ 30 ноября 2011

Если у вас нет реальной причины (которую вы не должны скрывать от нас), создайте, как говорит Бьёрн, и используйте вектор строк. Вы даже можете отказаться от первоначального запроса на общий размер:

#include <string>
#include <vector>
#include <iostream>

std::vector<std::string> fruits;
std::string line;

while (std::getline(std::cin, line))
{
  fruits.push_back(line);
}

Давайте проверим:

std::cout << "You entered the following items:\n";
for (auto const & f : fruits) std::cout << "* " << f << "\n";
1 голос
/ 30 ноября 2011

Поскольку arr[i][7] - это char, и фактически один последний элемент, что означает, что вы можете получить ошибку доступа к памяти.

То, что вы хотите сделать, может быть cin>>arr[i];.

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

Самый простой способ - использовать std::vector<std::string>, как предлагали другие.

0 голосов
/ 30 ноября 2011

Использование std :: vector и std :: string обычно избавит вас от головной боли, как только вы их поймете.Поскольку вы новичок в C ++, было бы полезно понять, что происходит с двумерными массивами.

Когда вы говорите

char array[N][M];

, когда N и M являются константами,не переменные, вы говорите компилятору выделить N * M элементов типа char.Там будет блок памяти, выделенный для этого массива размером N * M * sizeof (char).(Вы можете объявить массив чего угодно, не только char. Так как sizeof (char) равен 1, память будет иметь длину N * M байт.) Если вы посмотрите на необработанную память, первый байт в памяти будет где массив [0] [0] есть.Второй байт будет где массив [0] [1], и так далее, для М байтов.Тогда вы увидите массив [1] [0].Это называется основным порядком строки.

Как уже упоминалось @ jbat100, когда вы говорите массив [i] [j], вы ссылаетесь на один символ.Когда вы говорите массив [i], вы ссылаетесь на адрес строки i в массиве.Указатель фактически не хранится в памяти, но когда вы говорите массив [i], компилятор знает, что вы имеете в виду, что вам нужен адрес строки i в массиве:

char* row_i = array[i];

Теперь, если i> 0,затем row_i указывает где-то в середине этого блока памяти, выделенного для массива.Это сделало бы то же самое:

char* row_i = &array[i][0];

Если у вас есть строка «orange» и вы знаете, что ее длина меньше M, вы можете сохранить ее в заданной строке в массиве,как это:

strcpy(array[i], "orange"); // or
array[i][0] = 'o'; array[i][1] = 'a'; ... array[i][6] = 0;

Или вы могли бы сказать row_i вместо массива [i].Это копирует 7 байтов в массив в расположении row_i.Strcpy () также копирует дополнительный байт, который равен 0, и это соглашение для завершения символьной строки в C и C ++.Таким образом, 7 байтов - это шесть байтов: «o», «r», «a», «n», «g» и «e» плюс 0 байт.Теперь strcmp (row_i, "orange") == 0.

Помните, что если ваша строка длиннее, чем M, strcpy и простые char-назначения (вероятно) не приведут к ошибке компиляции, но вы закончитекопирование части вашей строки в следующий ряд.

Прочтите об указателях и массивах в хорошей книге по C / C ++.

0 голосов
/ 30 ноября 2011
strcpy(&arr[0], "apple");
strcpy(&arr[1], "orange");

но для C ++ лучше использовать std::vector<std::string> для массива строк

0 голосов
/ 30 ноября 2011

У вас есть двумерный массив char

char arr[number][7];

А затем пытается присвоить им строку (char * или const char *), которая не будет работать. Здесь вы можете назначить символ, например:

arr[0][1] = 'a';

Если бы вы могли, я бы порекомендовал использовать std::vector и std::string, чтобы было намного понятнее. В вашем случае вы могли бы сделать

cin>>arr[i];

Но я бы не советовал, поскольку вы можете хранить только до 6 символьных строк * (плюс нулевой терминатор). Вы также можете иметь массив char *

char* arr[number];

затем динамически распределяет память для хранения строк.

...