Скачиваний:
2
Добавлен:
03.01.2024
Размер:
567.33 Кб
Скачать

Строки как одномерные массивы данных типа char

Для ввода строк, как и для других объектов программы,

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

 

Функция scanf вводит значения для строковых

 

переменных при помощи формата (спецификатора

 

ввода) %s до появления первого символа “пробел”

 

(символ «&» перед ID строковых данных указывать не

 

надо);

Функция gets осуществляет ввод строки, которая может

 

содержать пробелы. Завершается ввод нажатием

 

клавиши Enter.

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

нулевой байт.

Например: char Str[30];

printf(“ Введите строку без пробелов : \n”); scanf(“%s”, Str);

или

puts(“ Введите строку ”); gets(Str);

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

Функция printf не переводит курсор после вывода на начало новой строки, а puts автоматически переводит курсор после вывода строковой информации в начало новой строки.

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

Часто используемые стандартные строковые функции:

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

#include <stdio.h> int main()

{char *S1 = «Санкт-Петербург\0", S2[] = «СПбГУТ"; printf("%d, %d.", strlen(S1), strlen(S2)); // getchar();

return 0;

}

Функция strcpy(S1, S2) – копирует содержимое строки S2 в строку S1.

Функция int strcmp(S1, S2) сравнивает строки S1 и S2 и возвращает значение <0, если S1<S2; >0, если S1>S2; =0, если строки равны, т.е. содержат одно и то же число одинаковых символов.

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

11

Строки как одномерные массивы данных типа char

Функции преобразования строковых объектов в числовые

 

Выводы. Пример: char s[80];

 

 

Функции преобразования строковых объектов в числовые

 

 

 

 

описаны в библиотеке stdlib.h

 

 

 

 

 

Преобразование строки S в число:

 

 

 

 

 

 

 

целое: int atoi(S); // array to int

 

 

 

 

 

 

 

длинное целое:

long atol(S); // array to longint

 

 

 

 

 

 

 

действительное:

double atof(S); // array to float

 

 

 

 

 

 

 

при возникновении ошибки данные функции

 

 

 

 

 

 

 

возвращают значение 0.

 

 

 

 

 

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

 

 

 

 

 

 

 

целое: itoa(V, S, kod); // int to array

 

 

 

 

 

 

 

длинное целое:

ltoa(V, S, kod); // longint to array

 

 

 

 

 

 

2 kod 36,

 

 

 

 

 

 

 

 

 

для десятичных чисел со знаком kod = 10.

 

 

 

 

 

Пример:

 

 

 

 

 

 

 

Фрагмент кода программы, в котором из строки s удаляется

 

 

 

 

символ, значение которого содержится в переменной с

каждый

 

Символьная строка – это последовательность символов,

 

 

раз, когда он встречается

 

 

 

 

 

 

 

 

 

которая заканчивается символом '\0'

 

 

 

 

char s[81], c;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

char s[80]; /* выделяется 80 байт, в строке – «мусор» (если она

 

 

 

 

...

 

 

 

 

 

 

 

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

 

 

глобальная, то нули '\0‘) */

 

 

 

 

if( s[i] != c) s[j++] = s[i];

 

 

char s[80] = "abc"; /* выделяется 80 байт, занято 4 байта

 

 

 

 

s[j]='\0';

 

 

 

 

 

 

...

 

 

 

(с учетом '\0') */

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

char s[ ] = "Вася"; /* выделяется 5 байт, (с учетом '\0') */

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

NB:

 

 

 

 

 

 

 

 

 

При выделении памяти надо учитывать место для символа '\0'.

 

 

 

 

 

 

 

 

 

В строку нельзя записывать больше символов, чем выделено

 

 

 

 

 

 

 

 

 

памяти.

12

4. Примеры обработки массивов

 

1. Реверс массива

элементы массива в обратном

 

2. Циклический сдвиг

 

 

 

 

Задача: сдвинуть элементы массива влево на 1 ячейку,

 

Задача: переставить

порядке (выполнить инверсию).

первый элемент становится на место последнего.

 

 

Алгоритм:

 

Алгоритм:

 

A[0]=A[1]; A[1]=A[2];… A[N-2]=A[N-1];

и A[N-2],

Фрагмент кода:

 

поменять местами A[0] и A[N-1], A[1]

 

