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

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

  • автор:

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

Свои особенности имеют символьные массивы. При инициализации мы можем передать символьному массиву как набор символов, так и строку:

char hello1[] ; char hello2[] ; //

На первый взгляд оба массива имеют один и тот же набор символов, пусть в первом случае это просто набор отдельных символов, а во втором — строка. Но в первом случае — массив hello1 будет иметь пять элементов. А во втором случае массив hello2 будет иметь не 5 элементов, а 6, поскольку при инициализации строкой в символьный массив автоматически добавляется нулевой символ ‘\0’.

Способ определения символьного массива влияет на работу с ним. Так, при выводе на консоль оператор count отобразит всю строку до символа «\0». В конце обязательно должен быть символ ‘\0’, иначе на консоль будут выводится символы из последовательных ячеек памяти, которые содержат мусор, пока не встретится либо нулевой символ, либо не произойдет недопустимый доступ к памяти. Например, сравним вывод трех символьных массивов:

#include int main() < char hello1[]; char hello2[]; char hello3[]; std::cout

Пример консольного вывода:

hello╨J:╕╗☻ hello hello

В первом случае консольный вывод не детерминирован, поскольку символьный массив не заканчивается нулевым символом.

Двухмерные массивы символов

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

#include int main() < const int max_length; // максимальная длина строки (включая нулевой байт \0) char langs[][max_length] < "C++", "C#", "Python", "Java", "Kotlin", "Go", "Dart", "PHP" >; std::cout 

Здесь массив langs содержит 8 элементов (8 строк). Максимальное количество символов (условно стобцов) в каждой строке задается с помощью константы max_length . Но непосредственно сами строки массива необязательно должны достигать этой длины. Например, в строке «C++» только четыре символа (3 + автоматически добавляемый нулевой символ). Все остальные элементы получают по умолчанию нулевые значения.

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

Перебор двухмерных символьных массивов

Так как вложенные массивы представляют строки или массивы символов, то каждый такой массив мы можем ввести на консоль в виде строки:

#include int main() < char langs[][20] < "C++", "Python", "JavaScript">; for(auto lang : langs) < std::cout >

Здесь при переборе массива langs, каждый его отдельный элемент — массив символов будет помещаться в переменную lang. И далее мы можем вывести этот массив в виде строки на консоль.

Ввод символьных массивов/строк с консоли

Функция getline() потока cin считывает последовательность символов, включая пробелы. По умолчанию, ввод заканчивается, когда считывается символ перевода строки ‘\n’ (например, при нажатии клавиши Enter). Функция getline() имеет две версии. Первая версия принимает два параметра: первый параметра указывает на массив символов для хранения введенных данных, а второй параметр указывает на максимальное количество символов, которое надо сохранить в массив. Это количество включает символ завершения строки — нулевой байт ‘\0’, который автоматически добавляться в конец ввода:

#include int main() < const int max_length ; // максимальное количиство считываемых символов char text[max_length] <>; // массив для считывания строки std::cout << "Enter some text:" << std::endl; // считываем символы, включая пробелы std::cin.getline(text, max_length); std::cout

В данном случае считываем не более 100 символов в массив text. Пример ввода:

Enter some text: Hello METANIT.COM You entered: Hello METANIT.COM

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

#include int main() < const int max_length ; // максимальное количиство считываемых символов char text[max_length] <>; // массив для считывания строки std::cout << "Enter some text:" << std::endl; // считываем символы, включая пробелы std::cin.getline(text, max_length, '!'); std::cout

Здесь в качестве символа окончания ввода выступает восклицательный знак !, поэтому при считывании он не будет включаться в строку:

Enter some text: Hello World! You entered: Hello World

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

@Tkas, как правильно писать @insolor Вам ответил.

Ответ непосредственно на Ваш вопрос, почему при char y[4]; y[4] = 0; ничего не выводится

заключается в том, что когда Вы пишете 0 в y[4], то он заносится в x[0] (. ). Память под массивы в стеке так компилятор выделил.

Соответственно printf получает пустую строку (x начинается с нуля, он копируется в y[0], Вы его «печатаете»).

Вот, что произошло.

Отслеживать
ответ дан 7 окт 2012 в 22:02
45.9k 6 6 золотых знаков 47 47 серебряных знаков 115 115 бронзовых знаков
@avp, а почему он заносит в x[0]? Я же явно указал, что массив игрек. Не знал о таком)
8 окт 2012 в 11:22

