Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции за I семестр.docx
Скачиваний:
5
Добавлен:
17.04.2019
Размер:
267.81 Кб
Скачать

12.1. Строки как нуль-терминированные массивы char.

а) Основные понятия.

Один из способов организовать работу со строками - это использование одномерных массивов типа char. Тогда строка символов – это одномерный массив типа char, заканчивающийся нулевым байтом.

Нулевой байт – это байт, каждый бит которого равен нулю, при этом для нулевого байта определена символьная константа ´\0´ (признак окончания строки, или нуль-терминатор). По нулевому байту функции, работающие со строками, определяют место окончания строки. Если они читают строку, то воспринимают ее только до первого нуль-терминатора; если они создают строку, то записывают нуль-терминатор в ее конец.

Поэтому, если строка должна содержать максимум k символов, то в описании массива необходимо указать k+1 элемент. Например, char a[7]; - означает, что строка может содержать от 0 до 6 символов, а один байт будет занимать нуль-терминатор.

Строковая константа – это набор символов, заключенных в двойные кавычки, например: "Работа со строками". Такие константы хранятся именно как массивы типа char. В конце строковой константы явно указывать символ ´\0´ не нужно (он будет добавлен автоматически в ходе компиляции).

Строковые константы можно использовать при инициализации массивов:

сhar S[]="Работа со строками";

В этом примере размер массива не указан, поэтому он будет определен автоматически (19 элементов).

б) Ввод-вывод строк - массивов char.

Для ввода с консоли строк - массивов char обычно используются две стандартные функции:

scanf() (см. тему "Функции ввода-вывода"; спецификатор ввода %s; символ «&» перед именем массива типа char указывать не надо). Значения вводятся до появления первого символа “пробел”, а если его нет - до конца строки;

gets(char *S) (запись "char *S" означает, что на ее место нужно подставить массив типа char; можно также подставить указатель на char - см. тему "Указатели"). Значения вводятся до конца вводимой строки (т.е., в отличие от scanf(), может вводить строку с пробелами как единое целое).

Обе функции автоматически ставят в конец строки нулевой байт.

Вывод строк производится функциями printf() или puts() до первого нулевого байта (‘\0’):

printf() (см. тему "Функции ввода-вывода"; спецификатор вывода %s) не переводит курсор после вывода на начало новой строки;

puts(char *S) автоматически переводит курсор после вывода строковой информации в начало новой строки.

Например:

char Str[30];

printf("Введите строку без пробелов : \n");

scanf("%s",Str);

или

puts("Введите строку");

gets(Str);

В оконных приложениях C++ Builder изображаемый на экране текст, как правило, имеет тип String (или при необходимости автоматически преобразуется в String). Для вывода туда строки - массива char обычно достаточно просто подставить ее имя в функцию вывода:

Edit1->Text=Str;

Но для ввода оттуда такой строки необходимо использовать преобразование типов и копирование (объяснение см. ниже):

strcpy(Str, Edit1->Text.c_str());

в) Поэлементная работа со строками.

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

Пример поэлементной работы со строкой - массивом char :

Задача 1. В строке заменить все пробелы на символы подчеркивания.

#include<stdio.h>

#include<conio.h>

void main(){

char s[50];

int i;

puts("Vvedite stroku s probelami:");

gets(s);

for(i=0; s[i]; i++) // poka s[i] != nul-terminatoru

if (s[i]==' ') s[i]='_';

puts(s);

getch();

}

г) Копирование, сцепление (конкатенация), сравнение, поиск строк - массивов char.

Описание прототипов стандартных функций работы со строками - массивами char находится в файле string.h.

Рассмотрим наиболее часто используемые функции (перед именем функции указывается тип ее результата, в скобках - количество и типы параметров).

Функция int strlen(char *S) возвращает длину строки (количество символов в строке), при этом завершающий нулевой байт не учитывается.

Пример:

char S1[]="Минск!\0", S2[90]="БГУИР-Ура!";

printf("%d, %d .", strlen(S1), strlen(S2));

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

6 , 10 .

Функция strcpy(char *S1, char *S2) - копирует содержимое строки S2 в строку S1. Она заменяет операцию присваивания, непригодную для массивов в языке С.

Пример:

char s[50], t[30];

strcpy(t, "Hello!");

strcpy(s,t);

Функция strcat(char *S1, char *S2) - присоединяет строку S2 к концу строки S1 и помещает ее в массив, где находилась строка S1, при этом строка S2 не изменяется. Нулевой байт, который завершал строку S1, заменяется первым символом строки S2. (Такая операция называется также конкатенацией или сцеплением строк).

Пример:

char a[20], b[10];

strcpy(a, "Hello,");

strcpy(b, "world!");

strcat(a,b);

puts(a);

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

Hello,world!

Функция int strcmp(char *S1, char *S2) сравнивает строки S1 и S2 . Результат функции - целое число, меньшее 0, если значение S1 предшествует значению S2 в "алфавитном" порядке; большее 0, если S2 предшествует S1; равное 0, если строки равны, т.е. содержат одно и то же число одинаковых символов.

Под "алфавитным порядком" здесь понимается порядок возрастания кодов символов (см. тему "Кодирование символов", кодовые таблицы). Как можно видеть из этих таблиц, этот порядок совпадает с алфавитным для латинских букв одинакового регистра, а также для русских букв одинакового регистра (кроме буквы 'ё'). Если первые символы S1 и S2 совпадают, то учитываются следующие символы и т.д., по обычным алфавитным правилам.

Функция int stricmp(char *S1, char *S2) делает то же, что и strcmp, но нечувствительна к регистру букв (например, 'D' и 'd' для нее - одинаковые символы).

Пример:

char a[20], b[10];

gets(a);

gets(b);

if (!strcmp(a,b))

puts("a==b!");

else

if (strcmp(a,b)<0)

puts("a<b!");

else puts("b<a!");

Для a="Москва", b="Могилев" результат будет:

b<a!

Функции:

  • strncpy(char *S1, char *S2, int max);

  • strncat(char *S1, char *S2, int max);

  • int strncmp(char *S1, char *S2, int max);

  • int strnicmp(char *S1, char *S2, int max);

делают то же, что и соответствующие им функции strcpy, strcat, strcmp, stricmp, но, если длина строки S2 превышает max, то они используют только первые max ее символов. В этом случае нуль-терминатор в конце полученной строки может не быть поставлен автоматически.

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

char * strstr(char *S1, char *S2);

Здесь S1 - строка, в которой будет проводиться поиск; S2 - искомая подстрока. Результатом функции является указатель (см. тему "Указатели") на первое (считая слева направо) местоположение подстроки S2 в строке S1, либо NULL, если S2 не встречается в S1.

д) Перевод строк - массивов char в числа и наоборот.

Функции преобразования строки S в число:

  • целое: int atoi(char *S);

  • длинное целое: long atol(char *S);

  • действительное: double atof(char *S);

При ошибке данные функции возвращают значение 0.

Пример:

char s[]="120"; int i;

i=atoi(s); // i=120

Функции преобразования числа V в строку S:

  • целое: itoa(int V, char *S, int kod);

  • длинное целое: ltoa(long V, char *S, int kod);

Здесь kod - основание системы счисления, в которой должно быть записано полученное число: 2 kod 36, для десятичных чисел kod=10.

Пример:

char s[10]; int i=120;

itoa(i, s, 10);

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

sscanf(char *S, …) ;

sprintf(char *S, …) ;

Они во всем подобны функциям scanf и printf, но после их открывающей скобки вначале указывается имя строки, из которой "читаются" (sscanf) или в которую "записываются" (sprintf) значения совершенно так же, как они вводятся с клавиатуры функцией scanf или выводятся на экран функцией printf.

В отличие от функции atoi, sscanf позволяет отличить ошибку ввода от нулевого результата (см. про scanf в теме "Функции ввода-вывода"), например:

char s[20]; int i;

...

if (! sscanf(s, "%d", &i)) puts("Nevernoe chislo!");

е) Примеры работы со строками - массивами char.

Задача 2. Удалить символ "с" из строки s каждый раз, когда он встречается.

int i,j;

for( i=j=0; s[i]; i++)

if( s[i]!=c)

s[j++]=s[i];

s[j]='\0';

Задача 3. Если строка начинается со слова "song" (неважно, в каком регистре), добавить в начало и конец ее восклицательные знаки.

char s[50],t[52];

int i;

...

if (!strnicmp(s, "song", 4)) {

strcpy(t,"!");

strcat(t, s);

strcat(t, "!");

strcpy(s,t);

}

Если s было равно "Song 1", то оно станет равно "!Song 1!".

Другой вариант решения этой же задачи:

if (!strnicmp(s, "song", 4)) {

sprintf(t,"!%s!",s);

strcpy(s,t);

}

Задача 4. Из строки выделить и вывести подстроку, содержащую запись вещественного числа без знака с фиксированной точкой. Если таких подстрок несколько, вывести их все.

n=strlen(s);

for (i=0; i<n; i++)

if (s[i]=='.'){

// Выделение целой части вещественного числа

for (j=i-1; j>=0; j--)

if (s[j]<'0' || s[j]>'9') break;

//(Вначале была проверка j>=0, т.к. иначе s[j] недопустимо)

// Выделение дробной части вещественного числа

for (k=i+1; s[k]>='0' && s[k]<='9'; k++);

//(Незачем проверять на k<n - при k=n s[k]=0, а 0 <'0')

if (k==i+1 && j==i-1) //Если ни целой, ни дробной части

continue; // то переходим к следующей итерации for(i)

for (j++, p=0; j<k; j++,p++)

t[p]=s[j]; // Копируем в t подстроку от j+1 до k-1

t[p]=0; // Ставим нуль-терминатор

puts(t);

i=k; // Смещаем i за конец подстроки

}