Макрос WINAPI

Оскільки компілятор Visual C++ більше не підтримує ключових слів __pascal, __fortran та __syscall, їх дію рекомендується емулювати за допомогою описаних вище ключових слів __cdecl, __stdcall або __fastcall, а також відповідних опцій об’єднувача.

Для забезпечення сумісності з наявними програмами заголовний файл WINDOWS.H містить макрос WINAPI, який потрібно задавати там, де раніше потрібно було використовувати макрос PASCAL або ключові слова __far та __pascal.

 

3.10 Функції вводу – виводу мови C

Мова C++ успадкувала від мови програмування C бібліотеку стандартних функцій потокового вводу – виводу.

Під потоком розуміється процес вводу або виводу інформації з або в зовнішнє джерело інформації, що є розгорненою в часі послідовністю байтів.

Коли програма починає виконуватися, для неї автоматично відкриваються три стандартні потоки вводу – виводу, представлених в табл. 3.6.

Таблиця 3.6

Стандартні потоки вводу - виводу

Стандартний потік Призначення Пристрій за умовчанням
stdin Стандартний пристрій вводу Клавіатура
stdout Стандартний пристрій виводу Екран
stderr Стандартний пристрій видачі повідомлень про помилки Екран

 

Для того, щоб можна було використовувати будь-який з цих потоків та описані нижче функції, в програму повинна бути включена директива:

 

#include <stdio.h>

3.10.1 Форматний ввід - вивід для стандартних потоків вводу і виводу

Функції printf() для виводу і scanf() для вводу дають можливість при виконанні операцій виводу або вводу перетворювати числові величини в їх символьне представлення і назад, а також працювати з текстовою інформацією. Перетворення інформації здійснюється цими функціями під управлінням рядків форматів format.

3.10.1.1 Функція printf()

Функція printf() форматує і виводить на стандартний пристрій виводу stdout послідовності символів і значень під управлінням спеціального рядка – рядка формату. Прототип цієї функції наступний:

 

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

 

Як видно з приведеного прототипу, ця функціяє функцією з неоголошеним числом аргументів. Вона має один обов'язковий аргумент format – рядок формату, під управлінням якого здійснюється перетворення до символьного формату і вивід значень не одного, одного або декількох аргументів, розміщених за обов'язковим аргументом.

Функція повертає кількість виведених символів або негативне число, якщо під час виводу була виявлена помилка.

Рядок формату містить символи двох типів: звичайні символи, які просто видаються у вихідний потік, і символи специфікацій перетворень, кожна з яких послідовно задає перетворення і вивід чергового аргументу із списку фактичних аргументів функції printf().

Кожна специфікація перетворення в рядку формату починається з символу відсотка (%) і закінчується одним з символів y, що задає тип перетворення значення чергового аргументу, як це показано нижче:

 

%[flags] [width] [.] [{h | l | I | I32 | I64}]z

 

Символ типу перетворення z може бути одним з символів, перелічених в табл. 3.7.

 

Таблиця 3.7

Символи перетворення значень аргументів функції printf().

