Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по С++.doc
Скачиваний:
27
Добавлен:
20.08.2019
Размер:
2.26 Mб
Скачать

1) Спецификации формата, которые определяются символом % - для выде­ления, контроля и преобразования соответствующих им введенных значений;

2) Любые символы, которые могут быть во входном потоке и которые надо игнорировать:

3) пробельные символы: пробел, символ табуляции (\t), символ новой стро­ки \n и возврата каретки \r

Например, если а строке формата появился символ пробел (_), то с этого момента ввод завершается и из входного потока считываются и игнорируются символы '_' до первого не пробела. Если в строке формата встретились непробельные символы, например последовательность латинских букв и цифр (за исключением символа %), то из входного потока такие же символы считыва­ются и игнорируются.

Появление в строке формата символа % определяет начало формата для очередного аргумента. Формат предписывает функции типа scanf прочитать и преобразовать очередные символы входного потока в значение типа, опреде­ленного форматом. Значение выделяется из входного потока, преобразуется в соответствии с форматом, контролируется на соответствие типу переменной аргумента и присваивается переменной, адрес которой указан в соответствую­щем формату элементе списка аргументов. Если выделенное значение не соответствует типу формата, результат ввода не определен. Это может произойти, например, при вводе форматом "%d" значения для переменной типа float или бук­ва. Сообщение при этом не выдается и продолжается выполнение программы.

При несоответствии типов форматов типам аргументов вводимых значений программа завершается аварийно на этапе ее выполнения. Во время трансля­ции эта ошибка не обнаруживается. Это может быть, например, при попытке форматом %f ввести значение для переменной целого или строчного типа. При этом выдается сообщение:

scanf: floating pointformats not linked

Abnormal program termination

Что означает:

scanf: формат для плавающей точки недопустим

Аварийное завершение программы

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

1) первого пробельного символа (кроме ввода по формату с);

2) Первого символа, который не соответствует формату (например, буква или пробел после выделения числа); .

3) Заданной длины поля вводимого значения, если она определена в формате.

Под пробельными символами понимаются символы: пробела ( ), табуляции (\t), новой строки (\n) и возврата каретки (\r).

Формат (спецификация формата) не содержит пробелов и имеет следующую форму:

% [ * ] [ w ] [ F | N | h | l | L ]

где: % - признак начала формата;

* - запрет присваивания аргументу (переменной) введенного значения;

w - width - ширина - десятичное целое, определяет максимальный, размер поля вводимого значения;

F|N - определяет тип адресации аргумента (Far, Near);

h|l|L - определяет уточнение типа аргумента вводимого значения, то есть вариант типа:

I или L - long или double; .

h - short;

тип - это символ типа формата вводимого значения.

В квадратных скобках указаны необязательные элементы формата.

Примеры допустимых типов форматов ввода приведены в таблице ниже.

Тип формата

Интерпретация значения, выделенного при вводе

Тип аргумента –указатель на

d

десятичное целое

int

D

“ — ”

long

o

восьмеричное целое

int

O

“ — ”

long

x

шестнадцатеричное целое

int

X

“ — ”

long

i

десятичное, восьмеричное или шестнадцатеричное целое

int

u

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

unassigned int

U

“ — ”

unassigned long

e, E

число с плавающей точкой

float / double

f, F

число с фиксированной точкой

float / double

c

символ, в т. ч. пробел

char

s

строка

char

n

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

int

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

Спецификаторам d, i, o, u, х может предшествовать:

- h - если аргументы - указатели на тип short int;

- l - если аргументы - указатели на тип long int/

Спецификаторам е, E, f, F может предшествовать:

- I - если аргументы - указатели на тип double (а не float)

- L- если аргументы - указатели на тип long double.

Значение с плавающей точкой, вводимое по форматам е, E, f, F во входном потоке, может содержать число с фиксированной точкой и (необязательно) -экспоненту - символ е или Е, за которым следует порядок. Например, допусти­мы: 123 1.23 1.23е-2 1.23Е-2

С помощью формата с вводится один очередной символ, в том числе про­бельный. Чтобы ввести строку из w символов, включающую и пробелы, и сим­вол конца строки (\n), надо использовать формат %wc. Если при вводе строки форматом %wc введен символ перехода на следующую строку, то при выводе этой строки, он вызовет переход на следующую строку, на которую и будет продолжен вывод.

- С помощью формата s вводится строка символов до очередного пробела; после последнего символа введенной строки помещается символ \0 - конца строки. Символы перехода на следующую строку (\n) считываются наравне с другими символами. Для чтения следующего непробельного символа можно воспользоваться форматом %1s.

С помощью формата %*ws можно пропустить очередное поле с w непробельными символами; а с помощью формата %*10с будут пропущены очередные 10 любых, в том числе пробельных, символов входного потока. Для таких форматов аргументы не требуются. Примеры форматов:

scanf ( “%d%ld%f%c%12c%s%*c”, &I, &k, &b, str1, str2 ) ;

Для формата %n из входного потока не производится чтение очередного значения для очередного аргумента, но значение в ОП, соответствующее оче­редному аргументу, может быть искажено.

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

