Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УМК-1_АЯП_рус.doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
1.19 Mб
Скачать

Int integ;

puts("Введите, пожалуйста, целое");

gets(ch);

integ=atoi(ch);

printf("Число было %d.\n", integ);

}

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

Для работы со строками существует специальная библиотека, описание которой находится в файле string.h.

Наиболее часто используются функции:

а)объединение строк или конкатенация

strcat(имя строки1, имя строки2);

б) замена содержимого одной строки содержимым другой

strcpy(имя строки1, имя строки2);

в) нахождение числа символов в строке

strlen(имя строки);

г) сравнение Строки 1 и Строки 2.

strcmp(имя строки1, имя строки2);

Возвращает 0, если строки равны, число меньше нуля, если Строка 1<Строка 2 и число больше нуля, если Строка 1>Строка2.

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

strlwr(имя строки);

е) преобразование прописных символов строки в строчные (обрабатывает только буквы латинского алфавита).

strupr(имя строки);

ж) заполнение строки указанным при вызове функции символом

strset(имя строки, имя символа);

Синтаксис: char*strset (char*Строка, char Символ)

з) поиск символа в строке. (Возвращает указатель на первый найденный символ или, если символ не найден – NULL.)

strchr(имя строки, имя символа);

Синтаксис: char*strchr (const char*Строка, int Символ).

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

Объединение строк. Функция – strcat () позволяет добавить строку источник в конец строки-приемника (завершающий нуль записывается автоматически). Надо только помнить, что приемник должен иметь достаточный размер, чтобы вместить обе исходных строки. Функция strcat автоматически добавляет в конец строки-результата завершающий символ '\0'.

#include <stdio.h>

#include <string.h>

main()

{

char s1[80] = "Могу, ",

s2[] = "хочу, ", s3[] = "надо!";

strcat ( s1, s2 ); // дописать s2 в конец s1

puts ( s1 ); // "Могу, хочу, "

strcat ( s1, s3 ); // дописать s3 в конец s1

puts ( s1 ); // "Могу, хочу, надо!"

}

Копирование строк

#include <stdio.h>

#include <string.h>

main()

{

char s1[] = "Ку-ку", s2[10];

strncpy ( s2, s1, 2 ); // скопировать 2 символа из s1 в s2

puts ( s2 ); // ошибка! нет последнего '\0'

s2[2] = '\0'; // добавляем символ окончания строки

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

}

Длина строки

#include <stdio.h>

#include <string.h>

main()

{

int len;

char s[] = "Prodigy";

len = strlen(s);

printf ( "Длина строки %s равна %d", s, len );

}

Сравнение строк. Функцияstrcmp () сравнивает две строки. Функция возвращает ноль, если строки равны (то есть «разность» между ними равна нулю) и ненулевое значение, если строки различны. Сравнение происходит

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

#include <stdio.h>

#include <string.h>

main()

{

char s1[] = "Вася",

s2[] = "Петя";

if ( 0 == strcmp(s1,s2) )

printf("Строки %s и %s одинаковы", s1, s2);

else printf("Строки %s и %s разные", s1, s2);

}

Эти числа можно использовать для сортировки строк – если «разность» отрицательна, значит первая строка «меньше» второй, то есть стоит за ней в алфавитном порядке.

Основная литература: 1[93-96], 2[38-40]

Дополнительная литература:1,2,3,5

Контрольные вопросы:

1. Как описываются строки в языке С?

2. Чем отличаются функции scanf() и gets(), printf() и puts()?

3. Функции преобразования символьных строк atoi(), atof().

4. Что является признаком конца потока и как он записывается в программе?

5. Что возвращает функция сравнения строк strcmp(имя строки1, имя строки2) , если строки различны.

Лекция 10. Связь между указателями и массивами. Массив указателей. Указатели, указывающие на другие указатели. Указатели на многомерные массивы

Связь между указателями и массивами.

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

INT A[10]

определяет массив размера 10, т.е. набор из 10 последовательных объектов, называемых A[0], A[1], ..., A[9]. Запись A[I] соответствует элементу массива через I позиций от начала. Если PA - указатель целого, описанный как

INT *PA

то присваивание

PA = &A[0]

приводит к тому, что PA указывает на нулевой элемент массива A; это означает, что PA содержит адрес элемента A[0]. Теперь присваивание

X = *PA

будет копировать содержимое A[0] в X. Если PA указывает на некоторый определенный элемент массива A, то по определению PA+1 указывает на следующий элемент, и вообще PA-I указывает на элемент, стоящий на I пози-

ций до элемента, указываемого PA, а PA+I на элемент, стоящий на I позиций после. Таким образом, если PA указывает на A[0], то

*(PA+1)

ссылается на содержимое A[1], PA+I - адрес A[I], а *(PA+I) -содержимое A[I].

Эти замечания справедливы независимо от типа переменныхв массиве A. Суть определения "добавления 1 к указателю", а также его распространения на всю арифметику указателей, состоит в том, что приращение масштабируется размером памяти, занимаемой объектом, на который указывает указатель. Таким образом, I в PA+I перед прибавлением умножается на размер объектов, на которые указывает PA.

Очевидно существует очень тесное соответствие между индексацией и арифметикой указателей. В действительности компилятор преобразует ссылку на массив в указатель на начало массива. В результате этого имя массива является указательным выражением. Отсюда вытекает несколько весьма полезных следствий. Так как имя массива является синонимом местоположения его нулевого элемента, то присваивание PA=&A[0] можно

записать как

PA = A

Еще более удивительным, по крайней мере на первый взгляд, кажется тот факт, что ссылку на A[I] можно записать в виде *(A+I). При анализировании выражения A[I] в языке "C" оно немедленно преобразуется к виду *(A+I); эти две формы совершенно эквивалентны. Если применить операцию & к обеим частям такого соотношения эквивалентности, то мы получим,что &A[I] и A+I тоже идентичны: A+I - адрес I-го элемента от начала A.

Имеется одно различие между именем массива и указателем, которое необходимо иметь в виду. указатель является переменной, так что операции PA=A и PA++ имеют смысл. Но имя массива является константой, а не переменной: конструкции типа A=PA или A++,или P=&A будут незаконными.

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

strlen(s) /* return length of string s */

char *s;

{

int n;

for (n = 0; *s != '\0'; s++)

n++;

return(n);

}

Операция увеличения s совершенно законна, поскольку эта переменная является указателем; s++ никак не влияет на символьную строку в обратившейся к STRLEN функции, а только увеличивает локальную для функции STRLEN копию адреса. Описания формальных параметров в определении функции в виде

CHAR S[];

CHAR *S;

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

Можно передать функции часть массива, если задать в качестве аргумента указатель начала подмассива. Например, если

A - массив, то как запись

F(&A[2])

так и запись

F(A+2)

передают функции F адрес элемента A[2], потому что и &A[2],и A+2 являются указательными выражениями, ссылающимися на третий элемент A. Внутри функции F описания аргументов могут присутствовать в виде:

F(ARR)

INT ARR[];

{

...

}

или

F(ARR)

INT *ARR;

{

...

}

Пример

//работа с массивами с помощью указателей

//нахождение суммы элементов массива

#include <stdio.h>

#include <conio.h> //для очистки экрана и задержки в программе