Gets ввод строки


Содержание

Функции обработки строк в Cи

В программе строки могут определяться следующим образом:

  • как строковые константы;
  • как массивы символов;
  • через указатель на символьный тип;
  • как массивы строк.

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

Любая последовательность символов, заключенная в двойные кавычки «» , рассматривается как строковая константа .

Для корректного вывода любая строка должна заканчиваться нуль-символом ‘\0’ , целочисленное значение которого равно 0. При объявлении строковой константы нуль-символ добавляется к ней автоматически. Так, последовательность символов, представляющая собой строковую константу, будет размещена в оперативной памяти компьютера, включая нулевой байт.

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

Для помещения в строковую константу некоторых служебных символов используются символьные комбинации. Так, если необходимо включить в строку символ двойной кавычки, ему должен предшествовать символ «обратный слеш»: ‘\»‘ .

Строковые константы размещаются в статической памяти. Начальный адрес последовательности символов в двойных кавычках трактуется как адрес строки. Строковые константы часто используются для осуществления диалога с пользователем в таких функциях, как printf() .

При определении массива символов необходимо сообщить компилятору требуемый размер памяти.

Компилятор также может самостоятельно определить размер массива символов, если инициализация массива задана при объявлении строковой константой:

В этом случае имена m2 и m3 являются указателями на первые элементы массивов:

  • m2 эквивалентно &m2[0]
  • m2[0] эквивалентно ‘Г’
  • m2[1] эквивалентно ‘o’
  • m3 эквивалентно &m3[0]
  • m3[2] эквивалентно ‘x’

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

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

В этом случае объявление массива переменной m4 может быть присвоен адрес массива:

Здесь m3 является константой-указателем. Нельзя изменить m3 , так как это означало бы изменение положения (адреса) массива в памяти, в отличие от m4 .

Для указателя можно использовать операцию увеличения (перемещения на следующий символ):

Массивы символьных строк

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

В этом случае poet является массивом, состоящим из четырех указателей на символьные строки. Каждая строка символов представляет собой символьный массив, поэтому имеется четыре указателя на массивы. Указатель poet[0] ссылается на первую строку:
*poet[0] эквивалентно ‘П’,
*poet[l] эквивалентно ‘-‘.

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

Разница заключается в том, что такая форма задает «прямоугольный» массив, в котором все строки имеют одинаковую длину.

IT Памятка

Чтобы не забыть и впоследствии освежить память

Си — работа со строками

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

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

Строка в языке Си представляет собой одномерный массив символов, последним элементом которой является символ конца строки – нуль (строка, завершающаяся нулем, то есть NULL terminated string).

Объявление переменной типа строка в языке Си возможно тремя способами, два из которых инициализируют строку во время объявления.

Первый способ:

Объявления массива символов (не забудьте добавить место для завершающего нуля):

Второй способ:

Присвоить строковой переменной начальное значение (при этом длину строки компилятор может вычислить сам):

Справа от знака присваивания записана строковая константа. В конце строки автоматически добавляется ноль (‘\0’). Константы символьных строк помещаются в класс статической памяти.

Третий способ:

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

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

Ввод строки со стандартного устройства ввода (клавиатуры)

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

Для ввода строки с помощью функции scanf, использует формат «%s», причем обратите внимание на то, что перед идентификатором строки не используется знак адреса «&», так как одномерный массив уже представлен указателем на его начало:

Функция gets() считывает символы до тех пор, пока не достигнет символа перехода на новую строку. Функция принимает все символы вплоть до символа перевода строки, но не включает его. К концу строки добавляется завершающий ноль (‘\0’). Функция gets() помещает считанную с клавиатуры последовательность символов в параметр типа строка и возвращает указатель на эту строку (если операция завершилась успешно), или NULL (в случае ошибки). В приведенном ниже примере при успешном завершении операции, на экран будет выведено две одинаковые строки:

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

Вывод строк на стандартное устройство вывода (экран монитора)

Для вывода строк на стандартное устройство вывода (экран монитора) можно использовать две функции printf и puts. В функции printf в качестве формата передается «%s». Удобство использования этой функции заключается в том, что помимо строки можно сразу выводит данные других типов. Особенность функции puts заключается в том, что после вывода строки автоматически происходит переход на следующую строку.

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

Для преобразования строк в языке Си предусмотрена библиотека string. Каждая из функций имеет свой формат записи (прототип).


Наиболее используемые функции рассмотрены в этой статье. — читать

Пример программ(листинг) работающей со строками

Gets ввод строки

Программа не дописана, но уже имеет некоторые проблемы. Конкретно, непонятно почему в функции Amnojestvo пропускается ввод строки через gets. Заметил, что если убрать выбор действий через функцию Menu, то все нормально. Прошу помочь разобраться в проблеме.

#include
#include
#include
#include

void Menu ( int & menu )
<
printf ( «\n Выберите номер действия: » );
scanf ( «%d» , & menu );
>
void Amnojestvo ( char Ainput [], int Adlina , int i )
<
printf ( » Задайте элементы множества А :\n» );
gets ( Ainput );
Adlina = strlen ( Ainput );

int menu , n = 100 , i , j = 100 , k = 100 ;
int Adlina ;