@Tkas, по простому о таком явлении говорят — «трешь память». Дело в том, что память под локальные переменные размещается подряд (не будем сейчас рассматривать выравнивание числовых типов). Реально Вы запросили у компилятора явно 4 байта под массив y (индексы 0,1,2,3) и неявно 5 байт под массив х. Посмотреть адреса можно printf («x[0] = %p, y[0] = %p y[3] = %p y[4] = %p», &x[0],&y[0],&y[3],&y[4]); результат c:/Documents and Settings/avp/src/hashcode $ ./a x[0] = 0022FF40, y[0] = 0022FF3C y[3] = 0022FF3F y[4] = 0022FF40 c:/Documents and Settings/avp/src/hashcode $

8 окт 2012 в 11:35
@avp, да, действительно, спасибо)
8 окт 2012 в 11:40

  1. В массиве y недостаточно места для для строки «test» и ‘\0’. Чтобы было достаточно, нужно объявлять char y[5]; (длина строки + 1)
  2. Обнулять последний символ перед копированием не нужно, т.к. вы копируете 5 символов, в том числе и конечный ‘\0’

Отслеживать
ответ дан 7 окт 2012 в 19:10
48.6k 17 17 золотых знаков 56 56 серебряных знаков 100 100 бронзовых знаков
Я думал, что y[0]=’t’ , y[1]=’e’. y[4]=’\0′
7 окт 2012 в 19:26
А почему при char y[5]; printf(«%s», strncpy(y, x, 2)); выводится «te=» ? Непонятный знак равно.
7 окт 2012 в 19:31

> Я думал, что y[0]=’t’ , y[1]=’e’. y[4]=’\0′ Вы правильно думаете, но при объявлении нужно указывать требуемый размер (в нашем случае 5 символов), а не номер последнего символа. > А почему при char y[5]; printf(«%s», strncpy(y, x, 2)); выводится «te=» ? Непонятный знак равно. Потому что заранее неизвестно, что лежит в y. Вы копируете только два символа из исходной строки и не вставляете после них ‘\0’, поэтому printf выводит 2 скопированных символа, и, не встретив ‘\0’, продолжает выводить «мусорные» символы, находящиеся после этих двух символов.

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

Запись была обновлена

В С++ отсутствует специальный тип строк. Строки рассматриваются как массивы символов, оканчивающиеся нулевым символом (‘\0’). Строка доступна через указатель на первый символ в строке. Значением строки является адрес ее первого символа. Таким образом, в С++ строка является указателем — указателем на первый символ строки. В этом смысле строки подобны массивам, потому что массив тоже является указателем на свой первый элемент.
Строка может быть объявлена либо как массив символов, либо как переменная типа char*. Каждое из двух приведенных ниже эквивалентных объявлений:

char S[] = "строка"; char *Sp = "строка";

присваивает строковой переменной начальное значение «строка». Первое объявление создает массив из 7 элементов S содержащий символы ‘с’, ‘т’, ‘р’, ‘о’, ‘к’, ‘а’ и ‘\0’. Второе объявление создает переменную указатель Sp, который указывает на строку с текстом «строка», лежащую где-то в памяти. Но в любом случае число хранимых символов на 1 больше числа значащих символов за счет оконечного нулевого символа.

Доступ к отдельным символам строки осуществляется по индексам, начинающимся с нуля. Например, S[0] и Sp[0] первые символы объявленных выше строк, S[1] и Sp[1] вторые и т.д.

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

char buff[100];

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

  • strcat — конкатенация (склеивание) двух строк
  • strcmp — сравнение двух строк
  • strcpy — копирование одной строки в другую
  • strstr — поиск в строке заданной подстроки
  • strlen — определение длины строки
  • strupr — преобразование символов строки к верхнему регистру
  • sprintf — построение строки по заданной строке форматирования и списку аргументов и ряд других функций.

Выше было приведено объявление массива символов buff. Как занести в него какой-то текст? Это можно сделать с помощью функции strcpy:

strcpy(buff,"Текст, копируемый в buff");

Эта функция копирует строку, являющуюся ее вторым параметром, в строку, являющуюся первым параметром, и возвращает указатель на результат копирования.

Теперь решим задачу посложнее. Пусть, например, нужно прибавить в конец текста строки S1 текст, хранящийся в строке S2. Это можно сделать с помощью функции strcat:

char S1[20] = "текст 1", S2[10] = "текст 2"; strcat(S1,S2);

Обратите внимание на то, что размер первой строки выбран с запасом, чтобы в ней уместились оба текста. Если не задать в объявлении размер строки, то он определится но присваиваемому ей тексту и в ней не останется места для каких-то добавлений.

Функция strcat прибавляет к тексту строки, указанной ее первом параметром, текст строки, указанной вторым параметром, и возвращает указатель на первую строку. Последнее обстоятельство позволяет делать вложенные вызовы strcat, если надо склеить несколько текстов.

Давайте несколько усложним задачу. Пусть нужно оставить в неприкосновенности обе строки, а в третьей строке S надо получить склеенные тексты строк S1 и S2, разделенные символом пробела. Это можно сделать следующими операторами:

char *S1 = "текст 1", *S2 = "текст 2", S[20]; strcat(strcat(strcat(S,S1)," "),S2);

Самый внутренний вызов strcat склеивает пустую строку S и строку S1, Он возвращает указатель на S и, значит, следующий вызов strcat склеивает текст, появившийся в S, со строковой константой, содержащей символ пробела. Функция strcat опять возвращает указатель на S и последний внешний вызов strcat добавляет к уже сформированной строке текст строки S2.

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

strcpy(S,S1)

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

strstr(S1,S2)

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

Пусть необходимо найти в строке S1 первое вхождение текста строки S2 и, если поиск прошел удачно, то заменить найденный фрагмент на текст, содержащийся в строке S3. Иначе говоря, требуется произвести контекстную замену в S1 текста S2 на текст S3. Один из возможных вариантов решения этой задачи приведен ниже:

char S1[20], S2[20], S3 [20], S[60], *St; // операторы занесения текста в S1, S2, S3 St = strstr(S1,S2); if(St) < *St = 0; St += strlen(S2); Label1->Caption = strcat(strcat(strcpy(S,S1),S3),St); > else Label1->Caption = "Текст не найден";

Помимо строк S1, S2, S3 в этом коде объявлена строка S, являющаяся буфером, в который будет помещаться текст с произведенной в нем заменой. Объявлен также указатель на строку St. Он потребуется в качестве вспомогательной переменной.

Первый выполняемый оператор кода ищет с помощью функции strstr вхождение строки S2 в строку S1 и присваивает результат поиска переменной St. Если функция strstr вернула нуль (это эквивалентно false), то печатается сообщение «Текст не найден». Если же поиск прошел успешно, то осуществляются следующие операции. Сначала в символ, на который указывает St, засылается 0 — это эквивалентно нулевому символу. Таким образом выделяется первая часть строки S1, расположенная до заменяемого текста. Затем указатель St сдвигается на длину заменяемого текста, которая определяется функцией strlen. После этой операции St начинает указывать на первый символ в строке S1 после заменяемого текста. Следующий оператор формирует в буфере S текст с заменой и отображает его в метке Label1. Формирование текста осуществляется вложенными вызовами функций strcat и strcpy. Сначала срабатывает вложенный вызов strcpy. Он копирует в S строку, на которую указывает S1. Но поскольку вместо первого символа заменяемого текста мы занесли нулевой символ, то скопирована будет только начальная часть строки S1 до этого символа. Затем срабатывает вложенный вызов strcat и к тексту, сформированному в S добавляется строка S3. Последний внешний вызов streat добавляет к сформированному тексту часть строки S1, расположенную после замененного фрагмента. Именно на эту часть строки указывает St.

Чтобы это стало понятнее, разберем пример. Пусть строка S1 содержит текст «Маша ела кашу», строка S2 содержит текст «ела», а строка S3 «съела». Значит строка S1 представляет собой массив:

'М', 'а', 'ш', 'а', ' ', 'е', 'л', 'а', ' ', 'к', 'а', 'ш', 'у', '\0'

После выполнения функции strstr указатель St будет указывать на шестой символ букву ‘е’. После того как в этот символ заносится нуль, строка S1 имеет вид:

'М', 'а', 'ш', 'а', ' ', '\0 ' , 'л', 'а', ' ', 'к', 'а', 'ш', 'у', '\0'

После изменения Pt он начинает указывать на девятый символ пробел после слова «ела». После вызова strcpy в строку S копируется первая часть строки S1, завершающаяся нулевым символом:

'М', 'а', 'ш', 'а', ' ', '\0'

После вложенного вызова strcat к строке S добавляется текст строки S3:

'М', 'а', 'ш', 'а', ' ', 'с', 'ъ', 'е', 'л', 'а', '\0'

И после внешнего вызова strcat к S добавляется строка, на которую указывает St, т.е. часть строки S1, начинающаяся с пробела после «ела»:

'М', 'а' , 'ш' , 'а', ' ', 'с', 'ъ', 'е', 'л', 'а', ' ', 'к, 'а', 'ш', 'у', '\0'

В качестве последнего примера рассмотрим использование функции sprintf. Пусть в приложении имеется окно редактирования Edit1, в котором пользователь вводит фамилию сотрудника, и компонент CSpinEdit1 типа TCSpinEdit, в котором вводится год рождения. Так нужно сформировать строку вида «Сотрудник . . г.р.», в которой вместо точек должны подставляться введенные данные: фамилия и год. Это можно сделать следующим кодом:

#include char S[40]; sprintf(S, "Сотрудник %s, %i г.p.", Edit1->Text, CSpinEdit1->Value);

Первый аргумент функции sprintf — формируемая строка. Второй это строка форматирования. Она указывает текст формируемой строки и содержит спецификаторы, записываемые после символа «%», которые указывают формат включения в строку аргументов, список которых расположен в вызове sprintf после строки форматирования. В данном случае первый из этих параметров текст в окне Edit1, вводимый со спецификатором %s, что означает строку, а второй параметр значение года в компоненте CSpinEdit1, вводимое со спецификатором %i, что означает целое число.

C++ Builder не ограничивается изложенным выше типичным для С++ подходом, сводящим строки к массивам символов. В нем реализованы в виде классов еще некоторые очень полезные типы. Наиболее интересные из них AnsiString, имеющий множество методов и перегруженных операций, облегчающих работу со строками, и типы списков строк TStrings и TStringList.

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

char str[]=»ТЕКСТ»;

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

Если длина строки в квадратных скобках опущена, то она определяется автоматически, по количеству присваеваемых символов. В приведенном выше примере она равна шести.
Запишем программу (пример 4.1), в которой функция main формирует строку по указанному выше правилу и вызывает функцию length, которая в качестве аргумента получает начальный адрес этой строки и вычисляет ее длину(без учета завеершающего символа). Эта функция представляет собой самостоятельный интерес и будет использована нами а дальнейшем как библиотечная.

/*длина сторки*/
length(s);
char s[];
int l=0;
while(s[l]!=’\0′)
i++;
return(i);
>
#include
main()
static char str[]=»ОЙ У ПОЛИ КРИНИЧКА»;
printf(«%d»,length(str));
>

Программа приведенная ниже (пример 4.2), выполняет сцепление двух строк. Собственно, сцепление выполняет функция concat(s,t), которая присоединят строку t к концу строки s. Объединяемые строки str1 и str2 объявлены как внешние, причем размер str1 достаточно большой, чтобы сохранить новую строку. Используя спецификацию формата %s, функция printf выводит всю строку сразу, причем она «знает», что печать остановить при достижении завершающего символа «\0».

/*сцепление строк*/
concat(s,t)
char s[],t[];
int i,j;
i=j=0;
/*поиск конца строки*/
while(s[i]!=’\0′)i++;
while((s[i++]=t[j++])!=’\0′);
/*копия t*/
#include
char str1[45]=»ОЙ ТАМ У ПОЛИ КРИНИЧКА»;
char str2[]=»ТАМ ХОРОША ВОДИЧКА»;
main()
concat(str1,str2);
printf(«%s»,str);
>

На пример 4.3 приведена программа с функцией revers(s), переставляющей символы строки s в обратном порядке. В качестве библиотечной исползуется ранее рассматривавшаяся функция length. Функция revers меняет местами символы строки, симетричные относительно ее середины; если в строке нечетное число символов, то средний символ остается на месте.

/*вращение строки*/
#include stdio.h
#include «length.c»
revers(s)
char s[];
<
int l,i=0;
l=length(s);
while(i_=l/2)
<
c=s[i]; s[i]=s[l-i-1];
s[l-i-1]=c;
i++;
>
>
main()
<
static char str[]= «ОЙ У ПОЛИ КРИНИЧКА»;
revers(str);
printf(«%s\n»,str);
>

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

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