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

Давыдов В.Г. - Программирование и основы алгоритмизации - 2003

.pdf
Скачиваний:
839
Добавлен:
13.08.2013
Размер:
9.55 Mб
Скачать

Программа-пример

4 (начало) .

 

 

ВЫВОД В ЯЗЫКЕ Си/С++:

 

 

 

Укажите вид

строк печати

в файле fl,out

на магнитном диске

после выполнения

приведенной

ниже программы

'^7

 

 

 

 

 

 

^include <stdio.h>

//

Для функций

ввода-вывода

±nt main ( void. )

//

Возвращает

О при

успехе

{

//Данные для печати

float

 

f

=

 

1.5е2;

 

 

 

 

 

 

long-

double

 

 

 

 

 

 

 

 

 

±пЬ

 

Id =

 

2.0e-3L;

 

 

 

 

 

 

i

= 7/

 

 

 

 

 

 

long- ±nb

11

=

 

121;

 

 

 

 

 

 

short

±nt

si

=

5;

 

 

 

 

 

 

FILE

 

*f_out/

 

//

Указатель на

структуру со

 

int

 

 

 

 

 

 

//

сведениями

о файле для

вывода

 

 

retcode;

//

Возвращаемое

значение для

fсlose

//

Открываем файл fl.out

для

записи

 

 

 

f_out

= fopen(

"fl.out",

 

"w"

);

 

 

 

±f(

f_out

== NULL )

 

 

 

 

 

 

{

print

f ( "\n

Файл fl.out

для записи

не открыт. " );

 

 

 

return

1;

 

 

 

 

 

 

 

 

}

//Записываем в файл fl.out

fprlntfi

f__out,

"

%30s\n

f=%f %5s l = %10d\n",

fprlntfi

f_out,

"

ld=%-Lf

f=%15f

f=%15.2f

 

f=%+15.2f\n".

 

 

 

Id,

frf.

 

f

);

fprlntf(

f_out,

"

l = %10.5d f=^%E ll = %ld sl = %hl\n",

 

 

 

i/

ff

11,

si

);

//Закрываем файл fl.out

retcode

= fclose(

f_out );

±f( retcode

== EOF )

{

 

 

 

printf(

"\n

Файл fl.out не закрыт." );

return

2;

 

}

 

 

 

return

0/

 

 

}

//Конец примера 4

Как работает д^уякияя fprintjl

Первый аргумент в вызове функции (foui) указывает поток, в который производится запись (вывод). Работа функции начинается с

50

просмотра слева направо управляющей строки "...". Если в управ­ ляющей строке нет ни одного формата, то после нее аргументов то­ же не будет. Символы в управляющей строке "..." могут быть трех видов.

1. Управляющие символы (в кодовой таблице первые 32 сим­ вола), примерами управляющих символов являются '\п\ \t\ '\0х7' и т.д. Если встречается управляющий символ, то он выполняет пред­ писанные ему действия. Например, '\п' вызовет переход в потоке ( в нашем случае в файле /Lout) на следующую строку, '\^' - выполнит печать пробелов в соответствии с используемым значением табуля­ тора (табулятору может соответствовать 2 - 1 6 пробелов, обычно че­ тыре или восемь) и т.д.

2. Форматы, которые начинаются с символа "%". Если встре­ тился формат, то из списка аргументов берется соответствующий ему аргумент, значение которого преобразуется в соответствии с типом формата и выводится в поток (в нашем случае в файл fJ.out).

!!! Число форматов в управляющей строке должно быть равно числу аргументов !!!

3. Остальные символы, которые называются печатными и вы­ водятся в выходной поток в том виде, как они изображены.

Работа функции заканчивается после просмотра управляющей строки до конца или при возникновении ошибки.

Формат имеет следующую структуру (в квадратных скобках указаны поля формата, которые могут отсутствовать):

% [флаг] [ширина__поля_вывода ] [ . точность] [префикс] тип

Допустимые значения полей "флаг", ".точность", "тип" и дей­ ствия, выполняемые перечисленными полями, приведены в табл. 9 - 11. Примеры их использования даны выше. Результаты действия форматов приведены в файле результатов/7.оwr, где условно с по­ мощью символа "^" показано расположение пробелов.

Поле "флаг" управляет выводом в поток ( табл. 9). В формате может быть указано несколько флагов одновременно, если они не противоречат друг другу.

Поле "ширина_поля_вывода" задает минимальное число выво­ димых символов. Это неотрицательное целое десятичное число. Ес­ ли "ширина" излишняя, то слева или справа, в зависимости от флага "-", поле вывода дополняется пробелами. Если ширина недостаточ­ на, то поле вывода увеличивается до требуемой длины, т.е. усечения выводимого данного не будет!

51

Табл. 9. Действие флагов форматирования

Флаг

Смысл

Значение по умолча­

-

Выравнивание результата по левому краю

нию

Выравнивание по пра­

+

заданного поля

вому краю

Вывод величины с указанием знака "+", если

Знак выводится толь­

 

величина принадлежит к типу со знаком

ко для отрицательных

 

 

величин

Пробел

Вывод пробела перед величиной, если это по­

Пробел не выводится

#

ложительное число со знаком

Префикс в указанных

Для форматов о, х или Х выводит перед числом

 

префикс 0, Ох или ОХ соответственно. Для

случаях не выводится.

 

форматов е, Е или/выводит число с десятич­

Десятичная точка

 

ной точкой.

выводится, если за

 

Для форматов g, G выводит число с десятич­

ней следует цифра.

 

ной точкой и предотвращает усечение лишних

Лишние нули

 

нулей.

усекаются.

"Точность"' - неотрицательное десятичное число, перед кото­ рым ставится точка (табл. 10). Обратите внимание, что "точность", в отличие от "ширины", может вызвать усечение выводимой величи­ ны или ее округление (для переменной с плавающей точкой).

Табл. 10. Действие поля формата ".точность"

Тип

Смысл

Умолчание

d, i, и,

Указывает минимальное число выводи­

Если точность равна нулю,

о, X, X

мых цифр. Если точность меньше, чем

или вообще опущена, или

 

надо, то число не усекается. Если точ­

стоит просто точка, то в ка­

 

ность больше, чем надо, то число допол­

честве точности берется еди­

Е, e,f

няется слева нулями.

ница.

Указывает число цифр, выводимых после

Точность равна шести. Если

 

десятичной точки (в случае усечения по­

она равна нулю или стоит

 

с л е д и ^ цифра округляется).

просто точка, то десятичная

 

 

точка не выводится.

g^G

Указывает максимальное число значащих

Выводятся все значащие

 

цифр выводимого числа.

цифры.

с

Ни на что не влияет.

Выводится символ.

S

Точность указывает максимальное число

Символы выводятся до тех

 

выводимых символов. Лишние символы

пор, пока не будет достигнут

 

строки не выводятся.

нуль-символ.

 

"Префиксы h, I, L, N,

F".

 

Префикс "/г" (sHort)

для типов d, i, о, х, А" (табл. 11) указывает

на тип аргумента short int,

а для типа и - на тип аргумента unsigned

short

int.

 

 

 

Префикс "/" для типов d, i, о, х, Jf указывает на тип аргумента

long

int,

для типа и - на тип аргумента unsigned long int, а для типов

е, Е, f, g,

G - на тип double.

52

\d, i

int

 

Табл. 11. Символы типа

 

 

Десятичное целое со знаком

 

и

int

 

Десятичное целое без знака

 

0

int

 

Восьмеричное целое без знака

 

X или

int

 

Шестнадцатеричное целое без знака с использованием

 

 

цифр "abcdef' или "ABCDEF"

 

/

float

 

Величина со знаком вида [-]dd.dd, где d - десятичная циф­

 

 

 

ра. Число цифр до точки определяется величиной числа, а

\Е, е

float

 

после - точностью.

 

 

 

 

Величина со знаком вида [-]d.ddddde[3HaK]ddd

или [-

 

 

 

ld.ddddd£[3HaK]ddd

 

 

 

G'S

float

 

Величина со знаком, выводимая в формате/или е, Е, в

 

 

 

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

с

int

 

сти

 

 

 

 

Отдельный символ

 

 

i

S

Строка

 

Символы выводятся или до достижения нуль-символа,

 

 

 

или после вывода количества символов, заданного в поле

п

 

 

"точность"

 

 

 

Указатель на

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

 

целое

 

ному м о м е т у . Эта величина присваивается переменной

 

 

 

inl с адресом в аргументе.

 

р

Указатель ти­

Выводит адрес, на который указывает аргумент, в виде

 

па void far

*

ХХХХ : УУУУ (сегмент : смещение) с использованием

 

 

 

шестнадцатеричных цифр верхнего регистра

 

 

Префикс "Z," для типов е, Е, f,

g,

G указывает на тип

аргумента

long

double.

 

для типов р, s,

п

 

 

 

Префикс

"F"

указывает на тип

аргумента

дальний указатель, а префикс 'W" для тех же типов - на тип аргумен­ та ближний указатель.

Файл результатов работы программы/7.ow/' имеет следующий вид (символ ^ обозначает пробел):

^i=''^'^^^00007^f=l. 500000Ei-02^1±=12^si=5

Обратите внимание, что функция print/ идентична функции* /print/, но вместо выходного потока, заданного первым аргументом, она по умолчанию использует предопределенный входной поток stdout. По этой причине в вызове функции/7гш(/'список аргументов начинается сразу с управляющей строки.

Функции ргш^/х^^гш^/'возвращают число выведенных символов при успешном завершении или EOF при ошибке. Однако это воз­ вращаемое значение обычно не контролируют.

53

2.4.4.Упражнения для самопроверки

1.Имеется следующий фрагмент Си-программы:

float

a,

 

Ь;

±nt

i^

J/

cha.r

cl

,

c2^ c3

±nt

= fscanfi

retcode;

"

%i

%3d

%c %c %c %f %f'\

retcode

stdin,

&i,

&j, &cl,

&c2r

&c3r

Sea,

&b

) ;

Строки исходных данных в файле с указателем stdin имеют следующий вид:

17 123456 2.4еЗ 112 14,5

Какие значения получат переменные retcode, а, Ь, i, J, cl, с2,

с31

2. Имеется следующий фрагмент Си-программы:

float

a;

 

 

±nt

^f

jr

c3;

char

cl,

c2,

±nt

retcode;

s[20];

char

c4,

c5,

Написать фрагмент программы, обеспечивающий чтение из файла f.dat, на магнитном диске следующих значений:

а

= 1.5

i

= 21

j

=

-12

cl

=

'в'

с2

=

'е'

сЗ

= 'с'

с4

=

'а'

с5

=

'н'

S

=>

"Прочита

иная-строка"

 

 

 

 

 

 

Как при этом будут выглядеть строки исходных данных в фай- n^f.datl

Предусмотреть контроль корректности значений, возвращае­ мых функциями библиотеки Си.

3. В программе имеются следующие переменные:

±nt

d

=

254;

 

float

f

=

1234.56;

символов";

char

*str

= "Строка

Используя, по возможности, только эти данные написать про-

54

грамму, выводящую в файл результатов/ile.out следующие строки (в них символ ^ обозначает местоположение пробела):

/•-/-254 " "-^"-^-^-"7 " " f

" " ^^2547

 

(^^^^^1234,5600)

" " (1234. 5

600''^^^^)

/Стр/^-^/м/

 

 

Ответы и решения для этих и последующих упражнений для самопроверки можно проверить в разд. 18.

3. т и п ы ДАННЫХ и и х АТРИБУТЫ

Вспомним еще раз определение программы по Н. Вирту:

"Программа = структуры данных + алгоритм'

В соответствии с приведенным определением начнем рассмот­ рение программы с данных. Данные характеризуются следующими атрибутами:

именами;

типами;

областями действия;

временем жизни.

Данные можно также инициализировать, то есть определять их начальные значения одновременно с их размещением в памяти. Так как в языках Си/С++ функции могут получать и возвращать значе­ ния, то важно также обсудить параметры/аргументы функций и воз­ вращаемые функциями значения.

3.1.Имена

Вязыках Си/С++ любая область памяти компьютера, которая может быть использована программой, называется объектом. Любое выражение, представляющее собой ссылку на объект, называется

адресным выраэюением или, короче, адресом^ именем.

Например, в рассмотренной выше программе объект "с/г" был определен следующим образом:

i n t main ( sroldL )

{

±nt

ch;

//

Объект с

именем

(адресом,

 

 

//

адресным

выражением) ch и типом

retuxm

0;

//

±nt

 

 

 

 

 

 

Имена объектов (например, ch) являются просто идентифика­ торами. Служебное слово int (INTeger, целый) указывает тип значе­ ния, которое будет содержать данный объект.

56

3.2. Типы данных

Тип данного указывает компилятору языка C++, сколько памя­ ти надо выделить для размещения объекта. Кроме того, он указыва­ ет компилятору каким образом надо интерпретировать значение, со­ держащееся в объекте. Тип объекта указывается в определении объ­ екта с помощью служебного слова (слов) - спецификации типа. Пре­ дусмотрено следующие основные (стандартные) типы данных

(табл. 12).

Табл. 12. Основные (стандартные) типы данных

Служебное слово

Размер в байтах

Назначение

char

1

Для символа (-128 ... +127)

wchart

2

Для символа из расширенного

int

 

набора (-32768 ... +32767)

Зависит от реализации

Для целого значения

bool

1

Для логического значения

float

 

(falsey true)

4

Для значения с плавающей точкой

 

 

(по абсолютной величине от

 

 

3.4Е-38до3.4Е+38)

Происхождение и перевод служебных слов:

char

(CHARacter:

буква,

 

симвом);

символьный

тип);

wchar_t

(wide

 

character

 

type: расширенный

int

(INTeger:

целое

число);

 

 

float

 

(число

с

плавающей

точкой).

 

 

Существуют четыре спецификатора типа (табл. 13), уточняю­ щих внутреннее представление и диапазон значений стандартных типов: unsigned (без знака), signed (со знаком), short (короткий), long (длинный).

Символьный тип (char). Под величину символьного типа от­ водится один байт, что позволяет хранить в нем любой символ из 256-символьного набора ASCII. Величины типа char применяются также для хранения целых чисел из диапазона +127 ... -128. По умолчанию тип char эквивалентен типу signed char. При использо­ вании типа unsigned char значения могут находиться в диапазоне О

... 255. Величины типа unsigned char применяются также для хране­ ния целых чисел из диапазона О ... 255.

Расигиренный символьный тип (wchart). Этот тип предна­ значен для работы с набором символов, для кодировки которого не­ достаточно одного байта (например, для набора Unicode). Символь­ ные и строковые константы с типом wchart записываются с пре­ фиксом L, например:

57

iinclude

<stdio.h>

 

 

int main (

void

)

 

 

{

 

 

 

 

wpr±ntf(

 

L"%s\n%c\n",

L"string",

L'A' ) ;

reburn

0;

 

 

 

}

 

 

 

 

В результате выполнения этой программы на экран выводятся следующие строки:

string

А

Табл. 13. Уточняющие спецификаторы типа

 

Служебное слово

Размер в байтах

Назначение

 

unsigned

char

 

1

Байт с неотрицательным

целым

unsigned

 

 

Зависит от реали­

значением (0 ... 255)

 

или

 

Для неотрицательногЬ целого

unsigned

int

 

зации

значения

 

short

или

 

 

2

Целое значение

 

short

int

 

 

 

(от -32768 до +32767)

 

unsigned

short

или

2

Беззнаковое короткое целое

unsigned

short

int

 

(0 ... 65535)

 

long

или

 

 

4

Целое длинное

 

long

int

 

 

 

(-231...+ (2^1 -1))

1

unsigned

long

или

4

Беззнаковое целое длинное

unsigned

long

int

 

(0...(232-1))

 

double или

 

8

Вещ. с двойной точностью

long

float

 

 

 

±1,7.10-'^..±1,7.10^'°'

 

long

double

 

10

Вещ. с повыщенной точностью

 

 

 

 

 

±3,4•10-'^•'^..±3,4.10"'^''

 

Целые типы. Размер типа int зависит от реализации, (для ше­ стнадцатиразрядного процессора - 2, для тридцатидвухразрядного - 4 байта). Диапазон значений для шестнадцатиразрядного процессора

- от -32768 до +32767,

для тридцатидвухразрядного процессора -

(-231...+ (231 _1))

 

Спецификатор short

перед именем типа указывает компилято­

ру, что под число требуется отвести два байта, независимо от раз­ рядности процессора. Спецификатор long означает, что целая вели­ чина занимает четыре байта. Таким образом, на шестнадцатиразряд­ ном процессоре эквивалентны типы int и short int, а на тридцатид­ вухразрядном - int и long int.

Внутреннее представление величины целого типа — целое чис­ ло в двоичном коде. При использовании спецификатора signed

58

старший бит числа интерпретируется как знаковый (О - положи­ тельное число, 1 — отрицательное). Спецификатор unsigned позволя­ ет представлять только положительные числа, поскольку старший разряд рассматривается как часть кода числа.

По умолчанию, все целочисленные типы считаются знаковы­ ми, то есть спецификатор signed можно опускать.

Логический тип (bool). Величины логического типа могут принимать только значения false и true, которые являются служеб­ ными словами. Внутренняя форма представления значения false — О (нуль). Любое другое значение интерпретируется как true. При пре­ образовании к целому типу true имеет значение 1.

Типы с плавающей точкой (floaty double и long double).

Внутреннее представление для типов с плавающей точкой состоит из двух частей — мантиссы и порядка. При этом величины типа float занимают четыре байта, из которых один двоичный разряд отводит­ ся под знак мантиссы, 8 разрядов под порядок и 23 под мантиссу. Мантисса — число большее 1,0, но меньшее 2,0. Поскольку старшая цифра мантиссы всегда равна 1, то она не хранится.

Для величин типа double, занимающих восемь байт, под поря­ док и мантиссу отводятся соответственно 11 и 52 разряда. Длина мантиссы определяет точность числа, а длина порядка — диапазон числа.

Спецификатор long перед именем типа double указывает, что под число отводится 10 байт.

Чтобы проверить размер памяти, выделяемой для объекта дан­ ного типа, можно написать программу, использующую операцию ''sizeof {size - размер). Значением этой операции является размер любого объекта или спецификации типа, выраженный в восьмиби­ товых байтах:

/ / См++. Программа печатает размеры объектов основных и

//производных типов

^include

<stdio.h>

//

Для

функций

 

ввода-вывода

 

 

int main (

void )

//

Возвращает

О при

успехе

 

 

{

(

"Тип объекта

Его

размер

в байтах

\п\п"

 

) ;

 

printf

;

 

prlntfC

(

"char

char

%d

\п",

slzeof(

(

char

)

)

 

) ) .

printf

"unsigned

%d

\ л " ,

sizeof

unslgnecL

cbar

printf

(

"int

 

%d

\ л " ,

sizeof

(

int

) )

;

)

)

/

printf(

 

"unsigned

 

%d

\ л " ,

sizeof(

 

unsigned

 

printf(

 

"short

short

%d

\n",

sizeof(

 

short

)

 

) ;

 

 

printf(

 

"unsigned

%d

\ n " ,

) ;

 

 

 

 

 

 

 

printf(

 

sizeof(

unsigned

short

)

 

long

)

)

/

 

 

"long

long

%d

\ n " ,

sizeof(

 

 

printf(

 

"unsigned

%d

\ л " .

 

 

 

 

 

 

 

 

59