char Ainput [ n ], A [ j ][ k ], B [ n ], temp ;
printf ( » Возможные действия:\n» );
printf ( «1. Создать(изменить существующее) и заполнить множество А.\n» );
printf ( «2. Создать(изменить существующее) и заполнить множество B.» );
// printf(«3. Применить объединение к A и B «);

Menu ( menu );
while ( menu != 0 )
<
if ( menu == 1 )
<
Amnojestvo ( Ainput , Adlina , i );
Menu ( menu );
>

gets_s, _getws_s gets_s, _getws_s

Получает строку из потока stdin . Gets a line from the stdin stream. Это версии функций gets, _getws с усовершенствованной безопасностью, как описано в разделе Функции безопасности в CRT. These versions of gets, _getws have security enhancements, as described in Security Features in the CRT.

Синтаксис Syntax

Параметры Parameters

buffer buffer
Место хранения входной строки. Storage location for input string.

сизеинчарактерс sizeInCharacters
Размер буфера. The size of the buffer.

Возвращаемое значение Return Value

Возвращает buffer в случае успеха. Returns buffer if successful. Указатель NULL указывает на ошибку или конец файла. A NULL pointer indicates an error or end-of-file condition. Используйте ferror или feof для определения того, что именно произошло. Use ferror or feof to determine which one has occurred.

Примечания Remarks

Функция gets_s считывает строку из стандартного входного потока stdin и сохраняет ее в буфер. The gets_s function reads a line from the standard input stream stdin and stores it in buffer. Строка состоит из всех символов до первого символа новой строки («\n»). The line consists of all characters up to and including the first newline character (‘\n’). затем gets_s заменяет символ новой строки символом NULL («\ 0») перед возвратом строки. gets_s then replaces the newline character with a null character (‘\0’) before returning the line. В отличие от этого, функция fgets_s оставляет символ новой строки. In contrast, the fgets_s function retains the newline character.

Если первый считанный символ является символом конца файла, то в начале буфера сохраняется символ NULL и возвращается значение NULL . If the first character read is the end-of-file character, a null character is stored at the beginning of buffer and NULL is returned.

_getws_s — это версия gets_sдля расширенных символов; его аргумент и возвращаемое значение являются строками расширенных символов. _getws_s is a wide-character version of gets_s; its argument and return value are wide-character strings.

Если значение buffer равно null или сизеинчарактерс меньше или равно нулю или если буфер слишком мал для хранения входной строки и признака конца null, эти функции вызывают обработчик недопустимого параметра, как описано в разделе параметр. Проверка. If buffer is NULL or sizeInCharacters is less than or equal to zero, or if the buffer is too small to contain the input line and null terminator, these functions invoke an invalid parameter handler, as described in Parameter Validation. Если выполнение может быть продолжено, эти функции возвращают значение NULL и задают значение ERANGE. If execution is allowed to continue, these functions return NULL and set errno to ERANGE.

В C++ использование данных функций упрощено наличием шаблонных перегрузок; перегруженные методы могут автоматически определять длину буфера (что исключает необходимость указания аргумента с размером буфера), а также они могут автоматически заменять более старые, незащищенные функции их новыми безопасными аналогами. In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. Дополнительные сведения см. в разделе Secure Template Overloads. For more information, see Secure Template Overloads.

Сопоставления подпрограмм обработки обычного текста Generic-Text Routine Mappings

Подпрограмма TCHAR.H TCHAR.H routine _UNICODE и _MBCS не определены _UNICODE & _MBCS not defined _MBCS определено _MBCS defined _UNICODE определено _UNICODE defined
_getts_s _getts_s gets_s gets_s gets_s gets_s _getws_s _getws_s

Требования Requirements

Подпрограмма Routine Обязательный заголовок Required header
gets_s gets_s
_getws_s _getws_s или or

Консоль не поддерживается в приложениях универсальная платформа Windows (UWP). The console is not supported in Universal Windows Platform (UWP) apps. Стандартные дескрипторы потока, связанные с консолью, stdin, stdoutи stderr, должны быть перенаправляться до того, как функции времени выполнения C смогут использовать их в приложениях UWP. The standard stream handles that are associated with the console, stdin, stdout, and stderr, must be redirected before C run-time functions can use them in UWP apps. Дополнительные сведения о совместимости см. в разделе Совместимость. For additional compatibility information, see Compatibility.

Особенности работы со строками

Неформатированные ввод из стандартного потока и вывод в стандартный поток

С помощью функции printf() можно легко вывести на экран строку, содержащую пробелы:

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

На помощь может прийти функция getchar() , осуществляющая посимвольный ввод данных:

В заголовке цикла getchar() возвращает символ, далее записываемый в очередную ячейку массива. После этого элемент массива сравнивается с символом ‘\n’. Если они равны, то цикл завершается. После цикла символ ‘\n’ в массиве «затирается» символом ‘\0’. В условии цикла должна быть также предусмотрена проверка на выход за пределы массива; чтобы не усложнять пример, опущена.

Однако в языке программирования C работать со строками можно проще. С помощью функций стандартной библиотеки gets() и puts() получают строку из стандартного потока и выводят в стандартный поток. Буква s в конце слов gets и puts является сокращением от слова string (строка).

В качестве параметров обе функции принимают указатель на массив символов (либо имя массива, либо указатель).

Функция gets() помещает полученные с ввода символы в указанный в качестве аргумента массив. При этом символ перехода на новую строку, который завершает ее работу, игнорируется.
Функция puts() выводит строку на экран и при этом сама добавляет символ перехода на новую строку. Простейший пример использования этих функций выглядит так:

