Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Практикум по программированию на языке Си

..pdf
Скачиваний:
23
Добавлен:
12.11.2023
Размер:
3.53 Mб
Скачать

int main ()

{

printf("symbol: %c, code: %u\n",'"','"'); return 0;

}

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

symbol: ", code: 34

Результаты экспериментов демонстрируют "неполноту" сообщений, выдаваемых компилятором при наличии нескольких ошибок в программе. Для получения безошибочного текста программы пришлось дважды вносить в нее исправления. Итак, выяснилось, что из нестандартных констант компилятор DJGPP смог воспринять только кавычки (в апострофах).

ЗАДАЧА 02-13. Получите изображения, "длины" и коды особых графических символов, представляя их эскейп-последова-

тельностями: \', \”, \?, \\.

/* 02_13.c – эскейп-представления особых символов */ #include <stdio.h>

int main ()

{

printf

("symbol: %c, sizeof(\'\\'\')=%d, code: %u\n", '\'', sizeof('\''), '\'');

printf

("symbol: %c, sizeof(\'\\\"\')=%d, code: %u\n", '\"', sizeof('\"'),'\"');

printf

("symbol: %c, sizeof(\'\\?\')=%d, code: %u\n", '\?', sizeof('\?'),'\?');

printf

("symbol: %c, sizeof(\'\\\\')=%d, code: %u\n", '\\', sizeof('\\'),'\\');

return 0;

}

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

51

symbol: ', sizeof('\'')=4, code: 39 symbol: ", sizeof('\"')=4, code: 34 symbol: ?, sizeof('\?')=4, code: 63 symbol: \, sizeof('\\')=4, code: 92

Отметим, что длина кода символа, записанного в виде эскейппоследовательности (например ‘\?’), равна четырем байтам, как и для обычного представления символа.

В тексте программы надо обратить внимание на разную запись эскейп-последовательностей внутри форматной строки и вне ее. Внутри форматной строки символ ' заменен двумя символами: \’, для изображения кавычки использована пара \”, а каждый отдельный символ \ должен быть изображен парой символов \\.

ЗАДАЧА 02-14. Получите "изображения" и коды неграфических символов, представляемых эскейп-последовательностями: '\a', '\b', '\f', '\n', '\r', '\t', '\v'.

// 02_14.c - коды неграфических символьных констант

#include <stdio.h> int main ()

{

printf("symbol: %c, code: %u\n",'\a','\a'); printf("symbol: %c, code: %u\n",'\b','\b'); printf("symbol: %c, code: %u\n",'\f','\f'); printf("symbol: %c, code: %u\n",'\n','\n'); printf("symbol: %c, code: %u\n",'\r','\r'); printf("symbol: %c, code: %u\n",'\t','\t'); printf("symbol: %c, code: %u\n",'\v','\v'); return 0;

}

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

symbol: , code: 7 symbol:, code: 8 symbol:, code: 12 symbol:

, code: 10

 

,

code: 13

, code: 9

symbol:

symbol:

 

'

code: 11

 

52

При исполнении программы воспроизводится звуковой сигнал, "инициатор" которого – эскейп-последовательность.

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

ЗАДАНИЕ. Проведите такой же эксперимент, как в предыдущей программе, с "нестандартными" эскейп-последователь- ностями, например, '\A' и '\z'.

/* 02_14_1.c - нестандартные представления */

*/

#include

<stdio.h>

/* 02

int main

()

/* 03

*/

{

 

/* 04

*/

printf("symbol: %c, code: %u\n",'\A','\A');/* 05

*/

printf("symbol: %c, code: %u\n",'\z','\z');/* 06

*/

return 0;

/*

07

*/

}

/*

08

*/

Трансляция с предупреждениями:

02_14_1.c: In function `main':

02_14_1.c:5: warning: unknown escape sequence `\A' 02_14_1.c:5: warning: unknown escape sequence `\A' 02_14_1.c:6: warning: unknown escape sequence `\z' 02_14_1.c:6: warning: unknown escape sequence `\z'

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

symbol: A, code: 65 symbol: z, code: 122

Полученные значения десятичных кодов совпадают с соответствующими кодами символов ‘A’ и ‘z’, но транслятор "возражает", выдавая предупреждающие сообщения (warning).

ЗАДАЧА 02-15. Получите длину и код символа, представляемого как '\0', и сравните с длинами и кодами символа '0' (ноль) и символа ' ' (пробел).

53

/* 02_15.c - символы '\0', '0' и ' ' */ #include <stdio.h>

int main ()

{

printf("sizeof(\'\\0\')=%d, symbol: %c", sizeof('\0'),'\0');

printf(", codes: %u(10), %o(8), %x(16)\n", '\0','\0','\0');

printf("sizeof(\'0\')=%d, symbol: %c", sizeof('0'),'0');

printf(", codes: %u(10), %o(8), %x(16)\n", '0','0','0');

printf("sizeof(\' ')=%d, symbol: %c", sizeof(' '),' ');

printf(", codes: %u(10), %o(8), %x(16)\n", ' ',' ',' ');

return 0;

}

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

sizeof('\0')=4, symbol: , codes: 0(10), 0(8), 0(16) sizeof('0')=4, symbol: 0, codes: 48(10), 60(8), 30(16)

sizeof(' ')=4, symbol: , codes: 32(10), 40(8), 20(16)

Результаты, особенно различие между кодами символов '0' и '\0', рекомендуется запомнить.

ЗАДАЧА 02-16. Выбрав из таблицы кодов ASCII коды какихлибо символов, напечатайте с помощью эскейп-последователь- ностей их изображения, длины внутренних представлений и числовые значения, представленные с разными основаниями счисления.

Нужно обратить внимание, что при записи эскейп-последова- тельностей с числовыми кодами не применимы десятичные цифры (только восьмеричные и шестнадцатеричные). В следующей программе рассматривается представление символов '#' и 'L'.

/* 02_16.c - изображения и коды эскейппоследовательностей */

54

#include <stdio.h> int main ()

{

printf("sizeof(\'\\043\')=%d, symbol: %c\n", sizeof('\043'),'\043');

printf("\tcodes: %u(10), %o(8), %x(16)\n", '\043','\043','\043');

printf("sizeof(\'\\x4c\')=%d, symbol: %c\n", sizeof('\x4c'),'\x4c');

printf("\tcodes: %u(10), %o(8), %x(16)\n", '\x4c','\x4c','\x4c');

return 0;

}

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

sizeof('\043')=4, symbol: #,

codes: 35(10), 43(8), 23(16) sizeof('\x4c')=4, symbol: L,

codes: 76(10), 114(8), 4c(16)

В результатах обратите внимание на "длины" констант, представленных эскейп-последовательностями. В тексте программы отметим разную запись эскейп-последовательностей в форматной строке и вне ее.

Остановимся на ошибках в записи эскейп-последовательностей.

ЭКСПЕРИМЕНТ. Опустите признаки оснований системы счисления в записи эскейп-последовательностей с числовыми кодами, представляющих символы '#' и 'L', т.е. вместо '\043' запишите '\43', а вместо '\x4c' используйте '\4c'.

Не приводя текста программы (см. файл 02_16_1.с в электронной поддержке Практикума), отметим, что трансляция пройдет с предупреждениями. На каждое появление неверной эскейп-после- довательности будет выдано сообщение:

"Warning: multi-character constant"

("Предупреждение: мульти-символьная константа"). Результаты выполнения программы будут такими:

sizeof('\43')=4, symbol: #

codes: 35(10), 43(8), 23(16)

55

sizeof('\4c')=4, symbol: c

codes: 1123(10), 2143(8), 463(16)

Из результатов исполнения видно, что компилятор воспринял '\43' как правильную запись константы, представляющей символ '#', а последовательность '\4c' трактует как мультибайтовую (мультисимвольную) константу, значение которой отличается от 'L'.

ЗАДАЧА 02-17. Выведите символ и коды мультисимвольной константы 'ab'.

/* 02_17.c - мультибайтовые символы */

/* 2*/

#include

<stdio.h>

int main

()

/* 3*/

{

 

/* 4*/

printf("sizeof(\'ab\')=%d, symbol: %c\n",

/* 5*/

 

sizeof('ab'),'ab');

/* 6*/

printf(",\tcodes: %u(10), %o(8), %x(16)\n",

/* 7*/

return

'ab','ab','ab');

/* 8*/

0;

/* 9*/

}

 

/*10*/

Трансляция с предупреждениями:

02_17.c: In function `main':

02_17.c:6: warning: multi-character character constant

02_17.c:6: warning: multi-character character constant

02_17.c:8: warning: multi-character character constant

02_17.c:8: warning: multi-character character constant

02_17.c:8: warning: multi-character character constant

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

sizeof('ab')=4, symbol: b

codes: 24930(10), 60542(8), 6162(16)

56

Длина мультибайтовой константы 'ab' равна четырем байтам. По спецификации %c из константы выведен только символ 'b'. Шестнадцатеричный код содержит коды обоих символов 61 для 'a' и 62 для 'b'. Десятичное и восьмеричное представления кода мультисимвольной константы не так наглядны.

ЗАДАЧА 02-18. Длина мультисимвольной константы равна четырем байтам. Проверьте допустимость размещения в апострофах четырех символов. Пусть это будут цифра 4 (код \x34) и

знаки: ? (код \x3f), = (код \x3d) и @ (код \x40):

/* 02_18.c - мультибайтовые символьные константы */ #include <stdio.h>

int main ()

{

printf("sizeof(\'4?=@\')=%d, symbol: %c", sizeof('4?=@'),'4?=@');

printf(", code: %x(16)\n",'4?=@'); return 0;

}

Трансляция с теми же предупреждениями, что и в программе

02_17.с.

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

sizeof('4?=@')=4, symbol: @, code: 343f3d40(16)

Шестнадцатеричный код представляет собой конкатенацию шестнадцатеричных кодов символов '4', '?', '=', '@'.

ЭКСПЕРИМЕНТ. Попытаемся разместить в мультибайтовой символьной константе более четырех символов.

/* 02_18_1.c - мультибайтовые недопустимые

 

#include

символьные константы */

/* 3*/

<stdio.h>

int main

()

/* 4*/

{

 

/* 5*/

printf("sizeof(\'12345\')=%d, symbol: %c",

/* 6*/

 

sizeof('12345'),'12345');

/* 7*/

 

 

57

printf(", code: %x(16)\n",'12345');

/*

8*/

return 0;

/*

9*/

}

/*10*/

Аварийное завершение трансляции:

02_18_1.c: In function `main':

02_18_1.c:7: character constant too long

02_18_1.c:7: character constant too long

02_18_1.c:8: character constant too long

Ничего не получилось – константу из пяти (и более) символов компилятор воспринимает как фатальную ошибку.

2.6. Символьные строки (строковые константы)

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

Изучая строковые константы, нужно обратить внимание:

!на их длину (в памяти ЭВМ);

!на особенности их записи в тексте программы;

!на изображение строки при выводе (например, на экран дисплея).

ЗАДАЧА 02-19. Сравните длины символьной константы 'A', символьной строки из одного символа "A" и строки из нескольких символов "12345".

// 02_19.c - символьные строки (строковые константы) #include <stdio.h>

int main ()

{

printf("sizeof(\"12345\")=%d\n",sizeof("12345"));

printf("sizeof(\"A\")=%d\n",sizeof("A"));

printf("sizeof(\'A\')=%d\n",sizeof('A')); return 0;

}

58

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

sizeof("12345")=6

sizeof("A")=2

sizeof('A')=4

Строковая константа представляется в памяти последовательностью байтов, каждый из которых содержит код символа строки. В конце этой последовательности размещается код "тернарного" символа '\0', автоматически добавляемый компилятором. Именно поэтому длина строки "A" равна 2, а длина строки "12345" равна шести байтам. C тем, что одному символу 'A' выделен участок памяти 4 байта, мы уже знакомы – символ отнесен Стандартом к типу int.

ЭКСПЕРИМЕНТ. Используя выражение sizeof(char) и sizeof(wchar_t), оцените размеры памяти, выделяемые вашим транслятором для данных типов char и wchar_t соответственно. Напоминаем, что тип wchar_t не является базовым, а определен в заголовочном файле <stddef.h>.

/* 02_19_1.c - символьные типы char и wchar_t */ #include <stdio.h>

#include <stddef.h> int main ()

{

printf("sizeof(char)=%d\n",sizeof(char)); printf("sizeof(wchar_t)=%d\n",sizeof(wchar_t)); return 0;

}

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

sizeof(char)=1 sizeof(wchar_t)=4

ЗАДАЧА 02-20. Сравните размеры памяти, выделенной для обычной строковой константы (с символами типа char), и для константы из символов расширенного набора:

// 02_20.c - строка из символов расширенного набора

#include <stdio.h> int main ()

59

{

printf("sizeof(\"12345\")=%d\n",sizeof("12345")); printf

("sizeof(L\"12345\")=%d\n",sizeof(L"12345")); return 0;

}

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

sizeof("12345")=6

sizeof(L"12345")=24

Как подтверждают результаты, строка с символами типа wchar_t занимает (k+1)#4 байта, для строки с символами типа char выделяется (k+1) байтов, где k – количество явно использованных символов. Отметим, что символ '\0' в строке с элементами типа char занимает 1 байт, а в строке из символов расширенного набора его длина равна 4 байта. В то же время sizeof('\0') равно 4.

Обратим внимание на некоторые особенности записи строковых констант в тексте программы.

ЗАДАЧА 02-21. Запишите фразу “Repetitio est mater studiorum!” ("Повторение – мать учения!"), разместив каждое слово на отдельной строке текста программы.

Первый вариант (одна строковая константа):

/* 02_21.c - строковая константа в нескольких строках */

#include <stdio.h> int main ()

{

puts("Repetitio \ est \

mater \ studiorum!");

return 0;

}

Символ '\', не видимый при печати код '\n', и все пробелы между ними компилятор автоматически удаляет из текста.

60