Язык си массив char
Строки в языке C
Строки в C, как и в большинстве языков программирования высокого уровня рассматриваются как отдельный тип, входящий в систему базовых типов языка. Так как язык 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’ и наоборот.
Массивы строк в С
Объявление массивов строк в языке С также возможно. Для этого используются двумерные массивы символов, что имеет следующий синтаксис:
char имя[количество][длина];
Первым размером матрицы указывается количество строк в массиве, а вторым – максимальная (с учетом завершающего нуля) длина каждой строки. Например, объявление массива из пяти строк максимальной длиной 30 значащих символов будет иметь вид:
Число строковых литералов должно быть меньше или равно количеству строк в массиве. Если число строковых литералов меньше размера массива, то все остальные элементы инициализируются пустыми строками. Длина каждого строкового литерала должна быть строго меньше значения длины строки (для записи завершающего нуля).
При объявлении массивов строк с инициализацией допускается не указывать количество строк в квадратных скобках. В таком случае, количество строк в массиве будет определено автоматически по числу инициализирующих строковых литералов.
Например, массив из семи строк:
Функции для работы со строками в С
Все библиотечные функции, предназначенные для работы со строками, можно разделить на три группы:
Ввод и вывод строк в С
Для ввода и вывода строковой информации можно использовать функции форматированного ввода и вывода (printf и scanf). Для этого в строке формата при вводе или выводе строковой переменной необходимо указать спецификатор типа %s. Например, ввод и последующий вывод строковой переменной будет иметь вид:
char str[31] = «»;
printf(«Введите строку: «);
scanf(«%30s”,str);
printf(«Вы ввели: %s”,str);
Недостатком функции scanf при вводе строковых данных является то, что символами разделителями данной функции являются:
Поэтому, используя данную функцию невозможно ввести строку, содержащую несколько слов, разделенных пробелами или табуляциями. Например, если в предыдущей программе пользователь введет строку: «Сообщение из нескольких слов», то на экране будет выведено только «Сообщение».
Для ввода и вывода строк в библиотеке stdio.h содержатся специализированные функции gets и puts.
Функция gets предназначена для ввода строк и имеет следующий заголовок:
char * gets(char *buffer);
Между тем использовать функцию gets категорически не рекомендуется, ввиду того, что она не контролирует выход за границу строки, что может произвести к ошибкам. Вместо нее используется функция fgets с тремя параметрами:
char * fgets(char * buffer, int size, FILE * stream);
Функция puts предназначена для вывода строк и имеет следующий заголовок:
int puts(const char *string);
Простейшая программа: ввод и вывод строки с использованием функций fgets и puts будет иметь вид:
Помимо функций ввода и вывода в потоки в библиотеке stdio.h присутствуют функции форматированного ввода и вывода в строки. Функция форматированного ввода из строки имеет следующий заголовок:
Функции форматированного вывода в строку имеют следующие заголовки:
Преобразование строк
В С для преобразования строк, содержащих числа, в численные значения в библиотеке 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 доступны также следующие функции преобразования строк в вещественные числа:
Аналогичные функции присутствуют и для преобразования строк в целочисленные значения:
Функции обратного преобразования (численные значения в строки) в библиотеке stdlib.h присутствуют, но они не регламентированы стандартом, и рассматриваться не будут. Для преобразования численных значений в строковые наиболее удобно использовать функции sprintf и snprintf.
Обработка строк
В библиотеке string.h содержаться функции для различных действий над строками.
Функция вычисления длины строки:
size_t strlen(const char *string);
Функции копирования строк:
Функции сравнения строк:
Функции осуществляют сравнение строк по алфавиту и возвращают:
положительное значение – если string1 больше string2;
отрицательное значение – если string1 меньше string2;
нулевое значение – если string1 совпадает с string2;
Функции объединения (конкатенации) строк:
Функции поиска символа в строке:
Функция поиска строки в строке:
char * strstr(const char *str, const char *substr);
Функция поиска первого символа в строке из заданного набора символов:
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);
Функции обработки строк в Cи
В программе строки могут определяться следующим образом:
Кроме того, должно быть предусмотрено выделение памяти для хранения строки.
Под хранение строки выделяются последовательно идущие ячейки оперативной памяти. Таким образом, строка представляет собой массив символов. Для хранения кода каждого символа строки отводится 1 байт.
При определении массива символов необходимо сообщить компилятору требуемый размер памяти.
Компилятор также может самостоятельно определить размер массива символов, если инициализация массива задана при объявлении строковой константой:
В этом случае имена m2 и m3 являются указателями на первые элементы массивов:
При объявлении массива символов и инициализации его строковой константой можно явно указать размер массива, но указанный размер массива должен быть больше, чем размер инициализирующей строковой константы:
В этом случае объявление массива переменной m4 может быть присвоен адрес массива:
Для указателя можно использовать операцию увеличения (перемещения на следующий символ):
Массивы символьных строк
В этом случае poet является массивом, состоящим из четырех указателей на символьные строки. Каждая строка символов представляет собой символьный массив, поэтому имеется четыре указателя на массивы. Указатель poet[0] ссылается на первую строку:
*poet[0] эквивалентно ‘П’,
*poet[l] эквивалентно ‘-‘.
Инициализация выполняется по правилам, определенным для массивов.
Тексты в кавычках эквивалентны инициализации каждой строки в массиве. Запятая разделяет соседние
последовательности.
Кроме того, можно явно задавать размер строк символов, используя описание, подобное такому:
Разница заключается в том, что такая форма задает «прямоугольный» массив, в котором все строки имеют одинаковую длину.
Свободный массив
Операции со строками
Большинство операций языка Си, имеющих дело со строками, работает с указателями. Для размещения в оперативной памяти строки символов необходимо:
Для выделения памяти под хранение строки могут использоваться функции динамического выделения памяти. При этом необходимо учитывать требуемый размер строки:
Функции ввода строк
Для ввода строки, включая пробелы, используется функция
В качестве аргумента функции передается указатель на строку, в которую осуществляется ввод. Функция просит пользователя ввести строку, которую она помещает в массив, пока пользователь не нажмет Enter.
Функции вывода строк
Для вывода строк можно воспользоваться рассмотренной ранее функцией
или в сокращенном формате
Для вывода строк также может использоваться функция
которая печатает строку s и переводит курсор на новую строку (в отличие от printf() ). Функция puts() также может использоваться для вывода строковых констант, заключенных в кавычки.
Функция ввода символов
Для ввода символов может использоваться функция
которая возвращает значение символа, введенного с клавиатуры. Указанная функция использовалась в рассмотренных ранее примерах для задержки окна консоли после выполнения программы до нажатия клавиши.
Функция вывода символов
Для вывода символов может использоваться функция
которая возвращает значение выводимого символа и выводит на экран символ, переданный в качестве аргумента.
Пример Посчитать количество введенных символов во введенной строке.
Результат выполнения
Основные функции стандартной библиотеки string.h
Основные функции стандартной библиотеки string.h приведены в таблице.
Пример использования функций
Результат выполнения
Комментариев к записи: 111
#include
#include «string.h»
#include «stdio.h»
using namespace std;
int main()
<
char from, to;
char text[100],*wbeg, * wend, delim[] = » ;. » ;
cout «Input text and put ‘.’ at the end: » ; cin.getline(text, 100, ‘.’);
do < cout "Line is empty! Retry: " ; cin.getline(text, 100, '.');>while (strlen(text) == 0);
int n_delim = strspn(text, delim); // возвращает к-сть разделителей
wbeg = text + n_delim; // указатель на начало слова
wend = text + strlen(text); // указатель на конец слова
n_delim = strcspn(wbeg, delim); //длина первого слова
int count = 1; cout «Input number of thе word: » ; int number; cin >> number;
while ((wbeg + n_delim if (count == number)
<
do
<
cout «Input symbol, that should be changed: » ; char ch1; cin >> ch1; //запрос буквы
char *pos_s = strchr(wbeg, ch1);
if (pos_s == 0) cout «No symbol!» ;
else if (wbeg + n_delim «Input symbol to change one: » ; char ch2; cin >> ch2;
ch2 = &pos_s;
> while (count else cout «No words with given number!» ; return 0;
>
return 0;
>
BestProg
Разработка класса, который реализует массив строк типа char*
Содержание
Поиск на других ресурсах:
Условие задачи
Решение
1. Общее построение класса. Добавление внутренних переменных
Прежде всего объявляется класс с именем ArrayPChar и в нем объявляются следующие внутренние переменные:
В будущем к этому классу будут добавлены разные методы в соответствии с условием задачи.
2. Разработка дополнительных методов класса
В раздел private класса нужно ввести ряд методов общего назначения. Эти методы (функции) будут вызываться из других методов. Методы общего назначения реализуют типичные операции со строками и массивом.
Метод CheckIndex() выполняет проверку, лежит ли индекс строки в массиве в допустимых пределах. Программный код метода следующий:
Этот метод нужно скопировать в раздел private класса.
Функция получает 2 параметра:
Программный код функции следующий:
Текст функции следующий:
Функцию CopyArrayStr() можно поместить в раздел private класса.
Текст функции следующий:
3. Разработка основных методов оперирования строками в соответствии с условием задачи
В разделе public класса объявляются методы, которые необходимы в соответствии с условием задачи.
3.1. Конструктор без параметров ArrayPChar()
Конструктор без параметров вызывается, если создается объект класса ArrayPChar в котором в массиве A нет ни одного элемента. Например,
Текст конструктора без параметров следующий
3.2. Конструктор с двумя параметрами ArrayPChar(char**, int)
3.3. Конструктор копирования ArrayPChar(const ArrayPChar&)
В данном классе необходимо реализовывать конструктор копирования, так как в классе используются указатели для которых динамично выделяется память. Более подробно о необходимости использования конструктора копирования описывается в теме:
Текст конструктора копирования следующий
Метод SetAi() реализует запись строки типа char* в массив в заданной позиции. Память, выделенная для предыдущей строки, перераспределяется под размер новой строки.
Общий алгоритм работы метода следующий:
Текст метода следующий
Общий алгоритм работы метода следующий:
Текст метода следующий
Операторный метод (функция) operator=() необходим, чтобы корректно выполнялось следующее присваивание
Текст операторного метода operator=() следующий
3.9. Деструктор
Строки как одномерные массивы данных типа char
В языке Си отдельного типа данных «строка символов» нет. Работа со строками реализована путем использования одномерных массивов типа char, т.е. строка символов – это одномерный массив символов, заканчивающийся нулевым байтом.
Нулевой байт – это байт, каждый бит которого равен нулю, при этом для нулевого байта определена символьная константа ´\0´ (признак окончания строки, или «нуль-символ»). Поэтому если строка должна содержать k символов, то в описании массива размер должен быть k+1. По положению нуль-символа определяется фактическая длина строки.
Например, char s[7]; – означает, что строка может содержать не более шести символов, а последний байт отводится под нуль-символ.
Отсутствие нуль-символа и выход указателя при просмотре строки за ее пределы – распространенная ошибка при работе со строками.
Строку можно инициализировать строковой константой (строковым литералом), которая представляет собой набор символов, заключенных в двойные кавычки. Например:
сhar S[ ] = “Работа со строками”;
для данной строки выделено и заполнено 19 байт – 18 на символы и 19-й на нуль-символ.
В конце строковой константы явно указывать символ ´\0´ не нужно. Компилятор добавит его автоматически.
Символ ´\0´ нужно использовать явно тогда, когда символьный массив при декларации инициализируется списком начальных значений, например, следующим образом:
или когда строка формируется посимвольно в коде программы. Пример такого формирования приведен в конце этого раздела.
При работе со строками можно пользоваться указателями, например:
Операция присваивания одной строки другой в языке Си не определена (поскольку строка является массивом) и может обрабатываться при помощи оператора цикла (с использованием стандартной библиотечной функций).
Процесс копирования строки s1 в строку s2 имеет вид
Функция int strcmp(S1, S2) сравнивает строки S1 и S2 и возвращает значение 0, если S1>S2; =0, если строки равны, т.е. содержат одно и то же число одинаковых символов.
Функции преобразования строковых объектов в числовые описаны в библиотеке stdlib.h. Рассмотрим некоторые из них.
Преобразование строки S в число:
– целое: int atoi(S);
– длинное целое: long atol(S);
– действительное: double atof(S);
при возникновении ошибки данные функции возвращают значение 0.
Функции преобразования числа V в строку S:
– целое: itoa(V, S, kod);
– длинное целое: ltoa(V, S, kod);
2 £ kod £ 36, для десятичных чисел со знаком kod = 10.
Пример участка кода программы, в котором из строки s удаляется символ, значение которого содержится в переменной с каждый раз, когда он встречается
В режиме консольных приложений в среде Visual C++ 6.0 вывод символов русского языка сопряжен с определенными неудобствами. Разрешение данной проблемы рассматривается в разд. 16.3.
Указатели на указатели
Указатели, как и переменные любого другого типа, могут объединяться в массивы.
Объявление массива указателей на целые числа имеет вид
Теперь каждому из элементов массива указателей a можно присвоить адрес целочисленной переменной y, например: a[1]=&y;
Чтобы теперь найти значение переменной y через данный элемент массива а, необходимо записать *a[1].
В языке Си можно описать переменную типа «указатель на указатель». Это ячейка оперативной памяти (переменная), в которой будет храниться адрес указателя на некоторую переменную. Признак такого типа данных – повторение символа «*» перед идентификатором переменной. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:
Если присвоить переменной а новое значение, например 10, то одинаковые результаты будут получены в следующих операциях:
a=10; *p1=10; **pp1=10; ***ppp1=10;
Для доступа к области ОП, отведенной под переменную а, можно использовать и индексы. Эквивалентны следующие выражения:
Фактически, используя указатели на указатели, мы имеем дело с многомерными массивами.
Многомерные массивы
Декларация многомерного массива имеет следующий формат:
< <список начальных значений>,
<список начальных значений>,
Списки начальных значений – атрибут необязательный.
Наиболее быстро изменяется последний индекс элементов массива, поскольку многомерные массивы в языке Си размещаются в памяти компьютера построчно друг за другом (см. следующую тему «Адресная функция»).
Рассмотрим особенности работы с многомерными массивами на конкретном примере двухмерного массива.
Например, пусть приведена следующая декларация двухмерного массива:
Идентификатор двухмерного массива – это указатель на массив указателей (переменная типа указатель на указатель: int **m;).
Поэтому двухмерный массив m[3][4]; компилятор рассматривает как массив трех указателей, каждый из которых указывает на начало массива со значениями размером по четыре элемента каждый. В ОП данный массив будет расположен следующим образом:
Указа-тели | m [0] | ® | m[0][0] | m[0][1] | m[0][2] | m[0][3] |
m [1] | m[1][0] | m[1][1] | m[1][2] | m[1][3] | ||
m [2] | m[2][0] | m[2][1] | m[2][2] | m[2][3] |
Рис. 10.1. Схема размещения элементов массива m размером 3×4
Причем в данном случае указатель m[1] будет иметь адрес m[0]+4*sizeof(int), т.е. каждый первый элемент следующей строки располагается за последним элементом предыдущей строки.
Приведем пример программы конструирования массива массивов:
int x0[4] = < 1, 2, 3,4>; // Декларация и инициализация
int x1[4] = <11,12,13,14>; // одномерных массивов
int *m[3] =
Как стать программистом
Обучение основам программирования на C для чайников.
Страницы
Последние новости
YoungCoder теперь и на Stepikе. Записывайтесь: https://vk.cc/75rISy
Чтобы записаться на курс, необходимо зарегистрироваться на Степике: https://vk.cc/75rIC4
Это моя личная ссылка-приглашение на Stepik для вас. Регистрируясь по этой ссылке, записываясь на курсы и решая задачи, Вы помогаете автору данного сайта принять участие в конкурсе платформы Stepik! Подробности конкурса здесь: https://vk.cc/75rKuS
воскресенье, 4 августа 2013 г.
Занятие 14. Строки и символьные массивы в языке Си.
Прочитайте улучшенную версию этого урока «Ввод и вывод символьных строк».
Объявление и инициализация строк.
Рис. 4. Вывод на экран символьного массива без нулевого элемента в конце |
Ввод и вывод строк.
Рис.9. Использование стандартных функций вывода строки puts(), fputs(). Особенности вывода. |
Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них.
123 комментария :
Самый непонятный урок для меня 🙁
Особенно с длинной строки.
«Количество символов, которые может считать функция с учетом символа конца строки. В нашем случае это 10, т.е. рабочих из них девять, и один зарезервирован для конца строки.»
Почему 9 да еще и минус один под конец строки и того 8? А на выводе все равно получается, что считали и вывели 9 символов. (Листинг 14.8)
Последний символ 100% записывается в конец строки и считается n-ным (последним) элементом массива? Как этот символ считать? т.е. как написать for (i = 0; i == конец строки; i++); (ага пока читал извилина шевельнулась. Не знаю только в правильную ли сторону 🙂 Получается так сделать нельзя т.к. мы сначала i приравниваем к целому числу, а потом хотим проверить не равено ли он символу. Тогда все равно не понятно как сделать такой цикл, что бы он выполнялся до конца строки).
Я наверное коряво написал. Смотрите 10 можете считать. Из них рабочих 9. А десятый, который не рабочий как раз и зарезервирован под конец строки.
Длина массива и длинна строки это разные вещи ведь. Длинна массива может быть и 100 элементов, а вот длина строки, которая хранится в этом массиве может быть и меньше. Например, Литстинг 14.3
Длинна массива str 17 элементов, а длина строки, которую мы туда поместили всего двенадцать. Из них, как мы уже разобрались 11 рабочие и последний, двенадцатый символ конца строки. )
Теперь, с учетом этих пояснений попробуйте ответить на свои последние вопросы или переформулировать их. Если не получится, напишите я или отвечу или дам еще подсказку. )