Основы массивов в C++

C++C++Beginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом практическом занятии вы изучите массивы в C++. Вы узнаете, как определить и инициализировать массивы, а также как использовать функции массивов.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL cpp(("C++")) -.-> cpp/IOandFileHandlingGroup(["I/O and File Handling"]) cpp(("C++")) -.-> cpp/BasicsGroup(["Basics"]) cpp(("C++")) -.-> cpp/AdvancedConceptsGroup(["Advanced Concepts"]) cpp(("C++")) -.-> cpp/ControlFlowGroup(["Control Flow"]) cpp/BasicsGroup -.-> cpp/variables("Variables") cpp/BasicsGroup -.-> cpp/data_types("Data Types") cpp/BasicsGroup -.-> cpp/arrays("Arrays") cpp/BasicsGroup -.-> cpp/strings("Strings") cpp/ControlFlowGroup -.-> cpp/for_loop("For Loop") cpp/ControlFlowGroup -.-> cpp/while_loop("While Loop") cpp/AdvancedConceptsGroup -.-> cpp/references("References") cpp/IOandFileHandlingGroup -.-> cpp/output("Output") cpp/IOandFileHandlingGroup -.-> cpp/user_input("User Input") subgraph Lab Skills cpp/variables -.-> lab-178535{{"Основы массивов в C++"}} cpp/data_types -.-> lab-178535{{"Основы массивов в C++"}} cpp/arrays -.-> lab-178535{{"Основы массивов в C++"}} cpp/strings -.-> lab-178535{{"Основы массивов в C++"}} cpp/for_loop -.-> lab-178535{{"Основы массивов в C++"}} cpp/while_loop -.-> lab-178535{{"Основы массивов в C++"}} cpp/references -.-> lab-178535{{"Основы массивов в C++"}} cpp/output -.-> lab-178535{{"Основы массивов в C++"}} cpp/user_input -.-> lab-178535{{"Основы массивов в C++"}} end

Предварительный просмотр содержания

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

Для создания массива вам нужно заранее знать длину (или размер) массива и выделить память соответственно. Как только массив создан, его длина фиксируется и не может быть изменена.

image desc

Объявление и использование массива

Предположим, что вы хотите найти средний балл класса из 30 учеников. Конечно, вы не хотите создавать 30 переменных: mark1, mark2,..., mark30. Вместо этого вы можете использовать одну переменную, называемую массивом, с 30 элементами.

Массив - это список элементов одного типа, идентифицируемый квадратными скобками [ ]. Чтобы использовать массив, вам нужно объявить массив с тремя вещами: именем, типом и размерностью (или размером, или длиной). Мы рекомендуем использовать множественное имя для массива, например, marks, rows, numbers. Например:

int marks[5];        // Объявить целочисленный массив marks с 5 элементами
double numbers[10];  // Объявить массив double из 10 элементов
const int SIZE = 9;
float temps[SIZE];   // Использовать const int в качестве длины массива

// Некоторые компиляторы поддерживают переменную в качестве длины массива, например:
int size;
cout << "Введите длину массива: ";
cin >> size;
float values[size];

Обратите внимание, что в C++ значения элементов не определены после объявления.

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

// Объявить и инициализировать целочисленный массив из 3 элементов
int numbers[3] = {11, 33, 44};
// Если длина опущена, компилятор подсчитывает элементы
int numbers[] = {11, 33, 44};
// Количество элементов при инициализации должно быть равно или меньше длины
int numbers[5] = {11, 33, 44};  // Оставшиеся элементы равны нулю. Обманчивый! Не делайте этого
int numbers[2] = {11, 33, 44};  // ОШИБКА: слишком много инициализаторов

// Используйте {0} или {} для инициализации всех элементов значением 0
int numbers[5] = {0};  // Первый элемент равен 0, остальные также равны нулю
int numbers[5] = {};   // Все элементы также равны нулю
/* Тест инициализации локального массива */
#include <iostream>
using namespace std;

int main() {
   int const SIZE = 5;

   int a1[SIZE];   // Неинициализированный
   for (int i = 0; i < SIZE; ++i) cout << a1[i] << " ";
   cout << endl;   //?????

   int a2[SIZE] = {21, 22, 23, 24, 25}; // Все элементы инициализированы
   for (int i = 0; i < SIZE; ++i) cout << a2[i] << " ";
   cout << endl;   // 21 22 23 24 25

   int a3[] = {31, 32, 33, 34, 35};   // Размер определяется из значений инициализации
   int a3Size = sizeof(a3)/sizeof(int);
   cout << "Размер равен " << a3Size << endl;   // 5
   for (int i = 0; i < a3Size; ++i) cout << a3[i] << " ";
   cout << endl;   // 31 32 33 34 35

   int a4[SIZE] = {41, 42};  // Стартовые элементы инициализированы, остальные равны 0
   for (int i = 0; i < SIZE; ++i) cout << a4[i] << " ";
   cout << endl;   // 41 42 0 0 0

   int a5[SIZE] = {0};  // Первый элемент равен 0, остальные также равны 0
   for (int i = 0; i < SIZE; ++i) cout << a5[i] << " ";
   cout << endl;   // 0 0 0 0 0

   int a6[SIZE] = {};   // Все элементы также равны 0
   for (int i = 0; i < SIZE; ++i) cout << a6[i] << " ";
   cout << endl;   // 0 0 0 0 0

   for (int i=0;i<5;i++){
       // присвоить значение для каждого элемента массива, вот так
       a6[i] = i;
       cout << a6[i] << " ";
   }
}