Итак, если вы работаете со строками, а не другими типами данных, при этом нет необходимости выполнять их посимвольную обработку, то удобнее пользоваться функциями puts() и gets() . (Однако функция gets() считается опасной и была выпилена из версии языка C11.)

Массив символов и указатель на строку

Как мы знаем, строка представляет собой массив символов, последний элемент которого является нулевым символом по таблице ASCII, обозначаемым ‘\0’. При работе со строками также как с численными массивами можно использовать указатели. Мы можем объявить в программе массив символов, записать туда строку, потом присвоить указателю адрес на первый или любой другой элемент этого массива и работать со строкой через указатель:

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

Иногда в программах можно видеть такое объявление и определение переменной-указателя:
char *strP = «Hello World!»;

Строку, которая была присвоена не массиву, а указателю, также можно получить, обратившись по указателю:
puts(strP);

Но давайте посмотрим, что же все-таки происходит, и чем такая строка, присвоенная указателю, отличается от строки, присвоенной массиву.

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

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

В последней строке кода возникнет ошибка, т.к. совершается попытка изменить строку-константу.
Тем более нельзя делать так:

В данном случае память не была выделена под массив символов, который мы пытаемся считать функцией scanf() ; память была выделена только под указатель. Поэтому записать строку просто некуда. Другое дело, если память была выделена с помощью объявления массива, после чего указателю был присвоен адрес на этот массив:


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

Передача строки в функцию

Передача строки в функцию ничем не отличается от передачи туда массива чисел:

В этом примере функция change() принимает в качестве параметра указатель на символ. В теле функции значение указателя инкрементируется, указывая на следующий символ массива. В теле цикла инкрементируется значение, которое находится по адресу, который содержит указатель.

Задание
Объявите в программе три массива символов. Данные для двух из них получите с помощью вызовов функции gets() . Третий массив должен содержать результат конкатенации (соединения) двух введенных строк. Напишите функцию, которая выполняет конкатенацию строк.

Массив строк и массив указателей

Рассмотрим более сложный пример. Допустим, у нас есть набор строк. Требуется выполнить сортировку строк по возрастанию по признаку длины: сначала вывести самые короткие строки, затем более длинные.

Набор строк можно представить как двумерный массив, т.е. массив, состоящий из одномерных массивов, где каждый одномерный массив — это строка символов:
char str[][10] = <"Hello", "World", ". ", "&&&">;

Представьте себе, что значит выполнить сортировку строк. Это значит, надо поменять местами содержимое множества ячеек памяти. Это достаточно трудоемкая для компьютера работа, особенно если строк очень много. Однако можно поступить по-иному. Достаточно создать массив указателей, каждый элемент которого будет указывать на соответствующую ему строку первого массива. Далее выполнить сортировку указателей, что несомненно быстрее. Конечно, сам массив строк отсортирован не будет, однако благодаря указателям у нас будет хранится отсортированный «срез» массива:

Примечания к программе:

  • На самом деле параметром функции sortlen() является указатель на указатель. Хотя для понимания проще сказать, что параметром является массив указателей на символы. Мы передаем в функцию указатель на первый элемент массива strP, который сам является указателем. Если бы в функции мы инкрементировали переменную s, то переходили бы к следующему элементу-указателю массива strP.
  • Сортировка выполняется методом пузырька: если длина строки, на которую ссылается следующий указатель массива strP, меньше длины строки под текущим указателем, то значения указателей меняются.
  • Выражение strP[i] = &strings[i][0] означает, что элементу массива указателей присваивается ссылка на первый символ каждой строки.

Задание
Напишите программу, которая сортирует строки по алфавиту. Для упрощения задачи пусть сортировка выполняется только по первым буквам строк (если первые буквы слов одинаковы, то вторые и последующие символы проверять не надо).

Зона кода

В этой статье мы рассмотрим проблему, которую уже затрагивали ранее. Речь идёт о чтении строки из консоли средствами языка C.

Проблема достаточно хорошо известна. Заключается она в том, что в стандартах C89 и C99 не предусмотрены стандартные библиотечные функции, позволяющие выполнять чтение строки безопасным образом.

С помощью стандартных функций scanf() и gets() можно считать строку с консоли и записать её по нужному адресу, однако обе эти функции не контролируют размер строки. Это означает, что в результате использования любой из этих функций будет предпринята попытка записи в память именно той строки, которую ввёл пользователь, даже если её размер превышает размер памяти, выделенной программой для её хранения. В случае такого превышения может произойти либо повреждение данных той частью записанной строки, которая «выйдет» за границы выделенной памяти, либо крушение программы.

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

В стандарте C11 имеется стандартная библиотечная функция gets_s() , которая выполняет безопасное чтение строки. В качестве одного из параметров эта функция принимает размер памяти, зарезервированной для её хранения, включая байт, отведённый под завершающий нулевой символ. Если введённая пользователем строка не может быть целиком помещена в эту область памяти, то она «обрезается», и в память записывается лишь её часть и завершающий нулевой символ, а если может, то gets_s() , «действует» так же, как и gets() . Таким образом, переполнения гарантированно не происходит.

В более ранних версиях языка C функцию gets_s() можно реализовать на основе стандартной библиотечной функции fgets() . О том, как это сделать, я уже рассказывал здесь.