scanf ( "а = %d”, &а ) ;

Во входном потоке может быть: а = 123.

При выполнении ввода символы а = из входного потока игнорируются, а в качестве значения переменной а введется значение 123.

Далее приведен пример программы для ввода значений различных типов из файла.

(пример старой версии)

# include <stdio.h>;

FILE *f;

void main ()

{ int a, e ;

float b, d; // ft – инициализированная строка форматов:

char c[7], g, * ft = “ a = %d b = %f c = %s%f%d%c”

f = fopen ( “8scanf.dat” , “r” );

fscanf (f, ft, &a, &b, c, &d, &e, &g);

fclose (f);

}

Содержимое файла “8scanf.dat” – с исходными данными:

а = 123, в = 2.5, с = asdfg 3.7 25k

В приведенном примере программы строка форматов включает подстроки: а = , Ь = , с = . Эти подстроки при считывании данных из файла игнорируются. В результате выполнения программы переменные списка аргументов функции fscanf получат следующие значения: а = 123, в = 2.5, с = “asdfg”, d = 3.7 e =25, g = ‘k’.

Пример программы для пересылки значений различных

типов из строки с помощью функции sscanf

(пример старой версии)

void main ()

{ char str [ ] = “Из втой строки читаются: "

"целое: i = -123, "

"шестнадцатеричное целое: j = 0x10, " "целое без знака: ui - 65535, " "значение с плавающей точкой: f = -123е-2, " "несколько строк и символов . "

// n1 - количество введенных значений

int I, j, n1;

unassigned ui;

float f;

{char s1[30], s2[30], c1, c2;

n1 = sscanf (str, “%*25c %*6s i = %d, %*29c%i, %*21c%u, %*33c%f, %s%s %c %*8s%c”, &i, &j, &ui, &f, s1, s2, &c1, &c2 );

printf ( “\ni = %d, j = %i, ui = %u, f =%.3f, “

“\ns1 %s, s2 = %s, c1 = %c, c2 = %c n1 = %d\n”,

i, j, ui, f, s1, s2, c1, c2, n1 ) ;

}

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

i = -123, j = 16, ui = 65535, f = -1.230, s1 = несколько, s2 = строк, с1 = и, с2 = . , n1 = 8

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

Например:

fgets (str, 50, fid) ; // ввод данных в строку str

sscanf (str, “%d%f%6c%f”, &a, &b, st, &c) ; // распаковка

В силу определенных особенностей функций sscanf и fscanf возможны слу­чаи, когда значения типа float или double вводятся неверно, например, в эле­менты массива арифметических данных или в элементы массива структур. В этом случае избежать ошибки можно, используя промежуточную скалярную переменную соответствующего типа (float или double). Надо сначала ввести значение в эту скалярную переменную, а затем переслать ее в элемент масси­ва структур. Пример фрагмента программы для ввода значений из файла в строку с последующей 'распаковкой' этой строки приведен на далее.

(пример старой версии)

#define PR struct data;

PR {int nb, gv; char ts [8], float gr; );

float skl; //skl - скаляр

PR s[5]; //s – массив структур типа PR

void main ()

{ ... for ( i = 0 ; i <= 5; i++ )

{fgets ( str, 55, fid ) ;

sscanf ( str, “%d%d6c%f” ,

&s[ i ] . nb, &s [ i ].gv, s [ i ].ts, &skl); // - ввод значения в skl

s [ i ].gr = skl; // - пересылка skl в s [ i ].gr - элемент массива s

...}

В этом примере с помощью функции sscanf значение типа float вводится сначала в скалярную переменную skl, а затем пересылается в s [ i ].gr - в элемент массива структур. Для других типов данных этого не требу­ется.

Функции для форматного вывода данных

Форматный вывод данных осуществляется с помощью функций printf, fprintf, sprintf. Правила их использования идентичны.

Прототип функции printf:

int printf ( char * format [ , arg ... ] ) ;

Функция fprintf выводит в стандартный выводной поток stdout (на экран) значения, определенные ее аргументами. Функция имеет переменное количе­ство параметров. Значение первого параметра format определяет адрес строки, которая управляет интерпретацией выводимых значений. Аргументы опреде­ляют имена переменных, значения которых должны быть выведены.

Возвращаемое значение. - количество выведенных значений.

Прототип функции fprintf:

int fprintf ( FILE * stream, char * format [, arg ... ] ) ;

Функция выводит данные в выводной поток stream. Прототип функции sprintf:

int sprintf (char * str, char * format [, arg ... ] ) .

Функция sprintf осуществляет вывод не в файл, а в строку str, расположен­ную в ОП. Таким образом, производится пересылка значений аргументов в строку в соответствии с форматами.

Строка format (описания форматов) обрабатывается слева направо. Первый формат соответствует первому аргументу, второй - второму и т. д. Если аргу­ментов больше, чем форматов, лишние аргументы игнорируются. Если количе­ство форматов больше количества аргументов, результат будет неопределен­ным.