Символ перетворення z Трактування printf() типу значення аргументу Представлення аргументу на пристрої виводу
c int Виводиться як один однобайтний символ
C int Виводиться як один широкий (двобайтний) символ
d int Десяткове ціле число зі знаком
i int Десяткове ціле число зі знаком
о int Беззнакове вісімкове ціле
u int Беззнакове десяткове ціле
x int Беззнакове шіснадцяткове ціле з використанням букв "abcdef "
X int Беззнакове шіснадцяткове ціле з використанням букв "ABCDEF "
e double Число з плаваючою крапкою у форматі [ – ]d.dddd e [sign]ddd, де: d – десяткова цифра, dddd – одна або більш десяткових цифр, ddd – точно три десяткові цифри, знак – це + або –
E double Все, як у попередньому випадку, за винятком того, що замість символу ступеня e використовується символ E
f double Число з плаваючою крапкою в форматі [ – ]dddd.dddd, де dddd – одна або більше десяткових цифр. Число цифр перед десятковою крапкою залежить від величини числа, а число цифр після крапки визначається заданою точністю (поле специфікації precision)
g double Число з плаваючою крапкою виводиться в форматі f або e залежно від того, яке представлення займає менше місце при заданих значенні і точності. Формат e використовується, тільки якщо десятковий ступінь значення, що виводиться, менше –4 або більше або рівно заданій точності. Кінцеві нулі видаляються, а десяткова крапка з'являється, якщо за нею слідує хоча би одна значуща цифра
G double Все, як у попередньому випадку, за винятком того, що замість символу ступеня e використовується символ E (якщо він взагалі потрібен)
n Вказівник на integer За адресою, заданою аргументом, заноситься кількість символів, виведених в потік або занесених в буфер
p Вказівник на void Виводиться адреса аргументу як шіснадцяткове число
s String Виводяться символи (однобайтні) рядка аж до зустрічі кінцевого нульового символу або ж до вичерпання заданої точності (поле precision), залежно від того, що перше відбудеться
S String Виводяться символи (двобайтні) рядка аж до зустрічі кінцевого нульового символу або ж до вичерпання заданої точності (поле precision), залежно від того, що перше відбудеться

 

У специфікації перетворення не обов'язково, але можна задати один з префіксів символу перетворення (h, l, I, I32 або I64), щоб вказати розмір відповідного аргументу: h – короткий (short), l - довгий (long), (I або I32) – 32-розрядний, I64 – 64-розрядний. Префікс діє на аргументи цілих типів, а справжній розмір аргументу залежить також і від символу перетворення, що модифікується.

Необов'язкове поле flags специфікації перетворення задає один або декілька підряд розташованих символів-прапорів, що модифікують представлення аргументу на пристрої виводу. Ці символи-прапори перелічені в табл. 3.8.

Таблиця 3.8

Символи-модифікатори специфікації перетворення.

Символ-прапор Призначення Дія за умовчанням
- Вирівнювання вліво всередині поля заданої ширини Вирівнювання вліво
+ Видача знаку числа + або -, якщо аргумент має тип зі знаком (signed) Знак з'являється тільки для негативних значень.
Якщо цифра 0 стоїть перед заданим значенням поля ширини (width) в специфікації, до значення зліва додаються символи 0, щоб досягти потрібної ширини поля. Якщо одночасно задані символи 0 та -, 0 ігнорується. Символ 0 також ігнорується, якщо він заданий для цілочисельних аргументів (i, u, x, X, o, d). Заповнення нулями не проводиться.
Пробіл (' ') Якщо значення, що виводиться, позитивне, для знакових типів зліва виводяться пробіли; пробіл як символ-модифікатор ігнорується, якщо він заданий разом зі знаком +. Заповнення пробілами не проводиться.
# При використанні з перетвореннями o, x або X значення виводиться з префіксом 0, 0x або 0X відповідно. Префікс не виводиться
# При використанні з перетвореннями e, E або f, значення виводиться з обов'язковою десятковою крапкою. Десяткова крапка виводиться, тільки якщо за нею слідує хоча би одна цифра.
# При використанні з перетвореннями g або G, значення виводиться з обов'язковою десятковою крапкою, і при цьому кінцеві нулі не видаляються. Десяткова крапка виводиться, тільки якщо за нею слідує хоча би одна цифра. При цьому кінцеві нулі видаляються.
# З перетвореннями c, d, i, u або s цей символ-модифікатор ігнорується.  

 

Друге необов'язкове поле width специфікації задає ширину поля для виводу. Якщо задано, поле повинне містити ненульове десяткове ціле, що задає мінімальне число символів, які повинні бути виведені для представлення значення відповідного аргументу. Якщо ширина більше, ніж потрібно, необхідне число пробілів додається до виводу – справа або зліва, залежно від встановленого вирівнювання. Якщо значення ширини починається з цифри 0, тоді ця цифра використовуватиметься замість пробілу як символ-заповнювач.

Якщо задана ширина недостатня для виводу значення, виводяться всі символи, не дивлячись на задану ширину.