Но к функции gets_s() (неважно, стандартной, или нет), при желании, можно предъявить претензию, заключающуюся в том, что пользователь, который ввёл строку чрезмерной длины, не узнает о том, что в «обработку» пошла лишь её часть. Разумеется, можно его заранее предупредить об ограничениях, но он может их не заметить (умышленное их игнорирование сейчас рассматривать не будем).

В этой статье мы рассмотрим способ безопасного чтения строки, который просто «не позволит» набрать пользователю ни единого лишнего символа. Программный код, реализующий этот способ, напишем на языке C99.

Важная оговорка

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

Мы будем использовать функцию из библиотеки, не предусмотренной стандартами языка C, хоть и входящей, обычно, в состав C-компиляторов. Компилятор MinGW64, которым мы воспользуемся, включает в себя эту библиотеку.

А работать мы будем с консолью 64-х битной версии операционной системы Windows 10. Для консолей других операционных систем наш способ реализации чтения строки может не подойти.

Основная идея

Нестандартная библиотека, о которой шла речь в предыдущем разделе, — это conio.h. Нас будет интересовать функция getch() , входящая в её состав. Именно на ней и будет основан наш способ чтения строки.

Функция getch() читает символ, введённый пользователем в консоль и возвращает его код в виде значения типа int . При этом сам символ на консоль не выводится, поэтому более точным будет считать, что эта функция просто «перехватывает» нажатие клавиши. А программа уже обрабатывает его нужным ей способом. При этом функция перехватывает даже нажатия некоторых клавиш, которым не соответствуют никакие символы кодировки ASCII. Об этом мы ещё поговорим в дальнейшем.

Мы будем обрабатывать нажатия, выводя на консоль символы, им соответствующие, и одновременно записывая их коды в символьный массив. Делать мы это будем до тех пор, пока пользователь не нажмёт на клавишу [Enter], или пока число набранных символов не достигнет заранее заданного количества. В первом случае в массив будет добавлен завершающий нулевой символ, и операция чтения строки будет считаться завершённой. А во втором все последующие попытки набора текста будут заблокированы. Однако и в этом случае пользователь сможет завершить набор нажатием клавиши [Enter].

Помимо этого, будет предусмотрена возможность простейшего редактирования уже набранной части строки с помощью клавиши [Backspace]. При нажатии на неё будет уничтожаться символ, стоящий слева от курсора.

А теперь переходим к реализации этой идеи.

Функция con2str()

Наш способ чтения строки будет реализован в функции con2str() . Вот её код:

Функция con2str() принимает в качестве первого параметра адрес символьного массива, а в качестве второго — целое число. Она считывает из консоли символы, в количестве, не превышающем второй параметр, который мы назовём «ограничителем», и записывает их в данный массив. Далее в массив помещается нулевой символ, после чего адрес сформированной C-строки (совпадающий с первым параметром) возвращается в вызывающую функцию. Таким образом, для корректной работы функции требуется, чтобы размер массива, в котором нужно сохранить C-строку, по крайней мере, на единицу превышал ограничитель.

В 3-ей строке объявляем и инициализируем счётчик символов, записанных в массив и не удалённых пользователем. Переменная c , предназначенная для хранения символов, возвращённых функцией getch() , объявляется в 4-й строке.

Далее в цикле while (стр. 5) многократно вызываем функцию getch() , записывая в c возвращаемые ею символы, до тех пор, пока пользователь не нажмёт на клавишу [Enter], т. е. до тех пор, пока код очередного символа не станет равным 13 (см. стр. 5). На каждый итерации цикла обрабатывается один символ, хранящийся в c (при условии, что его код отличен от 13).

Если код символа равен 8 (стр. 7), т. е. пользователь нажал на клавишу [Backspace], и, при этом, счётчик символов отличен от 0 (стр. 9), то уменьшаем счётчик на единицу (стр. 11) и удаляем символ, стоящий слева от курсора (стр. 12). Поясним, что печать строки «\b \b» приводит к тому, что сначала курсор возвращается на одну позицию, что соответствует печати символа ‘\b’ , далее вместо символа, стоящего справа от курсора, печатается пробел, после чего курсор снова возвращается на одну позицию.

Если же была нажата клавиша [Backspace], но счётчик символов нулевой, т. е. удалять нечего, то просто игнорируем нажатие, переходя к следующей итерации (стр. 14).

Наконец, если код символа не равен 8 и значение счётчика ещё не сравнялось с ограничителем (стр. 16), помещаем в массив текущий символ, выполняем инкремент счётчика и печатаем символ на консоли с помощью функции putchar() (стр. 17). А если код символа не равен 8, а значение счётчика совпадает с ограничителем, то не происходит вообще ничего, кроме перехода к следующей итерации цикла, т. е. нажатие на клавишу игнорируется.

Как только пользователь нажимает [Enter], так сразу записываем в массив завершающий нулевой символ (стр. 19) и возвращаем адрес сформированной C-строки (стр. 20).

Тестирование функции con2str()

Для тестирования функции con2str() создадим файл, предназначенный для хранения исходного кода на языке C, и поместим в его начало следующие директивы #include :

Далее располагаем в файле саму функцию con2str() , а ещё ниже — функцию main() , которая и будет заниматься тестированием. Вот её код:

Полагаю, что код функции main() понятен. Создаём символьный массив, имеющий размер 11, и предлагаем пользователю ввести произвольную строку не более, чем из 10 символов, которую и считываем с консоли в массив с помощью тестируемой функции con2str() . Далее на консоль выводим саму строку и её длину.

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

Запустив программу, читатель сможет убедиться в том, что нажатия на клавишу [Backspace] обрабатываются корректно и в том, что ему никак не удастся ввести в консоль более 10-ти символов.

Недостатки функции con2str()

Функция con2str() имеет 2 главных недостатка:


  1. Возможности редактирования уже набранного текста ограничиваются использованием клавиши [Backspace]. Нельзя, например, переместить курсор влево на несколько позиций и ввести новые символы в режиме вставки.
  2. Нажатия на многие клавиши, которым не соответствуют печатаемые символы (условно назовём эти клавиши «управляющими»), также обрабатываются функцией getch() . Если же выводить на консоль символы, возвращаемые getch() в качестве результата обработки нажатий на такие клавиши, то будет печататься нечитаемый «мусор» (читатель может убедиться в этом самостоятельно). Примечание: формально клавиша [Backspace] также является управляющей, но мы её таковой считать не будем.

Что касается первого недостатка, то его устранение потребует достаточно много усилий. Фактически, придётся «вручную» реализовывать часть функционала консоли. К тому же, потребуется реализация таких операций, как «вставка символов в массив со сдвигом» и «удаление символов из массива со сдвигом», поскольку в рамках нашей концепции любое изменение текста в консоли сразу же отражается на содержимом символьного массива. Так что «полноценное» редактирование набранного в консоли текста в данной статье мы рассматривать не будем по причине громоздкости его реализации.

А вот способ устранения второго недостатка рассмотрим.

Блокировка управляющих клавиш

Все управляющие клавиши можно разбить на 3 группы:

  1. Клавиши [F1] — [F10].
  2. Клавиши [F11], [F12], [Print Screen], [Scroll Lock], [Insert], [Delete], [Page Up], [Page Down], [Home], [↑], [←], [↓], [→].
  3. Клавиша [Esc].

Особенностью клавиш, входящих в первую и вторую группы, является то, что каждой из них соответствует не один символ, а два. Например, клавише [←] соответствует пара символов ‘а’ и ‘K’ (первая буква — русская, а вторая — латинская). Поясним, каким образом функция getch() обрабатывает нажатия на такие клавиши.

В результате первого вызова функции getch() программа переходит в режим ожидания нажатия клавиш. Как только нажимается клавиша, принадлежащая одной их первых двух групп, так сразу же функция возвращает первый символ, соответствующий этой клавише, а второй записывается в некий буфер. В результате следующего вызова функция getch() , «не дожидаясь» очередного нажатия клавиши, сразу же возвращает второй символ из буфера.

Первый символ, соответствующий клавишам из первой группы, имеет код 0. Это тот самый символ, который является завершающим символом в C-строках. Стандартные функции, работающие с C-строками, игнорируют все символы, находящиеся за первым встреченным в строке нулевым символом. Так что нажатия на эти клавиши после запуска нашей программы не только приведут к выводу «мусора» на консоль, но и «собьют её с толку» (она неверно отобразит набранную строку и её размер).

А первый символ, соответствующий клавишам из второй группы, имеет код 224. В кириллической версии ASCII-кодировки данному коду соответствует русская буква «а».

С единственной клавишей, входящей в третью группу, всё просто: ей соответствует код с символом 27.

Давайте теперь поговорим о том, как блокировать нажатия управляющих клавиш.

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

Ещё проще заблокировать нажатие на клавишу [Esc]: если getch() возвращает 0, то переходим к ожиданию очередного нажатия.

А вот с клавишами второй группы всё гораздо сложнее. Дело в том, что клавишу с русской буквой «а» пользователь нажать может. Поэтому, если, например, в результате первого и второго вызова функции getch() , были возвращены символы ‘а’ и ‘K’ , возникает вопрос: что нажал пользователь: две клавиши с соответствующими буквенными символами, или одну клавишу [←]? Имея в распоряжении лишь результаты вызовов функции getch() , ответить на этот вопрос невозможно.

Будем решать нашу проблему «специфическим» способом. Он основан на использовании стандартной библиотечной функции clock() , объявленной в заголовочном файле time.h. Эта функция возвращает время, прошедшее с момента запуска программы, из которой она вызвана, или значение -1 , если данное время недоступно.

Время возвращается в некоторых «условных единицах». Продолжительность этой единицы в секундах обратна значению макроса CLOCKS_PER_SEC , определённому в том же заголовочном файле time.h. В нашем случае (напоминаю, что мы используем компилятор MinGW64) значение этого макроса равно 1000 , т. е. clock() , возвращает время в миллисекундах.

Действовать будем так. Если функция getch() возвращает 224, то печатаем символ ‘а’ , вызываем функцию clock() и фиксируем возвращённое ею время. После следующего вызова getch() снова вызываем clock() и находим разность между результатами второго и первого вызовов последней функции. Если оно меньше заранее заданного целого числа (назовём его »допуском»), то будем считать, что пользователь нажал на управляющую клавишу, а если нет — то на две символьных. В первом случае удаляем символ ‘а’ и переходим к ожиданию следующего нажатия, а во втором — печатаем второй символ.

