Лекция 14


1. Задача на поиск смены знака в массиве


Найти в массиве размер N индекс k, такой, что все элементы с индексом i<=k имеют один знак, а все элементы с индексом i>k имеют другой знак, причем равенство 0 допускается только для элемента с индексом k (k>0 и k<N-1).


0

1

2

3

4

5

6

7

8

9

10

-2

-1

-3

-7

-12

-5

0

2

1

3

4



Процедура Индекс смены знака

! Дано: Массив A размера N

! Найти: Индекс k, для которого все элементы с индексом i<=k имеют один знак, а все

! элементы с индексом i>k имеют другой знак, причем равенство 0 допускается только

! для элемента с индексом k (k>0 и k<N-1)

k := -1

Если A[N-1] != 0 то

Цикл для I от N-2 до 1 (включительно) выполнять

Если A[I] * A[N-1] <= 0 то

k = I

выйти из цикла

Конец если

Конец цикла

Если k > 0 то

Цикл для I от k-1 до 0 (включительно) выполнять

Если A[I] * A[N-1] >= 0 то

k = -1

выйти из цикла

Конец цикла

Конец если

ответ := k

Конец процедуры



2. Инициализация массивов


int k = -1;

int array[100] = { -1, -2, 0, 4, 11 }; /* Значения первых 5 элементов массива */

int array[] = { 23, -17, 245, 6, -7, 14 }; /* Массив размера 6 */

char str[20] = { 'a', 'b', 'c' }; /* Значения первых 3 элементов массива */

char str1[] = { 'a', 'b', 'c' }; /* Массив размера 3 */

char str2[] = "abc"; /* Массив размера 4 */


В конце строковой константы — некий символ, который обозначает конец строки: символ с кодом 0 (так как символ с кодом 0 — служебный и не был еще занят).

ASCII (American Standard Institute …)

0 – символ конца строки символов

10 – символ конца строки в тексте (в Линуксе — один этот символ — конец строки)

13 — символ перевода каретки (Line Feed) Windows – два символа конца строки 13+10)

(утилиты Линукса dos2unix и unix2dos)

32 – пробел

...

48 — '0' (ноль)

49 — '1' (единица)

57 — '9' (девятка)

(код цифры → ее значение: value = с — '0', где c - char)

65 – 'a'

66 – 'b'

90 – 'z'



3. Работа со строками


Символ с кодом 0 определяет, где строка кончается.

Проблемы: При отсутствии символа с кодом 0 в строке — может произойти

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


Задача 1. Скопировать строку


char *strcpy(char *str1, char *str2) {

while (*(str2++) = *(str1++)); /* значение выражения в условии while равно присвоенному значению */

return –str2; /* Возвращаем адрес символа с кодом 0, завершающего строку */

}


(man strcpy → документация по функции strcpy())



Задача 2. Сравнить две строки


int strcmp(char *str1, char *str2) {

while (*str1) {

if (*str1 > *str2)

return 1;

if (*str1 < *str2)

return -1;

++str1;

++str2;

}

return (*str2 == 0 ? 0 : -1);

}

Лексико-графический порядок — строки упорядочены по алфавиту, начиная с первого символа



0

...




s1





s2





array








...






'a'

'b'

'c'

\0


'o'

'f'

\0



&s1


&s2








N=2


Задача 3. Отсортировать массив строк по возрастанию (исходный код)


/* Массив строк array, размер массива N */

void sort(char *array[], int N) {

int i, j;

char *buf;

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

for (j = 0; j < N-1; j++) {

if (strcmp(array[j], array[j+1]) > 0) {

buf = array[j];

array[j] = array[j+1];

array[j+1] = buf;

}

}

}

}