Результат:

6299128 0 485160213 32595 0 ## Некоторые неожиданные значения
21 22 23 24 25
Размер равен 5
31 32 33 34 35
41 42 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 2 3 4
image desc

Вы можете найти длину массива с помощью выражения sizeof(arrayName)/sizeof(arrayName[0]), где sizeof(arrayName) возвращает общее количество байт массива, а sizeof(arrayName[0]) возвращает количество байт первого элемента.

Массив и цикл

Массивы работают рука об руке с циклами. Вы можете обрабатывать все элементы массива с помощью цикла. C++11 представляет цикл for по диапазону (или for-each цикл), чтобы перебирать элементы массива, например:

/* Тестирование цикла for-each */
#include <iostream>
using namespace std;

int main() {
   int numbers[] = {11, 22, 33, 44, 55};

   // Для каждого элемента под названием number в массиве numbers - только для чтения
   for (int number : numbers) {
      cout << number << " ";
   }

   // Чтобы изменить элементы, нужно использовать ссылку (&)
   for (int &number : numbers) {
      number = 99;
   }

   for (int number : numbers) {
      cout << number << endl;
   }
   return 0;
}

Результат:

11 22 33 44 55
99 99 99 99 99
image desc

Многомерный массив

Например,

int[2][3] = { {11, 22, 33}, {44, 55, 66} };
image desc
/* Тестирование многомерного массива */
#include <iostream>
using namespace std;
void printArray(const int[][3], int);

int main() {
   int myArray[][3] = {{8, 2, 4}, {7, 5, 2}}; // 2x3 инициализированный
                 // Только первый индекс может быть опущен и подразумеваться
   printArray(myArray, 2);
   return 0;
}

// Вывод содержимого массива размером rows x 3 (количество столбцов фиксировано)
void printArray(const int array[][3], int rows) {
   for (int i = 0; i < rows; ++i) {
      for (int j = 0; j < 3; ++j) {
         cout << array[i][j] << " ";
      }
      cout << endl;
   }
}

Результат:

8 2 4
7 5 2
image desc

Массив символов

В C строка представляет собой массив char, завершающийся нулевым символом '\0' (ASCII-код шестнадцатеричного 0). C++ предоставляет новый класс string в заголовке <string>. Исходная строка в C известна как C-строка (или C-стильная строка или символьная строка). Вы можете выделить C-строку следующим образом:

char message[256];     // Объявить массив char
                       // Может хранить C-строку длиной до 255 символов, завершающуюся '\0'
char str1[] = "Hello"; // Объявить и инициализировать "литеральной строкой".
                       // Длина массива равна количеству символов + 1 (для '\0').
char str1char[] = {'H', 'e', 'l', 'l', 'o', '\0'};  // То же, что и выше
char str2[256] = "Hello";  // Длина массива равна 256, хранит меньшую строку.

Для новичков избегайте C-строк. Используйте C++ string (в заголовке <string>), о котором говорилось ранее.

Вы можете использовать cin и cout для работы с C-строками.

  • cin << читает строку, ограниченную пробелами;
  • cin.getline(*var*, *size*) читает строку в var до символа новой строки длиной до size-1, игнорируя символ новой строки (заменяя его '\0'). *size* обычно соответствует длине массива C-строки.
  • cin.get(*var*, *size*) читает строку до символа новой строки, но оставляет символ новой строки в буфере ввода.
  • cin.get(), без аргументов, читает следующий символ.
/* Тестирование C-строки */
#include <iostream>
using namespace std;

int main() {
   char msg[256]; // Хранит строку длиной до 255 символов (завершающуюся '\0')

   cout << "Введите сообщение (с пробелом)" << endl;
   cin.getline(msg, 256);  // Считывает до 255 символов в msg
   cout << msg << endl;

   // Доступ через нулевым заканчивающийся массив символов
   for (int i = 0; msg[i]!= '\0'; ++i) {
      cout << msg[i];
   }
   cout << endl;

   cout << "Введите слово (без пробела)" << endl;
   cin >> msg;
   cout << msg << endl;

   // Доступ через нулевым заканчивающийся массив символов
   for (int i = 0; msg[i]!= '\0'; ++i) {
      cout << msg[i];
   }
   cout << endl;
   return 0;
}

Результат:

Введите сообщение (с пробелом)
hello, how are you?
hello, how are you?
hello, how are you?
Введите слово (без пробела)
helloworld
helloworld
helloworld
image desc

Обзор

C/C++ не выполняет проверку границ индекса массива. Другими словами, если индекс выходит за пределы массива, он не выдаёт предупреждение/ошибку. Тем не менее, вам нужно оценить длину и выделить верхнюю границу. Это, вероятно, главный недостаток использования массива. C++ имеет шаблонный класс vector (а в C++11 добавлен шаблонный класс array), который поддерживает динамически изменяемый размер массива.