Опыт показал, что, как бы быстро ни нажимались 2 клавиши подряд, всё равно результаты вызовов clock() после соответствующих вызовов getch() будут различны. И даже если пользователь нажмёт на клавишу с символом ‘а’ и не будет отпускать её некоторое время, достаточное для того, чтобы одно нажатие интерпретировалось как два, то и в этом случае результаты двух вызовов clock() не совпадут. А вот при нажатии управляющей клавиши из второй группы оба вызова clock() дают одинаковые результаты. Так что в моём случае в качестве допуска можно брать единицу. Но вообще говоря, нужно экспериментировать.

Новая версия функции con2str()

Итак, внесём в функцию con2str() изменения, приводящие к блокировке управляющих клавиш. Но перед этим подключим заголовочный файл time.h:

и зададим значение допуска с помощью макроса eps :

А вот и новая версия функции con2str() :

Остановимся на изменениях, произошедших в функции con2str() .

В стр. 5 объявляется и инициализируется переменная cl . В начале каждой итерации она содержит -1 , если итерация первая, или если на предыдущей итерации не был получен символ с кодом 224. В противном случае в cl содержится результат последнего вызова функции clock() .

Теперь переходим к изменениям в теле цикла while . В начале итерации проверяем текущий символ на равенство его кода числу 224. Если оно выполнено, то присваиваем cl результат вызова clock() (стр. 8, 9). А если нет, то выясняем, был ли получен код с символом 224 на предыдущей итерации, а если был, то будет ли разность результатов последнего и предпоследнего вызовов clock() меньше, чем допуск (стр. 12).

Утвердительные ответы на оба вопроса означают, что последней была нажата управляющая клавиша из 2-й группы. В этом случае уменьшаем значение счётчика на единицу (стр. 14), удаляем последний напечатанный символ, т. е. символ ‘а’ (стр. 15), присваиваем cl значение -1 (стр. 16) и переходим к следующей итерации цикла (стр. 17).

Если же текущий символ не совпадает с ‘а’ , и, при этом, либо предыдущий символ не совпадает с ‘а’ , либо совпадает, но время прошедшее между двумя последними вызовами clock() достаточно велико, то это означает, что последняя нажатая клавиша — символьная. В этом случае присваиваем cl значение -1 (стр. 19).

В строках 21-25 обрабатывается нажатие на управляющую клавишу из 1-й группы. Если оно произошло, т. е. текущий символ — нулевой (стр. 21), то вызываем getch() , не интересуясь результатом вызова (стр. 23) и переходим к следующей итерации (стр. 24).

Последнее изменение в функции con2str() касается строки 35. Мы помним, что символ выводится на печать, если значение счётчика не совпадает с ограничителем. К этому условию добавляем неравенство кода текущего символа числу 27. Таким образом мы блокируем нажатие на клавишу [Esc].

Заметим, что если бы существовала управляющая клавиша, которой соответствовали бы 2 символа ‘а’ , то наша функция не блокировала бы нажатие на неё. Однако такой клавиши не существует.

Читатель, запустив программу с изменённой версией функции con2str() может сам убедиться в том, что нажатия на все управляющие клавиши успешно блокируются.

Заключение

Итак, мы построили функцию, считывающую строку с консоли и ограничивающую количество вводимых пользователем символов. Разумеется, функцию можно улучшить. Речь идёт не только об усовершенствовании возможностей редактирования строки. Можно, например, предусмотреть блокировку ввода определённых символов (таким же образом, каким мы блокировали нажатие на [Esc]). Скажем, если ожидается ввод информации на русском языке, то имеет смысл запретить ввод латиницы.

А можно, наоборот, реализовать блокировку набора любых символов, кроме заранее выбранных. Например, если ожидается натуральное число, то резонно запретить набор любых нецифровых символов.

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

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

Gets ввод строки

При запуске программы на Си автоматически открываются пять потоков, основными из которых являются следующие:

Стандартный поток ввода stdin

Стандартный поток вывода stdout

Стандартный поток вывода сообщений об ошибках stderr

Стандартный поток ввода stdin по умолчанию соответствует клавиатуре, а потоки stdout и stderr — экрану монитора.

Для управления вводом-выводом с помощью этих потоков используются ряд функций:

getchar() : ввод с клавиатуры одного символа

putchar() : вывод на консоль одного символа


gets() : ввод одной строки

puts() : вывод одной строки на консоль

scanf() : ввод с форматированием данных

printf() : вывод с форматированием данных

Функции printf и scanf уже рассматиривались ранее, поэтому посмотрим, как применять остальные функции.

Ввод и вывод символов

Для ввода одного символа с клавиатуры применяется функция getchar() , которая имеет следующий прототип:

В качестве результата функция возвращает числовой код введенного символа.

Для вывода отдельного символа на консоль предназначена функция putchar() со следующим прототипом:

Выводимый символ в виде числового кода передается в putchar в качестве параметра, он же возвращается функцией.

Следует сказать, что на самом деле функции getchar() и putchar() полноценными функциями не являются, а определены как макросы в заголовочном файле stdio.h :

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

И если буфер операционной системы не пуст, то при вызове функции getc() она получает очередной символ из буфера. Если же буфер пуст, то происходит чтение байта из потока ввода с помощью системной функции, название которой зависит от операционной системы.

