Слайд 1Работа с массивами и со строками в Си
Лекция 2
Слайд 2
Массивы
Массив состоит из элементов одного и того же типа. Ко
всему массиву целиком можно обращаться по имени. Можно выбирать любой
элемент массива. Число элементов массива назначается при его определении и в дальнейшем не изменяется. Если массив объявлен, то к любому его элементу можно обратиться следующим образом: указать имя массива и индекс элемента в квадратных скобках. Массивы определяются так же, как и переменные:
int a[100];
char b[20];
float d[50];
Индексация всегда начинается с нуля.
Слайд 3Двумерный массив
Двумерный массив представляется как одномерный, элементами которого так же
являются массивы. Например, определение
char а[10][20];
задает такой массив. По
аналогии можно установить и большее число измерений.
Элементы двумерного массива хранятся по строкам, т.е. если проходить по ним в порядке их расположения в памяти, то быстрее всего изменяется самый правый индекс. Например, обращение к девятому элементу пятой строки запишется так:
а[5][9]
Пусть задан массив
int a[2][3];
Тогда элементы массива а будут размещаться в памяти следующим образом:
a[0][0],a[0][1],a[0][2],a[1][0],a[1][1], a[1][2].
Слайд 4Имя массива
Имя массива это константа, которая содержит адрес его
первого элемента (в примере выше а содержит адрес элемента а[0][0]).
Предположим, что a = 1000. Тогда адрес элемента а[0][1] будет равен 1004 (если элемент типа int занимает в памяти 4 байта), адрес следующего элемента а[0][2] 1008 и т.д.
Что же произойдет, если выбрать элемент, для которого не выделена память? К сожалению, компилятор не отслеживает данной ситуации. В результате возникнет ошибка и программа будет работать неправильно.
В языке Си существует сильная взаимосвязь между указателями и массивами. Любое действие, которое достигается индексированием массива, можно выполнить и с помощью указателей, причем последний вариант будет работать быстрее, но об этом – позже.
Слайд 5Инициализация массива
Язык Си позволяет инициализировать массив при его определении. Для
этого используется следующая форма:
[...] ... [...] =
{<список значений>};
Примеры:
int a[5] = {0, 1, 2, 3, 4};
char ch[3] = {'d', 'e', '9'};
int b[2][3] = {{1, 2, 3}, {4, 5, 6}};
/*{1, 2, 3, 4, 5, 6}*/
В последнем случае:
b[0][0] = 1, b[0][1] = 2, b[0][2] = 3, b[1][0] = 4,
b[1][1] = 5, b[1][2] = 6.
Слайд 6Символьная информация
Символьная константа – это лексема, которая состоит из изображения
символов и ограничивающих апострофов.
’A’, ’a’, ’b’, ’9’, ’+’, …
Специальные символы
– управляющие последовательности:
’\n’ – перевод строки;
’\t’ – горизонтальная табуляция;
’\r’ – возврат каретки (курсора) к началу строки;
’\\’ – обратная косая черта \;
’\’’ – апостроф (одиночная кавычка);
’\”’ – кавычка (символ двойной кавычки);
’\0’ – нулевой символ;
’\a’ – сигнал-звонок;
’\b’ – возврат на одну позицию;
’\f’ – перевод (прогон) страницы;
’\v’ – вертикальная табуляция;
’\?’ – знак вопроса.
Слайд 7Символьные переменные
Описание символьных переменных:
char список_имен_переменных;
char c, b, l;
Для ввода и
вывода символьных значений в форматных строках библиотечных функций printf и
scanf используется спецификация преобразования %c.
Слайд 8Пример: необходимо вывести предложение, слова в котором разделены одним пробелом,
и в конце которого стоит точка. Лишние пробелы необходимо убрать
Текст
программы :
#include
int main()
{
char z, s; /*z - текущий вводимый символ*/
printf (″\n Input the sentence:\n″);
for (z = s = ′ ′; z != ′.′; s = z)
{ /* s – предыдущий символ */
scanf(″%c″, &z);
if (z==′ ′ && s==′ ′) continue;
printf (″%c″, z);
}
return 0;
}
Слайд 9Внутренние коды и упорядоченность символов
В языке принято соглашение, что везде,
где синтаксис позволяет использовать целые числа, можно использовать и символы,
т.е. данные типа char, которые при этом представляются числовыми значениями своих внутренних кодов.
Такое соглашение позволяет сравнительно просто упорядочивать символы, обращаясь с ними как с целочисленными величинами.
Таблица ASCII (American Standard Code for Information Interchange) – американский стандартный код для обмена информацией.
Слайд 12Пример:
Печать десятичных цифр и их шестнадцатеричных кодов
#include
int main
()
{
char z;
for (z='0'; z
%c-%x ", z, z);
}
return 0;
}
Результат выполнения программы:
0-30 1-31 2-32 3-33 4-34
5-35 6-36 7-37 8-38 9-39
Слайд 13Пример: Печать латинского алфавита
#include
int main ()
{
char z;
for (z='A'; z
z++)
printf("%c", z);
return 0;
}
Результат выполнения программы:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Слайд 14Пример: посчитать сумму десятичных цифр в введенной последовательности символов, заканчивающейся
точкой
#include
int main ()
{
char z;
int s = 0;
do
{
scanf("%c",&z);
if ((z>='0')&& (z
+= z -'0';
}
while (z!='.');
printf("%d\n", s);
return 0;
}
Слайд 15Строки и строковые константы
В программе строковые константы представляются последовательностью изображений
символов, заключенной в двойные кавычки.
Примеры:
"1234567890"
"\t List of users"
" The string
start \n and the string finish\n "
Размещая строку в памяти, транслятор автоматически добавляет в ее конец символ '\0'
Строка – это массив символов, т.е. она имеет тип char[].
Количество элементов в таком массиве на 1 больше, чем изображение соответствующей строковой константы.
Замечание
Минимальный размер памяти для строки равен 1 байт.
При работе со строками не забывайте предусматривать отведение памяти для этого символа и добавлять его в конец строки.
В чем различие :
"A" и 'A' ?
Слайд 16Пример: Печать символьной строки
#include
int main ()
{
char B[] = "Hello!";
printf("%s",
B);
return 0;
}
0 1
2 3 4 5 6
’Н’
’l’
’l’
’e’
0
’!’
’o’
B
Слайд 17Пример: для введенной строки создать новую строку, состоящую только из
маленьких букв латинского алфавита, входящих в нее
#include
int main ()
{
char
A[100], B[100];
int i, j = 0;
printf("Enter string: ");
scanf ("%s", A); // ввод строки с клавиатуры
for (i = 0; A[i]; i++)
if ( (A[i] >= 'a') && (A[i] <= 'z'))
{
B[j] = A[i];
j++;
}
B[j] = '\0'; //вставка в конец строки нуля
printf("%s", B);
return 0;
}
Слайд 18Строки и указатели
Указатель – это переменная, значением которой является адрес.
char
A[20];
/* массив, в который можно записать строку*/
char *B;
/* указатель,
с которым можно связать строку */
scanf ("%s", A); //оператор верен
scanf ("%s", B); //оператор не корректен
Слайд 20unsigned int strlen(char *s)
/* вычисляет длину строки s */
{
int i;
for
(i = 0; s[i]; i++);
return i;
}
...
int l;
char st[10] = ”hello!”;
l
= strlen (st);
0 1 2 3 4 5 6 7 8 9
’h’
’l’
’l’
’e’
0
’!’
’o’
st
Слайд 21char *strcpy(char *ad, char *as)
/* копирует байты строки as в
строку ad*/
{
int i;
for (i=0; as[i]; i++)
ad[i] = as[i];
ad[i] = 0;
return
ad;
}
...
char s1[10], s2[5];
...
strcpy (s1, s2);
’h’
’l’
’l’
’e’
0
’!’
’o’
s1
’t’
’t’
’s’
’e’
0
s2
’t’
’e’
’s’
’t’
0
Слайд 22int strcmp(char *al, char *ar)
/* сравнивает строки al и ar:
выдает значение > 0, если al > ar
0, если al < ar
= 0, если al = ar */
{
int i;
for (i = 0; (al[i] == ar[i]) && (al[i] != 0); i++);
return (al[i] – ar[i]);
}
...
char s1[10], s2[5];
...
if (strcmp (s1, s2) > 0) // что будет выдано?
...
’h’
’l’
’l’
’e’
0
’!’
’o’
s1
’t’
’t’
’s’
’e’
0
s2