main()

Фрагмент кода:

 

 

 

 

{

for ( i = 0; i < N/2; i++ ) // поменять местами A[i] и A[N-1-i]

const int N = 10;

main()

 

 

 

 

int A[N], i, c;

{ const int N = 10;

 

 

// заполнить массив

int A[N], i, c;

 

3. Сортировка массивов

// вывести исходный массив

// заполнить массив

 

На ПЗ и ЛР

c = A[0];

// вывести исходный массив

 

for ( i = 0; i < N/2; i++ )

 

 

for ( i = 0; i < N-1; i ++)

{ c = A[i];

 

4. Поиск в массиве

A[i] = A[i+1];

A[i] = A[N-1-i];

 

На ПЗ и ЛР

A[N-1] = c;

A[N-1-i] = c;

 

 

// вывести полученный массив

}

 

 

}

} // вывести полученный массив

 

 

 

 

13

Примеры обработки массивов

Пример 1: все элементы массива увеличиваются на 1. int A[3] = {1, 2, 3};

Вариант 1

A[0] = A[0]+1; A[1]+=1; A[2]++;

Вариант 2

A[0]++;

A[1]++;

A[2]++;

Вариант 3

for ( int i = 0; i < 3; i++ ) A[i]++;

Пример 2:

double m[100], a, b;

b = 3 * m[2]; a = m[50] / b; m[99]++;

Пример 3: сложение двух массивов. int A[4] = { 2, 3, 4};

int B[] = {1, -1, 5}; int C[4] = {0};

Вариант 1

C[0] = A[0]+B[0];

C[1] = A[1]+B[1];

C[2] = A[2]+B[2];

Вариант 2

for (int i=0; i<3; i++) C[i] = A[i]+B[i];

Использование массивов

Используются для хранения различных последовательностей

Обработка массивов

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

Поиск в массиве

и др.

14

Примеры обработки массивов

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

Предположим, что длина массива типа char равна 80.

Первое решение задачи инвертирования массива:

char z[80], s; char *d, *h;

/* d и h — указатели на символьные объекты */ for (d=z, h=&z[79]; d<h; d++, h--)

{ s = *d; *d = *h; *h = s;

}

В заголовке цикла указателю d присваивается адрес первого (с нулевым индексом) элемента массива z.

Здесь можно было бы применить и другую операцию, а именно d=&z[0].

Указатель h получает значение адреса последнего элемента массива z.

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

Цикл выполняется до тех пор, пока d<h.

После каждой итерации значение d увеличивается, значение h уменьшается на 1.

При первой итерации в теле цикла выполняется обмен значений z[0] и z[79], так как d - адрес z[0], h - адрес z[79].

При второй итерации значением d является адрес z[1], для h - адрес z[78] и т. д.

Второе решение задачи инвертирования массива:

 

 

char z[80], s, *d, *h;

 

 

 

for (d=z, h=&z[79]; d<h;)

 

 

 

{

 

 

 

s = *d; *d++ = *h; *h-- = s;

 

 

 

}

 

Приращение указателя d и уменьшение указателя h

 

 

перенесены в тело цикла.

 

Напоминаем, что в выражениях *d++ и *h-- операции

 

 

увеличения (постфиксный инкремент) и уменьшения

 

 

(постфиксный декремент) на 1 имеют тот же приоритет, что и

 

унарная адресная операция '*'.

 

Поэтому изменяются на 1 не значения элементов массива, на

 

которые указывают d и h, а сами указатели.

 

Последовательность действий такая:

 

 

 

по значению указателя d (или h) обеспечивается доступ к

 

 

элементу массива;

 

 

в этот элемент заносится значение из правой части

 

 

 

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

 

 

затем увеличивается (уменьшается) на 1 значение

 

 

 

указателя d (или h).

 

 

Третье решение задачи инвертирования массива (используется

 

цикл с предусловием):

 

 

 

char z[80], s, *d, *h;

 

 

 

d=z;

 

 

 

h=&z[79];

 

 

 

while (d < h)

 

 

 

{

 

 

 

} s=*d; *d++ = *h; *h-- = s;

15

Примеры обработки массивов

Продолжение (см. предыдущий слайд)

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

Предположим, что длина массива типа char равна 80.

Четвертое решение задачи инвертирования массива

(имитация индексированных переменных указателями со

смещениями):

 

char z[80],s;

Этот пример демонстрирует

int i;

возможность использования вместо

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

индексированного элемента z[i]

{s = *(z+i);

выражения *(z+i).

В языке Си, как мы знаем, имя массива

*(z+i) = *(z+(79-

без индексов есть адрес его первого

*(z+(79-i)) = s;

элемента (с нулевым значением

}

индекса).

Прибавив к имени массива целую величину, получаем адрес соответствующего элемента, таким образом, &z[i] и z+i – это две формы определения адреса одного и того же элемента массива, отстоящего на i позиций от его начала.

Итак, в соответствии с синтаксисом языка операция индексирования E1[E2] определена таким образом, что она эквивалентна *(E1+E2), где E1 - имя массива, E2 - целое.

Для многомерного массива правила остаются теми же.

Таким образом, E[n][m][k] эквивалентно *(E[n][m]+k) и, далее,

*(*(*(E+n)+m)+k).

Имя массива не является переменной типа указатель, а есть

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

Таким образом, к имени массива не применимы операции '+ +' (увеличения), '--' (уменьшения), имени массива нельзя присвоить значение, то есть имя массива не может использоваться в левой части оператора присваивания.

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

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

В случае массивов с другими элементами (другого типа) единичному изменению указателя, как уже отмечалось, соответствует большее изменение адреса.

16

Примеры обработки массивов

Задача: ввести с клавиатуры массив из 5 элементов,

умножить все элементы на 2 и вывести полученный массив на

экран.

 

#include <stdio.h>

 

#include <conio.h>

 

void main()

 

{

 

const int N = 5;

 

int A[N], i;

 

// ввод элементов массива

 

printf("Введите 5 элементов массива:\n");

A[0] = 5

for( i=0; i < N; i++ ) {

A[1] = 12

printf ("A[%d] = ", i );

A[2] = 34

scanf ("%d", & A[i] );

A[3] = 56

}

A[4] = 13

// обработка массива

printf("Введите 5 элементов массива:\n"); for( i=0; i < N; i++ ) {

printf ("A[%d] = ", i ); scanf ("%d", & A[i] );

}

// вывод результата

printf("Введите 5 элементов массива:\n"); for( i=0; i < N; i++ ) {

printf ("A[%d] = ", i );

Результат:

scanf ("%d", & A[i] );

10 24 68 112 26

}

 

getch();

 

}

 

Самостоятельно дома:

1) Ввести c клавиатуры массив из 5 элементов, найти среднее арифметическое всех элементов массива.

Введите пять чисел: 4 15 3 10 14

среднее арифметическое 9.200

2) Ввести c клавиатуры массив из 5 элементов, найти минимальный из них.

Введите пять чисел: 4 15 3 10 14

минимальный элемент 3

17

Примеры обработки массивов. Заполнение случайными числами

#include <stdlib.h> // случайные числа

RAND_MAX – максимальное случайное целое число (обычно RAND_MAX = 32767)

Случайное целое число в интервале [0,RAND_MAX] x = rand(); // первое число

x = rand(); // уже другое число

Установить начальное значение последовательности: srand ( 345 ); // начнем с 345

Целые числа в интервале [0,N-1]: int random(int N)

{} return rand()% N;

Примеры:

x = random ( 100 ); // интервал [0, 99] x = random ( z ); // интервал [0, z-1]

Целые числа в интервале [a,b]:

x = random ( z ) + a; // интервал [a, z-1+a] x = random (b – a + 1) + a; // интервал [a, b]

Пример: Заполнение случайными числами

#include <stdio.h> #include <stdlib.h>

/* функция выдает случайное число от 0 до N-1 */ int random(int N)

{ return rand() % N; }

main()

{

const int N = 10; int A[N], i;

printf("Исходный массив:\n"); for (i = 0; i < N; i++ )

{

A[i] = random(100) + 50; printf("%4d", A[i]);

}

...

}

Самостоятельно дома:

3)Заполнить случайными числами [100, 150]. Найти максимальный элемент и его номер

4)Заполнить массив из 10 элементов случайными числами в интервале [-10..10] и найти в нем максимальный и минимальный элементы и их номера.

18

19

Соседние файлы в папке Лекции