При этом при нажатии клавиши Enter, в буфер также помещается код этой клавиши. То есть если мы введем один символ и нажмем на Enter, в буфере окажутся два числовых кода — введенного символа и клавиши Enter. И это надо учитывать при работе с функцией getchar. В частости, рассмотрим простой, но показательный пример:

Сначала на экран выводится цифра 1, после чего функция getchar ожидает ввода символа. Если после ввода символа мы нажмем Enter, то в буфер будет помещены два числовых кода — введеного символа и клавиши Enter. Поэтому при втором вызове getchar эта функция считывает байт из буфера — то есть числовой код клавиши Enter.

Например, введем при первом вызове функции getchar символ «a», а затем Enter:

Но если при каждом вызове getchar мы будем только нажимать клавишу Enter, тогда в буфер будет заноситься только код этой клавиши, и соответственно программа будет работать, как и ожидалось:

Применим функции getchar и putchar для ввода и вывода символов с клавиатуры:

Функция getchar считывает числовой код символа, который потом выводится в функции putchar. Для вывода из программы необходимо ввести комбинацию клавиш Ctrl+C.

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

Для ввода строки с клавиатуры применяется функция gets() , которая имеет следующий прототип:

Вводимые данные помещаются в массив, на который указывает указатель *s, передаваемый в функцию в качестве параметра. При успешном прочтении строки функция возвращает адрес этого массива s. А в случае ошибки возвращается значение NULL .

При вводе символов функция gets() завершает свою работу при вводе символа ‘\n’, то есть при нажатии на клавишу Enter. Но вместо этого символа в строку записывается нулевой символ ‘\0’, который и будет указывать на завершение строки.

Для вывода одной строки на консоль предназначена функция puts() со следующим прототипом:

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

При этом функция puts() будет выводить символы переданной строки, пока не дойдет до нулевого символа ‘\0’. Если же выводимый массив символов не содержит этого символа, то результат программы неопределен.

Ввод текстовых строк с клавиатуры

Вывод текстовых строк на экран сложностей не вызывает:

char Str[21] = “Это пример текста”;

cout > Str; //Пусть введена строка“Это пример текста”

cout >) обеспечивает ввод символов до первого пробельного символа (по словам), а не до конца строки. Остальные символы введенного с клавиатуры предложения остаются в потоке ввода и могут быть прочитаны из него следующими операторами >>.

Для того чтобы прочесть всю строку полностью, можно воспользоваться одной из функций gets или gets_s (для этого в программу должен быть включен заголовочный файл ):

const int N = 21;

char Str [N];

gets (Str); //Пусть введена строка“Это пример текста”

// gets_s (Str, N);Альтернативный вариант

Рассмотри следующий пример:

const int N = 11;

char Str [N];

cin.getline (Str, N); //Пусть введена строка“Это пример текста”

cin.getline (Str, N); //Пусть введена строка“Это пример текста”

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: На стипендию можно купить что-нибудь, но не больше. 8987 — | 7235 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Как вводить строки или выводить их на экран?

Выводиться строка может или уже известной вам функцией printf( ) со спецификатором ввода «%s«, либо специальной функцией int puts (char *string), которая выводит строку string на экран и возвращает некоторое ненулевое значение в случае успеха.

Зачем нужен спецификатор «%s«? Это делается для того, чтобы можно было выводить строки с любыми символами. Сравните:


Пример:

char str [] = «Захотелось мне вывести %d. «;

printf («%s», str); /* Правильный вариант */

printf («\n»); /* Разделитель новой строки */

printf (str); /* Неправильный вариант */

В первом случае функция напечатает именно то, что от нее требуется. А вот во втором случае printf(), встретив в строке str спецификатор «%d» (ведь теперь эта строка – первая, значит, она задает формат вывода), сделает вывод, что за ней должно следовать число. А так как оно не следует, то вместо «%d» будет напечатан некоторый мусор – число, находящееся в тот момент в стеке.

Последствия могут быть и более серьезными, если в строке находится последовательность «%s», то сочтет ее за строку, и будет выводить ее до тех пор, пока не встретит нулевой символ. А где она его встретит, сколько успеет напечатать и не crash’нется ли из-за обращения не к своей памяти – не знает никто.

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

Пример: Необходимо сохранить введенную строку.

/*чтение строки с терминала*/

int getline(char s, /*введенная строка*/

int lim) /*ее максимальная длина*/

9.5 Ввод–вывод строк. Основные функции работы со строками

Одной из наиболее популярных операций ввода-вывода является операция ввода-вывода строки символов. В библиотеку языка СИ для обмена данными через стандартные потоки ввода-вывода включены функции ввода-вывода строк gets() и puts(), которые удобно использовать при создании диалоговых систем.

Для ввода строки существует функция с прототипом

char *gets (char *string),

которая считывает строку с клавиатуры и помещает ее в буфер string, указатель на который и возвращает. Если произошла ошибка, то возвращается EOF.

Функция имеет только один аргумент – указатель s на массив символов. Прототип функции описан в файле .

Функция gets() завершает свою работу при вводе символа ‘\n’, который автоматически передается с клавиатуры в ЭВМ при нажатии клавиши . При этом сам символ ‘\n’ во вводимую строку не записывается. Вместо него в строку помещается нуль–символ ‘\0’. Таким образом, функция gets() производит ввод “правильной” строки, а не просто последовательности символов.

Здесь следует обратить внимание на следующую особенность ввода данных с клавиатуры. Функция gets() начинает обработку информации от клавиатуры только после нажатия клавиши . Таким образом, она “ожидает”, пока не будет набрана нужная информация и нажата клавиша . Только после этого начинается ввод данных в программу.

Пример: #include

printf ( «Input a string:» );

printf ( «The string input was: %s\n», string );

Функция puts() (вывод строки на экран) в случае успешного завершения возвращает последний выведенный символ, который всегда является символом ‘\n’, если произошла ошибка, то возвращается из функции EOF. Прототип этой функции имеет следующий вид:

int puts ( char*s ); /*функция вывода строки*/

Функция имеет только один аргумент – указатель s на массив символов. Прототип функции описан в файле .

Приведем простейший пример использования этих функций.

char strl[ ] = ”введите фамилию сотрудника:”;

Напомним, что любая строка символов в языке СИ должна заканчиваться нуль–символом ‘\0’. В последний элемент массива strl нуль–символ будет записан автоматически во время трансляции при инициализации массива. Для функции puts() наличие нуль-символа в конце строки является обязательным.

В противном случае, т.е. при отсутствии в символьном массиве символа ‘\0’, программа может завершиться аварийно, т.к. функция puts() в поисках нуль-символа будет перебирать всю доступную память байт за байтом, начиная, в нашем примере, с адреса strl. Об этом необходимо помнить, если в программе происходит формирование строки для вывода ее на экран дисплея.

Пример: #include

char string[] = «This is an example output string\n»;

9.5 Функции манипуляции со строками

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

Для манипуляций со строками существует набор функций, объявленных в файле (те, кто пишет под Windows, могут включать вместо него файл ).

Наиболее важные функции:

I. int strcmp (char *string1, char *string2)

осуществляет сравнение двух строк. Возвращает отрицательное число, если первая строка меньше второй, 0, если строки равны и положительное число, если первая строка больше второй. Более детально, функция возвращает разницу между кодами первых встретившихся неодинаковых символов (если строки неодинаковы по длине, то когда-то ненулевой символ будет сравниваться с нулем).

Пример:

char *buf1 = «aaa», *buf2 = «bbb», *buf3 = «ccc»;

ptr = strcmp (buf2, buf1);

printf(«buffer 2 is greater than buffer 1 \n» );

printf(«buffer 2 is less than buffer 1 \n»);

ptr = strcmp( buf2, buf3 );

printf(«buffer 2 is greater than buffer 3\n»);

printf(«buffer 2 is less than buffer 3\n» );

На экране появится:

buffer 2 is greater than buffer 1

buffer 2 is less than buffer 3


II. char *strcpy (char *dest, char *source)

осуществляет копирование строки source на место строки dest. Опять-таки позаботьтесь о том, чтобы вся строка поместилась в отведенном для нее месте. Функция возвращает указатель на строку-приемник.

Пример: #include

char *str1 = «a b c d e f g h i»;

strcpy (string, str1);

printf( «%s \n», string);

На экране появится: a b c d e f g h I

III. char *strcat (char *string1, char *string2)

осуществляет склеивание двух строк. Вторая строка добавляется в конец первой. Функция не проверяет (да и не может проверять технически) наличие необходимого количества памяти в конце первой строки – об этом должны позаботиться вы. Функция возвращает указатель на первую строку.

Пример:

char *blank = » «, *c = «C++», *turbo = «Turbo»;

strcpy (destination, turbo); //Копирование строки «turbo»

на место destination

strcat (destination, blank); // Склеивание destination …

strcat (destination, c); // сначала с blank, потом с c

На экране появится: Turbo C ++

IV. int strlen (char *string)

возвращает длину строки string (не считая нулевого символа).

V. char *strdup (char *string)

создает дубликат строки string и возвращает указатель на него. Учтите, что в отличие от остальных функций, strdup сама создает строку и поэтому после того, как она стала вам не нужна, не забывайте ее освободить.

VI. char *strncpy ( char *dest, char *source, int count)

VII. char *strncat ( char *string1, char *string2, int count)

аналогично strcpy и strcat, но копируются только первые count символов. Функции не добавляют к строке завершающего нуля – вам придется сделать это самим.

VIII. char *strchr (char *string, int c)

IX. char *strstr (char *string, char *substring)

ищут первое вхождение в строку string соответственно символа c и подстроки substring. Обе функции возвращают адрес первого вхождения или NULL, если такового не найдено.

Пример:

strcpy (string, «This is a string»);

ptr = strchr(string, c);

printf(«The character %c is at position: %d\n», c, ptr-string);

printf( «The character was not found\n» );

На экране появится: The character r is at position: 12

Дата добавления: 2015-06-10 ; просмотров: 1967 ; ЗАКАЗАТЬ НАПИСАНИЕ РАБОТЫ

Строки в языке 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’ и наоборот.

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

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

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

При объявлении массивов строк можно производить инициализацию:
char имя[количество][длина] = <строковый литерал №1, . строковый литерал №N>;

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

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

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

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

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

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

Для ввода и вывода строковой информации можно использовать функции форматированного ввода и вывода (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);

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

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

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

Для считывания одного символа можно использовать функцию 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] . );

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

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

В С для преобразования строк, содержащих числа, в численные значения в библиотеке 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);

Илон Маск рекомендует:  Что такое код fbsql_query
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL