Примечание 2. Программист должен сам заботиться о том, чтобы в строке-приемнике (s1) хватило место для строки-источника (s2), и о том, чтобы строка всегда имела нуль-символ

Текст программы

/* Вывод символьной переменной в различных формах*/

#include<stdio.h>

#include<conio.h>

main()

{

char b; //Обявление символьной переменной

puts("Введите один символ");

b=getchar(); //Ввод значения переменной b

printf("\tb=");

putchar(b); //Вывод значения переменной b

printf("\nДесятичный код b=%d\n",b); //Вывод десятичного кода b

printf("\tВосьмеричный код b=%o\n",b); //Вывод восьмеричного кода b

printf("\t\tШестнадцатеричный код b=%X\n",b);

printf("b='%c'\n",b);

getch();

}

Результаты выполнения программы:

 

Введите один символ

*

b=*

Десятичный код b=42

Восьмеричный код b=52

Шестнадцатеричный код b=2A

b='*'

 

Введите один символ

{

b={

Десятичный код b=123

Восьмеричный код b=173

Шестнадцатеричный код b=7B

b='{'

Введите один символ

#

b=#

Десятичный код b=35

Восьмеричный код b=43

Шестнадцатеричный код b=23

b='#'

 

 

Введите один символ

b=5

Десятичный код b=53

Восьмеричный код b=65

Шестнадцатеричный код b=35

b='5'

В библиотеке ctype определен целый ряд функций, проверяющих принадлежность символа какому-либо множеству: множеству букв (isalpha), букв или цифр (isalnum), разделителей (isspase), знаков пунктуации (ispunct), цифр (isdigit), видимых символов (isgraph), букв верхнего регистра (isuper), букв нижнего регистра (islower), печатаемых символов (isprint) и т.д.

Аргументом каждой из этих функций является символ. Функция возвращает значение true,если символ принадлежит конкретному множеству символов, или false в противном случае.

 

Пример. Ввести символ с клавиатуры и проверить, является ли он знаком пунктуации (. , ! ? : ; ).

Текст программы

#include<stdio.h>

#include<ctype.h>

#include<conio.h>

void main()

{

char a;

puts("Введите один символ");

a=getchar();

if(ispunct(a))

printf("Символ %c явл. знаком пунктуации\n",a);

else

printf("Символ %c не явл. знаком пунктуации\n",a);

getch();

}

Результаты выполнений программы

 

Введите один символ

.

Символ . явл. знаком пунктуации

Введите один символ

^

Символ ^ явл. знаком пунктуации

Введите один символ

e

Символ e не явл. знаком пунктуации

Введите один символ

#

Символ # явл. знаком пунктуации

Введите один символ

[

Символ [ явл. знаком пунктуации

Введите один символ

-

Символ - явл. знаком пунктуации

Введите один символ

n

Символ n не явл. знаком пунктуации

 

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

 

#include<stdio.h>

void main()

{

char c,c1;

c='A';

c1=65;

printf("%c %d\n",c,c);

printf("%i %c\n",c1,c1);

if(c1=='A' && c== 65)

puts("Обе A");

else puts("****");

}

 

Результат выполнения программы:

A 65

65 A

Обе A

 

Пример использования функции char (код символа) из библиотеки ctype

#include<stdio.h>

#include<conio.h>

#include<ctype.h>

void main()

{

int cod;

char S;

puts("Ввeдите 1 символ");

S=getchar();

cod=char(S);

putchar(S);

printf("\t\n");

printf("%c %d %d\n",S,S,cod);

getch();

}

Результаты выполнения программы:

Ввeдите 1 символ

2 50 50

Ввeдите 1 символ

%

%

% 37 37

Ввeдите 1 символ

D

D

D 68 68

Понятие и описание строки

 

В языке Си отсутствует специальный строковый тип.

Строка в Си – это массив символов.

В памяти ЭВМ строка представляется как массив элементов типа char, в конце которого помещается символ '\0' - завершающий нуль-символ. Это не цифра 0, а символ, у которого в кодовой таблице все нули (т.е. 00000000).

Строковая константа – это последовательность символов, заключенная в кавычки ("). Например, " Задача имеет множество решений". В памяти представляется как массив элементов типа char с завершающим нуль-символом ('\0').

Общий вид описания строки:

 

сhar <имя строки>[<длина строки с учетом нуль-символа>];

 

Например, сhar S[100];

Или const int N=100;

сhar S[N]; //Удобно задавать длину строки с помощью // именованной константы

В такой строке можно хранить 99 символов и завершающий нуль-символ.

 

При описании строки можно выполнять ее инициализацию. Например,

сhar S1[100]= "Исходный массив";

 

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

Если строка при описании инициализируется, то можно опускать длину строки. Например,

сhar S1[]= "Исходный массив"; //16 символов

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

сhar a[20]; //Так

a="Строковая константа"; //нельзя

1. Описание динамической строки

 

Для размещения строки в динамической памяти, необходимо описать указатель на сhar, а затем выделить память с помощью new или malloc (new предпочтительнее).

Например,

сhar *S3=new char[m];//m должно быть уже определено

Или

сhar *S3;

S3=new char[m];

Примечание. Динамические строки, как и другие массивы, нельзя инициализировать.

Например, оператор,

сhar *S4="На нуль делить нельзя";

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

 

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

Рассмотрим ввод-вывод строк с помощью функций, унаследованных из бибдиотеки Си: gets и puts, scanf и printf.

Функции gets и puts используются, если работа производится только со строками. Функции scanf и printf удобнее использовать в том случае, если в одном операторе требется ввести или вывести данные разных типов.

Функция gets предназначена для ввода строки. Имеет один параметр, задающий адрес области памяти, в которую помещаются символы вводимой строки. В языке Си имя переменной, имеющей строковый тип, является этим адресом. Обращение имеет вид: gets(name), где name – переменная строкового типа - имя вводимой строки. Выполняя эту функцию, программа приостанавливает свою работу и ждет от пользователя ввода последовательности символов и/или нажатия клавиши Enter. Символ новой строки в строку не включается, вместо него в строку заносится нуль-символ. Функция возвращает указатель на строку s, а в случае возникновения ошибки или конца файла – NULL.

Функцияputs предназначена для вывода строки на стандартное устройство вывода. Имеет один параметр, задающий адрес области памяти, из которой на экран выводятся символы. Как уже отмечалось, имя переменной, имеющей строковый тип, является этим адресом. Обращение имеет вид: puts(name), гдеname – переменная-строка - имя выводимой строки или строка символов, заключенная в кавычки. После вывода строки курсор перемещается к началу новой строки экрана, т.е. завершающий нуль-символ строки заменяется на символ новой строки. Возвращает неотричательное значение при успехе или EOF при ошибке.

Функция printf предназначена для вывода форматированной последовательности данных

Функция scanf предназначена для ввода данных в заданном формате. Обращение имеет вид:

scanf(nf,&a1,&a2,...)

Здесь nf - форматная строка; &a1,&a2,... - список ввода - указатели на значения вводимых переменных a1, a2, .....

Подробно эти функции рассматривались в разделе "Консольный ввод-вывод".

 

Операции над строками

Реализация операции присваивания

Поскольку строка является массивом, а не специальным типом данных, то для строк не определена операция присваивания. Присваивание можно выполнить посимвольно, т.е. "вручную", или с помощью стандартных функций strcpy и strncpy.

Рассмотрим первый способ. Пример: s[0]='В'; s[1]='в'; s[2]='о'; s[3]='д';

Рассмотрим второй способ. Для использования функций strcpy и strncpy к программе следует подключить заголовочный файл <string.h> предложением #include <string.h>

Обращение к функции strcpy имеет вид: strcpy(s1,s2);

Функция копирует все символы строки s2, включая завершающий нуль-символ, в строку s1 и возвращает s1.

Пример 1.

/* Копирование строки s2 в строку s1 c помощью strcpy */

#include<stdio.h>

#include<string.h>

#include<conio.h>

void main()

{

int n; // Длина строки

char s2[20]="Скоро сессия!"; //Исходная строка

n=strlen(s2)+1; //Длина s1

char *s1=new char[n]; //Строка - копия s1

// char s1[20];

strcpy(s1,s2); //Копирование s2 в s1

puts(s2); // Вывод s2

puts(s1); //Вывод s1

puts(strcpy(s1,s2)); //strcpy возвращает s1

getch();

}

Результат выполнения программы – три строки:

Скоро сессия!

Скоро сессия!

Скоро сессия!

 

Обращение к функции strncpy имеет вид: strncpy(s1,s2,n);

Функция копирует не более n символов из строки s2 в строку s1 и возвращает s1. При этом, если длина исходной строки (s2) превышает или равна n, нуль-символ в конец строки s1 не добавляется. В противном случае строка s1 дополняется нуль-символами до n-го символа. Если строки перекрываются, поведение не определено.

Пример 2.

/* Копирование строки s2 в строку s1 c помощью strncpy */

#include<stdio.h>

#include<string.h>

#include<conio.h>

void main()

{

int n; // Длина строки

char s2[20]="Скоро сессия!"; //Исходная строка

n=strlen(s2)+1; //Длина s1

//char *s1=new char[n]; //Строка - копия s1

char s1[20];

strncpy(s1,s2,n); //Копирование s2 в s1

puts(s2); // Вывод s2

puts(s1); //Вывод s1

puts(strncpy(s1,s2,n)); //strncpy возврващает s1

getch();

}

 

Результат выполнения программы такой же, как и в примере 1.

Примечание 1. В рассмотренных примерах использована функция strlen(s), возвращающая фактическую длину строки s, не включая нуль-символ.

Примечание 2. Программист должен сам заботиться о том, чтобы в строке-приемнике (s1) хватило место для строки-источника (s2), и о том, чтобы строка всегда имела нуль-символ.