Якщо як ширина вказаний символ зірочки (*), тоді як значення ширини поля береться значення чергового аргументу функції printf(), а поточною специфікацією виводиться наступний за ним аргумент.

Третє необов'язкове поле специфікації precision (точність) задає після символу крапки (.) ненегативне десяткове ціле, яке вказує число символів, що виводяться, число десяткових цифр для чисел з плаваючою крапкою або число значущих цифр.

Якщо як точність вказаний символ зірочки (*), тоді як значення точності береться значення чергового аргументу функції printf(), а поточною специфікацією виводиться наступний за ним аргумент.

Нижче як приклад приведена програма, що використовує функцію printf():

 

#include <stdio.h>

int main()

{

char ch = 'h', *string = "computer";

int count = -9234;

double fp = 251.7366;

printf("Цілі формати:n"

" Decimal: %d Justified: %.6d Unsigned: %un",

count, count, count, count);

printf(" Decimal %d as:n Hex: %Xh C hex: 0x%x Octal: %on",

count, count, count, count);

printf(" Digits 10 equal:n Hex: %i Octal: %i Decimal: %in",

0x10, 010, 10);

printf("Дійсні числа:n %f %.2f %e %En", fp, fp, fp, fp );

}

 

В результаті роботи програми на екран буде виведено:

 

Цілі формати:

Decimal: -9234 Justified: -009234 Unsigned: 4294958062

Decimal -9234 as:

Hex: FFFFDBEEh C hex: 0xffffdbee Octal: 37777755756

Digits 10 equal:

Hex: 16 Octal: 8 Decimal: 10

Дійсні числа:

251.736600 251.74 2.517366e+002 2.517366E+002

3.10.1.2 Функція scanf()

Функція scanf() є аналогом функції printf(), але використовується для вводу інформації зі стандартного пристрою вводу в змінні програми. Функція scanf() здійснює більшість перетворень даних, описаних для функції printf(), але виконуваних у зворотний бік. Прототип цієї функції наступний:

 

int scanf(const char *format[, arg1]... );

 

Функція читає символи із стандартного потоку вводу stdin, інтерпретує їх відповідно до специфікацій перетворень, заданих аргументом форматування format, і записує результати інтерпретації в змінні, задані подальшими аргументами функції.

Всі аргументи, окрім, можливо, першого, повинні задаватися посиланнями на заповнювані з вводу змінні.

Функція повертає число успішно зчитаних і проінтерпретованих полів, не включаючи поля, для яких не виконувалося присвоювання змінним. Функція повертає 0, якщо жодній змінній не було присвоєно значення. Функція повертає EOF (-1), якщо при зчитуванні чергового символу була виявлена помилка, кінець файлу або ж символ кінця рядка.

Перший аргумент функції format звичайно містить специфікації перетворень і використовується для безпосередньої інтерпретації вхідної послідовності символів.

У рядок формату можуть включатися:

- пробіли, символи табуляції і переходи на новий рядок (так звані порожні символи); ці символи ігноруються;

- звичайні символи (окрім символу %); ці символи повинні співпадати з черговими не порожніми символами з вхідного потоку;

- специфікації перетворень, що складаються з символу %, можливо, символу заборони присвоювання *, можливо, числа, що задає максимальний розмір поля, і самого символу перетворення; самі символи перетворень, як і їх дія практично співпадають з відповідними символами перетворень для функції printf().

Так само як і для функції printf(), кожна специфікація перетворення послідовно управляє перетворенням чергового вхідного поля. Результат перетворення символів поля поміщається в змінну, задану черговим аргументом, якщо в специфікації немає символу заборони присвоювання *; якщо такий символ є, вхідне поле просто пропускається.

Вхідне поле при вводі визначається як рядок не порожніх символів, обмежений або порожніми символами, або розміром поля, якщо він заданий в специфікації. Функція scanf() у пошуку ввідних полів завжди проглядає вхідну інформацію до границі рядка, оскільки символ кінця рядка є порожнім символом.

Функція scanf() завершує свою роботу при вичерпанні рядка формату або при невідповідності вхідної інформації специфікаціям формату.

Нижче як приклад приведена програма, що використовує функцію scanf():

 

#include <stdio.h>

int main( void )

{

int i, result;

float fp;

char з, s[81];

result = scanf("%d %f %c %80s", &i, &fp, &c, s);

printf("The number of fields input is %dn", result);

printf("The contents are: %d %f %c %sn", i, fp, з, s);

}

 

Якщо на стандартному пристрої вводу задати послідовність символів:

 

71 98.6 z Byte characters

 

то на екран буде виведено:

 

The number of fields input is 4

The contents are: 71 98.599998 z Byte characters

3.10.2 Форматні перетворення в пам'яті.

Крім описаних функцій вводу формату і виводу scanf() і printf() в бібліотеці є дві функції sscanf() і sprintf(), призначені для роботи не з пристроями вводу і виводу, а з рядками в пам’яті. Профілі цих функцій наступні:

 

int sscanf(const char *buffer,const char *format[, arg1]... );

int sprintf(char *buffer,const char *format[, arg1]... );

 

Перша функція– функція sscanf() - здійснює ввід і перетворення інформації відповідно до заданого формату format не з пристрою вводу, як це робить функція scanf(), а з рядка символів в пам'яті, заданій першим аргументом цієї функції buffer.

Аналогічно, друга функція– функція sprintf() - проводить форматування і вивід інформації відповідно до заданого формату format в рядок в пам'яті buffer, заданій першим аргументом цієї функції, а не на пристрій виводу, як це робить функція printf().

3.10.3 Функції роботи з файлами

У стандартній бібліотеці вводу – виводу є ряд функцій для роботи з файлами. Це в першу чергу функції fopen() і fclose().

Функція fopen() використовується для відкриття файлу. Вона має наступний профіль:

 

FILE *fopen(const char *filename, const char *mode);

 

Перший аргумент filename функції fopen() задає ім'я файлу, що відкривається, а другий аргумент mode – режим відкриття файлу як один з рядків:

"r" – файл відкривається для читання;

"w" - файл відкривається для запису;

"a" - файл відкривається для запису в кінець файлу;

"r+" - файл відкривається для читання і запису; файл не повинен бути порожнім;

"w+" - порожній файл відкривається для читання і запису;

"a+" - файл відкривається для читання і запису в кінець файлу.

Функція fclose() забезпечує закриття файлу, розриваючи зв'язок між програмою і файлом. Ця функціямає профіль:

 

int fclose(FILE *stream);

 

Функція повертає 0, якщо файл був успішно закритий.

3.10.3.1 Форматний ввід - вивід для файлів

В бібліотеці для форматного вводу і виводу інформації не із стандартних пристроїв, а з довільних файлів є дві функції fscanf() і fprintf(). Профілі цих функцій наступні:

 

int fscanf(FILE *stream, const char *format[, arg1]... );

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

 

Обидві ці функції працюють так само, як і їх аналоги scanf() і printf(), але працюють не із стандартними пристроями вводу і виводу, а з потоковими файлами, які задаються першими аргументами функцій stream. Перед використанням файл повинен бути відкритий за допомогою функції fopen(); значення, одержане при відкритті файлу, повинне використовуватися як перший фактичний аргумент функцій fscanf() та fprintf().

Після закінчення роботи з файлом він повинен бути закритий за допомогою функції fclose().

3.10.4 Функції посимвольного вводу – виводу

Посимвольний ввод чергового байта виконують наступні функції:

 

int getc(FILE *stream);

int getchar();

 

Перша функціявводить і повертає черговий символ з потокового файлу stream, а друга – із стандартного пристрою вводу. Обидві функції повертають EOF (-1), якщо при вводі символу виявляється кінець файлу.

Вивід чергового символу виконують наступні функції:

 

int putc(int c, FILE *stream);

int putchar(int c);

 

Кожна з функцій виводить символ, заданий першим аргументом c у файл або на стандартний пристрій виводу, відповідно.

Для функцій getc() і putc(), що працюють з файлами, перед виводом першого символу у файл, цей файл повинен бути відкритий за допомогою функції fopen(). Після закінчення роботи з файлом він повинен бути закритий функцією fclose().