Перейти к содержимому

Как создать массив строк

  • автор:

Массивы строк

В программировании типично использование массивов строк. Например, процессор ввода в базу данных может проверять команды пользователя в строковом массиве. Для создания массива строк используется двумерный массив символов. Левый индекс определяет число строк, а правый индекс — максимальное число символов в каждой строке. Данный фрагмент кода объявляет массив из 30-ти строк, причем каждая может содержать до 79 символов включительно:

char str_array [30] [80];

Доступ к отдельным строкам очень прост — необходимо просто определить левый индекс. Следующий оператор вызывает функцию gets(), передавая ей в качестве параметра третью строку массива str_array:

Данная функция эквивалентна

но предыдущий вариант более типичен при написании профессиональных программ.

Чтобы лучше понять принцип работы символьных массивов, рассмотрим следующую программу, использующую массив как основу простейшего текстового редактора.

#include
#define MAX 100
#define LEN 255
char text[MAX][LEN];

/* простейший текстовый редактор */
int main(void)
register int t, i, j;
for (t=0; t printf («%d: «, t);
gets(text [t]);
if(!*text [t]) break; /* выход по пустой строке */
>

/* посимвольный вывод текста */
for (i=0; i for(j=0; text[i][j]; j++) printf(«%с», text[i][j]);
printf («%с», ‘\n’);
>
return 0;
>

Данная программа осуществляет ввод текста, пока не встретится пустая строка. Затем она отображает каждую строку. В целях иллюстрации она выводит текст посимвольно, с использованием первого индекса. Поскольку каждая строка массива завершается нулевым символом, подпрограмма, отображающая текст, может быть упрощена:

Как создать массив строк?

Как в C++ создается массив строк? В JS это делается вот так: var arr = [‘one’, ‘two’]; В C++ нет типа данных String как я понял. Как решить вопрос?

Отслеживать

219k 15 15 золотых знаков 119 119 серебряных знаков 230 230 бронзовых знаков

задан 27 янв 2019 в 13:16

uzi_no_uzi uzi_no_uzi

2,186 2 2 золотых знака 18 18 серебряных знаков 51 51 бронзовый знак

в с++ можно самому создавать типы данных или пользоваться бибилиотечными. ::std::array <::std::string, 2>arr;

27 янв 2019 в 13:20

В С++ существует масса разных способов «создать массив строк» и выбор конкретного способа зависит о того , зачем вам нужен этот массив и что вы с ним потом собираетесь делать. Невозможно дать осмысленного ответа на такой огульный вопрос, не обладая более конкретной информацией.

Строки в языке C

Строка — это последовательность ASCII или UNICODE символов.

Строки в C, как и в большинстве языков программирования высокого уровня рассматриваются как отдельный тип, входящий в систему базовых типов языка. Так как язык C по своему происхождению является языком системного программирования, то строковый тип данных в C как таковой отсутствует, а в качестве строк в С используются обычные массивы символов.

Исторически сложилось два представления формата строк:

  1. формат ANSI;
  2. cтроки с завершающим нулем (используется в C).

Формат ANSI устанавливает, что значением первой позиции в строке является ее длина, а затем следуют сами символы строки. Например, представление строки «Моя строка!» будет следующим:

11 ‘М’ ‘о’ ‘я’ ‘ ‘ ‘с’ ‘т’ ‘р’ ‘о’ ‘к’ ‘а’ ‘!’
В строках с завершающим нулем, значащие символы строки указываются с первой позиции, а признаком завершения строки является значение ноль. Представление рассмотренной ранее строки в этом формате имеет вид:

‘М’ ‘о’ ‘я’ ‘ ‘ ‘с’ ‘т’ ‘р’ ‘о’ ‘к’ ‘а’ ‘!’ 0

Объявление строк в C

Строки реализуются посредством массивов символов. Поэтому объявление ASCII строки имеет следующий синтаксис:

char имя[длина];
Объявление строки в С имеет тот же синтаксис, что и объявление одномерного символьного массива. Длина строки должна представлять собой целочисленное значение (в стандарте C89 – константа, в стандарте C99 может быть выражением). Длина строки указывается с учетом одного символа на хранение завершающего нуля, поэтому максимальное количество значащих символов в строке на единицу меньше ее длины. Например, строка может содержать максимально двадцать символов, если объявлена следующим образом:
char str[21]; Инициализация строки в С осуществляется при ее объявлении, используя следующий синтаксис:
char str[длина] = строковый литерал;

Строковый литерал – строка ASCII символов заключенных в двойные кавычки. Примеры объявления строк с инициализацией:

char str1[20] = «Введите значение: «, str2[20] = «»;

const char message[] = «Сообщение об ошибке!»;

Работа со строками в С

Так как строки на языке С являются массивами символов, то к любому символу строки можно обратиться по его индексу. Для этого используется синтаксис обращения к элементу массива, поэтому первый символ в строке имеет индекс ноль. Например, в следующем фрагменте программы в строке str осуществляется замена всех символов ‘a’ на символы ‘A’ и наоборот.

for(int i = 0; str[i] != 0; i++)
if (str[i] == ‘a’) str[i] = ‘A’;
else if (str[i] == ‘A’) str[i] = ‘a’;
>

Массивы строк в С

Объявление массивов строк в языке С также возможно. Для этого используются двумерные массивы символов, что имеет следующий синтаксис:
char имя[количество][длина];

Первым размером матрицы указывается количество строк в массиве, а вторым – максимальная (с учетом завершающего нуля) длина каждой строки. Например, объявление массива из пяти строк максимальной длиной 30 значащих символов будет иметь вид:

При объявлении массивов строк можно производить инициализацию:
char имя[количество][длина] = ;

Число строковых литералов должно быть меньше или равно количеству строк в массиве. Если число строковых литералов меньше размера массива, то все остальные элементы инициализируются пустыми строками. Длина каждого строкового литерала должна быть строго меньше значения длины строки (для записи завершающего нуля).

char days[12][10] = <
«Январь», «Февраль», «Март», ”Апрель», «Май»,
«Июнь», «Июль», «Август», «Сентябрь»,»Октябрь»,
«Ноябрь», «Декабрь»
>;

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

char days[][12] = <
«Понедельник», «Вторник», «Среда», «Четверг»,
«Пятница», «Суббота», «Воскресенье»
>;

Функции для работы со строками в С

Все библиотечные функции, предназначенные для работы со строками, можно разделить на три группы:

  1. ввод и вывод строк;
  2. преобразование строк;
  3. обработка строк.

Ввод и вывод строк в С

Для ввода и вывода строковой информации можно использовать функции форматированного ввода и вывода (printf и scanf). Для этого в строке формата при вводе или выводе строковой переменной необходимо указать спецификатор типа %s. Например, ввод и последующий вывод строковой переменной будет иметь вид:

char str[31] = «»;
printf(«Введите строку: «);
scanf(«%30s”,str);
printf(«Вы ввели: %s”,str);

Недостатком функции scanf при вводе строковых данных является то, что символами разделителями данной функции являются:

  1. перевод строки,
  2. табуляция;
  3. пробел.

Поэтому, используя данную функцию невозможно ввести строку, содержащую несколько слов, разделенных пробелами или табуляциями. Например, если в предыдущей программе пользователь введет строку: «Сообщение из нескольких слов», то на экране будет выведено только «Сообщение».
Для ввода и вывода строк в библиотеке stdio.h содержатся специализированные функции gets и puts.

Функция gets предназначена для ввода строк и имеет следующий заголовок:
char * gets(char *buffer);

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

char * fgets(char * buffer, int size, FILE * stream);

где buffer — строка для записи результата, size — максимальное количество байт, которое запишет функция fgets, stream — файловый объект для чтения данных, для чтения с клавиатуры нужно указать stdin. Эта функция читает символы со стандартного ввода, пока не считает n — 1 символ или символ конца строки, потом запишет считанные символы в строку и добавит нулевой символ. При этом функция fgets записывает в том символ конца строки в данную строку, что нужно учитывать.

Функция puts предназначена для вывода строк и имеет следующий заголовок:
int puts(const char *string);

Простейшая программа: ввод и вывод строки с использованием функций fgets и puts будет иметь вид:

char str[102] = «»;
printf(«Введите строку: «);
fgets(str, 102, stdin);
printf(«Вы ввели: «);
puts(str);

Для считывания одного символа можно использовать функцию fgetc(FILE * stream) . Она считывает один символ и возвращает значение этого символа, преобразованное к типу int, если же считывание не удалось, то возвращается специальная константа EOF, равная -1. Функция возвращает значение -1 для того, чтобы можно было обрабатывать ситуацию конца файла, посимвольное чтение до конца файла можно реализовать следующим образом:

int c;
while ((c = fgetc(stdin)) != EOF) // Обработка символа
>

Для вывода одного символа можно использовать функцию int fputc(int c, FILE *stream); .

Помимо функций ввода и вывода в потоки в библиотеке stdio.h присутствуют функции форматированного ввода и вывода в строки. Функция форматированного ввода из строки имеет следующий заголовок:

int sscanf(const char * restrict buffer, const char * restrict string, [address] . );

Функции форматированного вывода в строку имеют следующие заголовки:

int sprintf(char * restrict buffer,
const char * restrict format, [argument] . );
int snprintf(char * restrict buffer, size_t maxsize,
const char * restrict format, [argument] . );

Преобразование строк

В С для преобразования строк, содержащих числа, в численные значения в библиотеке stdlib.h
предусмотрен следующий набор функций:
double atof(const char *string); // преобразование строки в число типа double
int atoi(const char *string); // преобразование строки в число типа int
long int atol(const char *string); // преобразование строки в число типа long int
long long int atoll(const char *string); // преобразование строки в число типа long long int

Корректное представление вещественного числа в текстовой строке должно удовлетворять формату:

После символов E, e указывается порядок числа. Корректное представление целого числа в текстовой строке должно удовлетворять формату:

Помимо приведенных выше функций в библиотеке stdlib.h доступны также следующие функции преобразования строк в вещественные числа:

float strtof(const char * restrict string, char ** restrict endptr);
double strtod(const char * restrict string, char ** restrict endptr);
long double strtold(const char * restrict string,char ** restrict endptr);

Аналогичные функции присутствуют и для преобразования строк в целочисленные значения:

long int strtol(const char * restrict string, char ** restrict endptr, int base);
unsigned long strtoul(const char * restrict string,
char ** restrict endptr, int base);
long long int strtoll(const char * restrict string,
char ** restrict endptr, int base);
unsigned long long strtoull(const char * restrict string,char ** restrict endptr, int base);

Функции обратного преобразования (численные значения в строки) в библиотеке stdlib.h присутствуют, но они не регламентированы стандартом, и рассматриваться не будут. Для преобразования численных значений в строковые наиболее удобно использовать функции sprintf и snprintf.

Обработка строк

В библиотеке string.h содержаться функции для различных действий над строками.
Функция вычисления длины строки:
size_t strlen(const char *string);

char str[] = «1234»;
int n = strlen(str); //n == 4

Функции копирования строк:

char * strcpy(char * restrict dst, const char * restrict src);
char * strncpy(char * restrict dst, const char * restrict src, size_t num);

Функции сравнения строк:

int strcmp(const char *string1, const char *string2);
int strncmp(const char *string1, const char *string2,size_t num);

Функции осуществляют сравнение строк по алфавиту и возвращают:

положительное значение – если string1 больше string2;
отрицательное значение – если string1 меньше string2;
нулевое значение – если string1 совпадает с string2;

Функции объединения (конкатенации) строк:

char * strcat(char * restrict dst, const char * restrict src);
char * strncat(char * restrict dst, const char * restrict src, size_t num);

Функции поиска символа в строке:

char * strchr(const char *string, int c);
char * strrchr(const char *string, int c);

Функция поиска строки в строке:
char * strstr(const char *str, const char *substr);

char str[] = «Строка для поиска»;
char *str1 = strstr(str,»для»); //str1 == «для поиска»

Функция поиска первого символа в строке из заданного набора символов:
size_t strcspn(const char *str, const char *charset);

Функции поиска первого символа в строке не принадлежащему заданному набору символов:
size_t strspn(const char *str, const char *charset);

Функции поиска первого символа в строке из заданного набора символов:
char * strpbrk(const char *str, const char *charset);

Функция поиска следующего литерала в строке:
char * strtok(char * restrict string, const char * restrict charset);

Как создать массив строк

Нередко возникает необходимость работы не с одиночными данными, а с наборами данных. И для этого в языке Си применяются массивы. Массив представляет набор однотипных значений. Объявление массива выглядит следующим образом:

тип_переменной название_массива [длина_массива]

После типа переменной идет название массива, а затем в квадратных скобках его размер. Например, определим массив из 4 чисел:

int main(void)

Используя номера элементов массиве, которые называются индексами, мы можем обратиться к отдельным элементам. Например:

#include int main(void) < int numbers[4]; numbers[0] = 1; numbers[1] = 2; numbers[2] = 3; numbers[3] = 4; printf("numbers[0] = %d \n", numbers[0]); // 1 - первый элемент printf("numbers[2] = %d \n", numbers[2]); // 3 - третий элемент return 0; >

Индексы указываются в квадратных скобках после названия массива и начинаются с нуля, поэтому для обращения к первому элементу необходимо использовать выражение numbers[0] .

Также мы можем сразу объявить и инициализировать массив значениями. Для этого переменной массива присваивается набор значений через запятую в фигурных скобках:

int numbers[4] = < 1, 2, 3, 5 >; // инициализация массива printf("numbers[2] = %d", numbers[2]); // 3

То есть в данном случае у нас будет следующее соответствие между значениями элементов и их индексами:

Значение 1 2 3 5
Индекс 0 1 2 3

При инициализации массива можно явно не указывать его длину, в этом случае длина массива будет вычисляться исходя из количества его элементов:

int numbers[] = < 1, 2, 3, 5 >;

Используя циклические конструкции, можно перебрать массив:

#include int main(void) < int numbers[] = < 10, 12, 13, 54, 43 >; for(int i =0; i < 5; i++) < printf("numbers[%d] = %d \n", i, numbers[i]); >return 0; >

При этом необязательно инициализировать массив значениями для всех его элементов:

int numbers[5] = < 10, 12>; // 10, 12, 0, 0, 0

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

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

Массивы могут быть многомерными. Элементы таких массивов сами в свою очередь являются массивами, в которых также элементы могут быть массивами. В большинстве случаев многмерные массивы представляют двухмерные массивы, которые можно представить в виде таблицы. Например, определим двухмерный массив чисел:

int numbers[3][2] = < , , >;

Здесь массив numbers имеет три элемента (3 строки), но каждый из этих элементов сам представляет массив из двух элементов (2 столбцов). Такой массив еще можно представить в виде таблицы:

И чтобы обратиться к элементам вложенного массива, потребуется два индекса:

int numbers[3][2] = < , , >; printf("numbers[1][0] = %d \n", numbers[1][0]); // 4

другой пример, двухмерный массив с двумя строками и тремя столбцами:

int numbers[2][3] = < , >;

Такой массив графически можно представить следующим образом:

Для перебора двухмерного массива применются вложенные циклы:

#include int main(void) < int numbers[3][2] = < , , >; // проходим по 3 строкам таблицы for(int i =0; i < 3; i++) < // проходим по 2 столбцам каждой строки for(int j =0; j> return 0; >

Строки

Выше рассматривались массивы чисел, но с массивами остальных типов данных все будет аналогично. Но отдельно стоит остановиться на массивах символов. В различных языках программирования есть специальные типы данных для представления строк. В языке программирования Си для представления строк используются массивы символов, ведь по сути строка — это и есть набор символов. Например, определим строку:

#include int main(void) < char message[] = "Hello"; printf("message: %s \n", message); // message: Hello return 0; >

Строки определяются в двойных кавычках. И если нам в программе нужны строки, то как раз можно использовать массивы символов.

Но стоит отметить, что кроме самих символов, которые заключены двойные кавычки, каждая строка в качестве завершающего символа содержит символ \0или нулевой символ (нулевой байт). Он же самый первый символ из таблицы ASCII. В Си нулевой байт служит признаком окончания строки. Поэтому в строке «Hello» на самом деле будет не 5 символов, а 6.

К примеру, переберем все символы строки и выведем их десятичный код ASCII:

char message[] = «Hello»; for(int i=0; i

На консоли при запуске программы мы сможем увидеть в конце нулевой символ:

72 101 108 108 111 0

Если бы мы определяли массив message не как строку, а именно как массив символов, то последним элементом должен был бы идти нулевой символ:

char message[] = ;

Размер и количество элементов массива

Не всегда в программе может быть известен размер массива. В этом случае можно использовать оператор sizeof , который возвращает размер массива в байтах.

#include int main(void) < int numbers[] = < 5, 6, 7>; int size = sizeof(numbers); printf("numbers size: %d \n", size); // numbers size: 12 return 0; >

В этом примере оператор sizeof() для массива < 5, 6, 7>возвращает 12 байт (так как массив содержит 3 значения типа int, которое обычно занимает 4 байта).

Используя размер типа, мы можем получить количество элементов в массиве:

#include int main(void) < int numbers[] = < 5, 6, 7>; int size = sizeof(numbers); int count = sizeof(numbers) / sizeof(int); printf("numbers size: %d \n", size); // numbers size: 12 printf("numbers count: %d \n", count); // numbers count: 3 return 0; >

Также можно получить количество элементов в массиве, разделив его размер на размер первого элемента:

#include int main(void) < int numbers[] = < 5, 6, 7>; int size = sizeof(numbers); int count = sizeof(numbers) / sizeof(numbers[0]); printf("numbers size: %d \n", size); // numbers size: 12 printf("numbers count: %d \n", count); // numbers count: 3 return 0; >

Динамическая установка размера массива

Размер массива можно установить динамически с помощью переменной/константы:

#include int main(void) < int maxSize = 3; int array[maxSize]; array[0] = 1; array[1] = 2; array[2] = 3; for (int i = 0; i < maxSize; i++) < printf("%d", array[i]); >return 0; >

Стоит отметить, что при динамической установке нельзя при определении инициализировать массив:

int maxSize = 3; int array[maxSize] = ; // ! Ошибка, так нельзя

Задачи с массивы

Рассмотрим работу с массивами на примере умножения матриц:

#include int main(void) < const int r1 = 3, c1r2=2, c2=1; int matrix1[3][2] = ,,>; int matrix2[2][1] = ,>; int matmult[r1][c2]; // инициализируем результирующую матрицу for(int i=0;i > for(int i=0;i > > printf("Result \n"); for(int i=0;i printf("\n"); > >

Здесь у нас определены две матрицы. Матрица matrix1[3][2] имеет три строки и два столбца:

Вторая матрица фактически состоит из одно столбца:

Для хранения размера столбцов и строк определены переменные

const int r1 = 3, // число строк в 1-й матрице c1r2=2, // число столбцов в 1-й и число строк во 2-й матрице c2=1; // число столбцов во 2-й матрице

Также определяем результирующую матрицу — результат произведения — matmul:

int matmult[r1][c2];

И инициализируем ее нулями.

При произведении матриц мы получаем матрицу, где количество строк равно количеству строк первой матрицы, а количество столбцов — количеству столбцов второй матрицы. А элемент результирующей матрицы на i-й строке j-м столбце равен сумме произведений элементов на i-й строке первой матрицы на соответствующие элементы j-го столбца второй матрицы.

c2,1 = a2,1 * b1,1 + a2,2 * b2,1

Соответственно при вычислении произведения в цикле по i проходим по всем строкам первой матрицы:

for(int i=0;i

Далее в цикле по j проходим по всем столбцам второй матрицы:

for(int j=0;j

В цикле по k умножаем значения из k-столбца первой матрицы на значения k-строки второй матрицы и прибавляем к результату:

for(int k=0;k

В результате мы получим матрицу из трех строк и одного столбца:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *