Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
часть4(измен).doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
297.98 Кб
Скачать

15.3.7. Функции ввода и вывода

Язык С имеет большой набор различных функций для организации эффективного ввода и вывода разных типов данных. В этом подразделе рассмотрим только две функции – scanf и printf из файла stdio.h, предназначенные для организации форматированного вывода и ввода данных.

Функция scanf имеет следующий синтаксис:

<форматированный ввод> scanf("<шаблон>",<список ввода>);

<список ввода> представляет собой последовательность разделенных запятыми указателей, значения которых являются адресами областей памяти соответствующих переменных. Функция предназначена для форматированного ввода с клавиатуры значений числового, символьного и строкового типов и типа указатель. В случае необходимости организации ввода значений переменных числового и символьного типа и типа указатель перед идентификатором переменной в <списке ввода> необходимо поместить знак операции адреса – &.

Например: float a,b

…..

тогда <список ввода> выглядит так &a,&b

*перед переменными строкового типа значек “&” не ставится,т.к они имеют смысл указатель

<Шаблон> задает допустимую последовательность символов логической строки окна результатов в режиме ввода с клавиатуры и может содержать символы двух типов:

1) вспомогательные символы, которые должны присутствовать в логической строке окна результатов в режиме ввода с клавиатуры и могут служить разделителями между значениями;

2) символы формата ввода, последовательность которых образует формат ввода.

Синтаксис формата ввода может иметь вид:

<формат ввода> %[<длина>][<модификатор>]<символ преобразования>

<Длина> – число в виде строки цифр, задающее длину поля для ввода. Если длина отсутствует, то длина поля для ввода равна длине значения выражения.

<Символ преобразования>, в частности, может быть следующим:

d или i – значение преобразуется к целому десятичному;

о – значение преобразуется к целому восьмеричному;

х или X – значение преобразуется к целому шестнадцатеричному;

с – значение преобразуется к символу;

s – значение преобразуется к строке символов;

е или E – значение преобразуется к действительному в формате с плавающей точкой;

f – значение преобразуется к действительному;

u – значение преобразуется к целому беззнаковому;

р –значение преобразуется к указателю (адресу).

<Модификатор> используется для уточнения преобразования, а именно:

h – значение преобразуется к типу short (используется вместе с символами преобразования d, i, о, u, х, Х);

l – значение преобразуется к типу long (в случае символов преобразования d, i, о, u, х, X) или double (в случае символов преобразования е, Е, f);

L– значение преобразуется к типу long double (используется вместе с символами преобразований е, Е, f).

Семантика вызова этой стандартной функции в системе программирования Turbo–C++ следующая.

Компьютер переходит в режим ожидания ввода данных с клавиатуры. В этом режиме пользователю предоставляется возможность ввести с клавиатуры значения переменных, идентификаторы которых перечислены в списке ввода. Последовательность вводимых с клавиатуры символов для визуального контроля выводится на дисплей, начиная с текущего положения курсора окна результатов, и может редактироваться в диалоговом режиме обычным образом. В качестве корректных значений допускаются только константы соответствующего типа. Режим ожидания ввода данных с клавиатуры завершается нажатием клавиши “ENTER”, и компьютер переходит в режим интерпретации введенной пользователем с клавиатуры логической строки. Результат интерпретации этой логической строки зависит от соответствия вводимых данных <Символу преобразования> и <Модификатору>, наличия в ней соответствующих <Шаблону> вспомогательных символов, а для символьного и строкового типа еще и от <Длины>. Результат интерпретации не всегда удается предсказать, но известно, что для числового типа пробелы, соответствующие вспомогательные символы являются разделителями. Если <список ввода> содержит идентификаторы нескольких переменных то возможен ввод данных по частям. В случае неправильной интерпретации выполнение программы не завершается досрочно с выдачей сообщения об ошибке.

Если после интерпретации значений всех переменных списка ввода, в логической строке остались не интерпретированные символы, то они игнорируются. Если все символы логической строки интерпретированы, но не всем переменным списка ввода присвоены значения, то компьютер переходит в режим ожидания ввода данных с клавиатуры, считая, что осуществляется ввод данных по частям. Пользователь должен набрать еще одну логическую строку, и после нажатия клавиши “ENTER” компьютер попытается интерпретировать ее как последовательность значений соответствующих переменных, которым еще не присвоены значения, и так далее. Последовательность символов очередной вводимой логической строки для визуального контроля выводится на дисплей с начала новой строки экрана.

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

Например, при вычислении значения scanf("%c,%f",s, x) для присвоения s=’a’, x=1.23456e-10 логическая строка окна результатов в режиме ожидания ввода данных с клавиатуры может иметь вид:

а,1.23456e-10

Функция printf имеет следующий синтаксис:

<форматированный вывод> printf("<шаблон>",<список вывода>);

<список вывода> представляет собой последовательность разделенных запятыми выражений, значения которых выводятся на экран дисплея в соответствии с форматами <шаблона>.

<Шаблон> содержит символы трех типов: вспомогательные символы, которые текстуально выводятся на экран дисплея, символы формата вывода и управляющие символьные константы. Синтаксис формата вывода может иметь вид:

<формат вывода> %[-][<длина>][.<точность>][<модификатор>]<символ преобразования>

Знак минус влияет на характер выравнивания значения в случае, когда длина поля для вывода больше длины значения выражения. А именно, соответствующее значение прижимается к левой границе поля для вывода (лишние позиции поля для вывода справа от значения заполняются пробелами), при его отсутствии – к правой границе поля (лишние позиции поля для вывода слева от значения заполняются пробелами).

<Длина> – число в виде строки цифр, задающее минимальную длину поля для вывода. Если длина отсутствует, то длина поля для вывода равна длине значения выражения, с учетом <точности>. <Точность> – число в виде строки цифр, которое интерпретируется следующим образом:

  • в случае использования <символа преобразования> в действительное значение <точность> задает число цифр после десятичной точки;

  • в случае использования <символа преобразования> в строковое значение – максимальное число символов строки, начиная с ее начала, которое нужно вывести;

  • в случае использования <символа преобразования> в целое значение – минимальное количество выводимых цифр. Если в значении меньше цифр, то оно выводится с необходимым числом ведущих нулей.

(Например, если символ преобразования «i»,а точность =5,а получилось число 123,то на экран будет выведено 00123)

Если длина значения больше длины поля для вывода, то длина поля для вывода автоматически увеличивается до длины значения. Исключением является случай вывода действительного значения. В этом случае дробная часть округляется по правилам симметричного округления до указанной <точности> и при выводе в формате с фиксированной точкой, в случае необходимости, длина поля для вывода увеличивается с целью сохранения всех цифр целой части. Если же при выводе действительного значения <точность> не указана, то дробная часть округляется до шести цифр.

<Символ преобразования> и <Модификатор> могут быть такими же, как в <формате вывода>. В случае использования в качестве символа форматирования f значение выводится в формате с фиксированной точкой.

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

\а – кратковременная подача звукового сигнала;

\n – переход на новую строку;

\t – горизонтальная табуляция;

\v – вертикальная табуляция;

\b – возврат курсора назад на одну позицию;

\\ – вывод символа \;

\' – - вывод символа ';

\" – вывод символа ";

\? – вывод символа ?.

Число выражений <списка вывода> должно совпадать с числом форматов вывода <шаблона>. Если выражений больше, то последние лишние выражения <списка вывода> игнорируются; если меньше, то последние лишние <форматы вывода> заполняются произвольными значениями.

Например, при вычислении значения printf("i=%ld; \n j=%6d, a=%6.2f.\n", i, j, a); при i=123456, j=456, a=86.531 в окно результатов будут выведены две строки:

I=123456;

J= 456, a= 86.53.

Массивы в Си.

Массив – это совокупность данных одного и того же типа, расположенных в памяти ЭВМ последовательно, непосредственно одно за другим. Каждый элемент массива имеет номер, или индекс, определяющий его место в массиве. Основными характеристиками массива являются: имя, размерность, тип его элементов.

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

Пример: int a [3][5][3], - элементы этого одномерного массива – 3 одномерных массива, элементы которых – 5 одномерных массивов.

<рез-е пам.>≡<идент. типа><идент.>[ [конст.]{[конст.]}]{,<идент.типа><идент.>[[конст.]{[конст.]}]}.

Константа-это целое положительное число,которое задает количество значений индекса. Индекс меняется от 0 до <константа>-1.

Выбор отдельного компонента массива осуществляется указанием идентификатора массива, за которым в квадратных скобках следует константа или переменная. Допустимо также использование индексного выражения. Индексное выражение должно давать значения, лежащие в диапазоне, определяемом при описании массива.

В программе одному массиву может быть присвоено значение другого массива, если их базовые типы и типы индексов совпадают.

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

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

Значения элементов массива хранятся в памяти ЭВМ последовательно, непосредственно одно за другим. Каждый элемент массива имеет номер, или индекс, определяющий его место в массиве.

Операция образования массива [ ] может быть использована при описании несколько раз. В этом случае массив называется многомерным. Например:

Mass[2][15];

Это двумерный массив или матрица. Первый размер в описании определяет количество строк, а второй – количество столбцов.

Элементы многомерных массивов располагаются в памяти ЭВМ таким образом, что наиболее быстро меняется значение самого последнего индекса, т.е. для рассмотренного примера:

Mass[0][0], Mass[0][1], …, Mass[0][14], Mass[1][0],…, Mass[1][14].

Количество оперативной памяти, занимаемой элементами многомерного массива, определяется произведением величин его размерностей на длину элемента массива(т.е. для данного примера 2*15=30 элементов всего). Во избежание ошибок не следует определять массивы, занимающие более одного сегмента оперативной памяти (более 64 кбайт).

Многомерные массивы представляют собой чистую абстракцию, поскольку память у ЭВМ одномерна, и многомерные массивы хранятся в ней в виде линейных последовательных значений.

Начальная инициализация.

<резер-е пам.> ≡ <идент. типа><идент.>[[конст.]{[конст.]}][=<значение>] {,<идент.>[[конст.]{[конст.]}][=<значение>]}.

<значение> = {<знач. эл. мас.>{, <знач. эл. мас.>}}.

Пример: int a[3][5][3] = {{{15, 1, 3}, {2, 3, 0}, …}, …}

int a[3][5][3] = {15, 1, 3, 2, 3, 0, …}, - допустима частичная инициализация, т.е. записать до 45 (в нашем примере) элементов, можно меньше, но не больше.

Массивы и указатели довольно тесно связаны между собой. Этот факт может быть подтвержден следующим тождеством:

x[i] == *(х + i). Работа в языке С с указателями, несомненно, покрывает все возможности работы с массивами. Если использование массивов делает программу более читабельной, то использование указателей делает ее более компактной и эффективной. Идентификатор массива имеет значение адреса и тип «указатель».

Если нам дан трехмерный массив float а[3][4][3] (действительного типа),то

*a ~ a[0]

*(a+1) ~ a[1] -тип указатель(т.е является адресом элемента

)

*(*a) ~ a[0][0] -тип указатель

*(*(*a)) ~ a[0][0][0] -действительный тип

a[i][j][k] ~ *(*(*(a+i)+j)+k)

Данный массив можно также инициализировать таким образом: float a[ ][4][3] Т.е самая левая размерность многомерного массива может не указываться. Это объясняется тем, что первый индекс программа считает сама, как смещение относительно адреса а. НО во второй и последующих квадратных скобках размерности указывать обязательно, т.к программа не сможет сформировать адрес, если не знает, из скольких элементов состоит массив массивов

Для многомерных массивов также можно использовать указатели. Указатель будет ссылаться на первый элемент первой строки. Увеличи­вая затем его значение на единицу, мы будем последовательно переме­щаться по элементам строк. Если, например, в программе имеются опи­сания двумерного массива и указателя:

int z[3][4], *р;

то после присвоения

p = z

следующие элементы будут эквивалентными:

р == &z[0][0]

р + 1 == &z[0][1]

р + 2 == &z[0][2]

Так как двумерный массив - это массив массивов, то можно исполь­зовать имена строк z[0], z[l], z[2], которые являются указателями на пер­вые элементы этих строк.

Строки.

Строки в С обрабатываются как массивы элементов типа char. Функции для работы со строками можно найти в модуле string.h.

“\0”, - символ конца строки; его необходимо использовать, так как, не найдя его система будет заполнять строку всякой «ненужной информацией».

Пример: char s[10], - можно рассматривать как строку из 9-ти элементов, так как один символ – “\0”.

Со строками можно работать, как и с обычными массивами, т.е. возможна и начальная инициализация: char s[10] = {‘0’, ‘1’, …, ‘8’, ‘\0’}.

getchar(), - функция, считывающая один символ из вводимых.

(ввод строки): for (I=0; I<9&&(S[I]=getchar())!=’\n’; I++)

S[I]=’\0’

Для ввода строк символов может быть также использована функция gets(<идент.>) (ее прототип находится в файле stdio.h).

Если string - массив символов, то ввести строку с клавиатуры можно так:

gets(string);

(ввод оканчивается нажатием клавиши <Enter>).

Для вывода строк символов помимо потокового и форматированного вывода может использоваться функции puts(<идент.>) (ее прототип находятся в файле stdio.h). следующим образом:

puts(string);

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

Функции работы со строками:

  1. strlen(<выр.>), - определяет длину строки, без учета служебного символа ‘\0’.

Используется значение самой функции.

  1. strcpy(<идент.>,<выр.>), - <идент.> и <выр.> должны быть строкового типа; после вызова этой функции идентификатору присваивается значения выражения.

Здесь используется побочный результат вызова ф-ии(т.е. идентификатор принимает значение выражения), значит само значение ф-ии НЕ используется

  1. strcat(<идент.>, <выр.>), - склейка строк, т.е. после вызова данной ф-ии к значению идентификатора присоединяется значение выражения.

Значение ф-ии здесь НЕ используется

  1. strcmp(<выр. 1>, <выр. 2>), - посимвольное сравнение строк слева направо.

Из кодов ASCII символов строки <выражения1> вычитаются коды символов строки <выражения2> .Данная функция возвращает значение ноль, если строки равны(т.е. все коды символов совпали) ; отрицательное значение, если строка <выр.1> меньше строки <выр.2> и положительное значение если строка <выр.1> больше строки <выр.2>.

Здесь используется само значение функции

Копирование части строки S с позиции M в количестве N:

for (I=0; I<N; S1[I] = S[M+I-1], I++);

S1[I] = ‘\0’;

Удаление символов из строки S с позиции M в количестве N:

K=strlen(S);

for (I=0; I<K-N-M+2; S[M+I-1]=S[M+N+I-1], I++);

Вставка в строку S выражения с позиции M:

for(I=0; I<strlen(S)-M+2; S1[I]=S[M+I]-1, I++);

S[M-1]=’\0’;

strcat(S,<выр.>);

strcat(S, S1).