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

osn_progr_final

.pdf
Скачиваний:
37
Добавлен:
12.02.2016
Размер:
3.27 Mб
Скачать

int *arob=(int*)malloc(sizeof(int)*pow(n,m-1)); int *brob=(int*)malloc(sizeof(int)*pow(n,m-1)); if(m==2)

{

//добуток двовимірних матриць for(int i=0;i<n;i++)

for(int j=0;j<n;j++)

{

*(*c+i*n+j)=0; for(int k=0;k<n;k++)

*(*c+i*n+j)+=*(a+i*n+k)**(b+k*n+j);

}

(*c)+=n*n;

}

else

{

b=ctranspon(b,n,m);

//формування блоків for(int i=0;i<n;i++) for(int j=0;j<n;j++)

{

arob=a+i*pow(n,m-1); brob=b+j*pow(n,m-1); dobutok(arob,brob,c,n,m-1);

}

}

}

181

main()

{

int n,m,i,size;

printf(“введіть розмірність матриць та вимір-

ність(>=2)\n”)

scanf(“%d%d”,&n,&m);

size=pow(n,m);

int a=(int*)malloc(sizeof(int)*size);

int *b=(int*)malloc(sizeof(int)*size);

int sizerezult;/*кількість елементів результуючої матриці. Вона залежить від розмірності. Добуток двовимірних матриць-двовимірна, тривимірних-чотиривимірна, для всіх інших розмірність збільшується на два. Відповідно кількість елементів визначається як розмірність у степені вимірності*/

swich(m)

{

case 2: sizerezult=size; break;

case 3:sizerezult=size*n; break;

default: sizerezult=size*n*n;

}

int *cp,*c=(int*)malloc(sizeof(int)*sizerezult);

cp=c;

printf(“введіть матриці \n”)

printf(“матриця А:\n”);

for(i=0;i<size;i++) scanf(“%d”,a+i);

printf(“матриця B:\n”);

for(i=0;i<size;i++) scanf(“%d”,b+i);

dobutok(a,b,&c,2,3);

clrscr();

182

for(int i=0;i<sizerezult;i++)

printf("%d ",*(cp+i));

}

7.9 ВВІД-ВИВІД С. ФАЙЛИ ТА ПОТОКИ.

Як приклад реалізації концепції процедурного програмування можна розглянути систему вводу-виводу С. Система вводу-виводу С являє собою набір відповідних функцій, об’єднаних у бібліотеці stdio.h.

Для користувача файл, відкритий на зовнішньому рівні, являє собою послідовність байт, що зчитуються та записуються. Щоб підкреслити цю особливість , використовується термін “потік”. Коли програма починає виконуватись, відкриваються 5 стандартних потоків:stdin (пов’язаний з стандартним пристроєм вводу), stdout (вивід), stderr (пристрій помилок), stdprn (принтер), stdaux (порт) .

Ці потоки мають відповідно дескриптори 0,1,2,3,4. Відмітимо, що стандартні імена можна легко перепризначити:

FILE *f; stdin=f;

Всі функції вводу-виводу можна поділити на 3 класи:

1.верхнього рівня

2.консольного терміналу та порта

3.нижнього рівня

Єтакож функції для роботи з послідовним портом (com). Умовно їх можна віднести до другої групи.

7.9.1 Функції вводу-виводу верхнього рівня.

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

clearerr( )-скидання прапорців помилок, fclose( )-закриття потоку,

183

fcloseall( )-закриття всіх відкритих файлів,

fdopen( )-створення потоку для файла, відкритого раніше на нижньому рівні з використанням дескриптора,

feof( )-перевірка на кінець потоку, ferror( )-перевірка прапорців помилок, flush( )-скидання буфера потоку, fgetc( )-читання символа з потоку,

fileno( )-отримання дескриптора файла, пов”язаного з потоком, fgetchar( )-макрос читання з stdin (аналог fgetc(stdin)),

fgets( )-читання рядка з потоку , flushall( )-скидання всіх буферів, fopen( )-відкриття файла,

fprintf( )-форматований вивід в потік, fputc( )-запис символу в потік,

fputchar( )-макрос запису символу в stdout,

fputs( )-запис рядка в потік,символ нового рядка не дописується, fread( )-неформатоване читання,

freopen( )-повторне відкриття в новому режимі, printf( )-форматований вивід в stdout,

scanf( )-форматований ввід з stdin, fscanf( )-форматоване читання з потоку,

fseek( )-позиціювання файлового покажчика, fwrite( )-неформатований запис в потік,

getc( )-читає символ з потоку і переставляє файловий покажчик на наступну позицію,

getchar( )-макрос читання з stdin ( аналог getc(stdin)), gets( )-читання рядка з stdin,

getw( )-читання слова з потоку (цілого типу int), putc( )-макрос запису символу в потік,

putchar( )-макрос запису в stdout,

puts( )-записує рядок з нуль-символом в stdout і дописує символ нового рядка, putw( )-запис слова в потік,

rewind( )-встановлення файлового покажчика на початок файлу, setbuf( )-встановлює буфер для відкритого потоку,

setvbuf( )-встановлює буфер з рядом додаткових параметрів, sprintf( )-форматований вивід в рядок,

sscanf( )-форматований ввід з рядка,

tempnam( )-генерує ім”я тимчасового файлу в каталозі, tmpfile( )-створює тимчасовий файл,

184

ungetc( )-повертає символ в потік,

vfprintf( ), vsprintf( ), vfscanf( ), vscanf( ), vsscanf( ) –аналоги відповід-

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

Розглянемо деякі функції.

Функція printf(control, arg1, arg2, ...) визначає формат і друкує свої аргументи в стандартний вивід під керуванням рядка control. Керуючий рядок містить два типи об'єктів: звичайні символи, що просто копіюються у вихідний потік, і специфікації перетворень, кожна з яких викликає перетворення і друк чергового аргументу printf (див. довідник функцій).

Наступна таблиця демонструє вплив задання різних специфіка-

цій на друк "hello, world" (12 символів).

 

:%10s:

:hello, world:

 

:%10-s:

:hello, world:

 

:%20s:

:

hello, world:

:%-20s:

:hello, world

:

:%20.10s:

:

hello, wor:

:%-20.10s:

:hello, wor

:

:%.10s:

:hello, wor:

 

Функція scanf використовується для вводу даних і є аналогом printf. Функція scanf(control, arg1, arg2, ...) читає символи зі стандартного вводу, інтерпретує їх відповідно до формату, зазначеного в аргументі control, і поміщає результати в інші аргументи (див. довідник по функціях).

Наприклад, звертання int 1;

float x;

char name[50];

scanf("&d %f %s", &i, &x, name);

зрядком на введенні

25 54.32e-1 alpha

призводить до присвоювання i значення 25, x - значення 5.432 і name - рядка "alpha", належним чином закінченого символом ‘\ 0’. Ці три поля вводу можна розділювати довільною кількістю пропусків, табуляції і символів нових рядків. Виклик функції

int i; float x;

char name[50];

185

scanf("%2d %f %*d %2s", &i, &x, name);

звведенням

56789 0123 45a72

присвоїть i значення 56, x - 789.0, пропустить 0123 і помістить у name рядок "45". При наступному звертанні до будь-якої процедури вводу розгляд почнеться з букви а. У цих двох прикладах name є вказівником і, отже, перед ним не потрібно поміщати знак &.

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

scanf("%d", n); замість scanf("%d", &n);

Функції sscanf і sprintf, здійснюють аналогічні перетворення, але оперують з рядком, а не з файлом:

sprintf(string, control, arg1, arg2, ...) sscanf(string, control, arg1, arg2, ...)

Як і раніше, функція sprintf перетворить свої аргументи arg1, arg2 і т.д. відповідно до формату, зазначеним у control, але поміщає результати в string, а не в стандартний вивід. Звичайно, рядок string повинний бути достатньо великим щоб прийняти результат. Наприклад, якщо name - це символьний масив, а n - ціле, то

sprintf(name, "temp%d", n);

створює в name рядок виду tempnnn, де nnn - значення n.

Функція sscanf виконує зворотні перетворення - вона переглядає рядок string відповідно до формату в аргументі control і поміщає результуючі значення в аргументи arg1, arg2 і т.д. Ці аргументи повинні бути покажчиками. У результаті виклику

sscanf(name, "temp%d", &n);

змінна n одержує значення рядка цифр, що слідують за темр у name. Аналогічними є функції fprintf() та fscanf(), що працюють з фай-

лами і перший параметр мають змінні типу FILE*.

Функції getc( ), getchar( ), gets( ), getw( ) відповідно зчитують символ, рядок, слово з потоку, putc( ), putchar( ), puts( ), putw()-

записують.

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

186

позиція символу в буфері, спосіб використання файлу, читання чи запис, тощо). Користувач може і не знати всіх технічних деталей.

Приклад:

FILE *fopen(), *fp;

Тут fp є покажчиком на FILE і fopen повертає покажчик на FILE. Зверніть увагу, що FILE є ім'ям типу (це реалізовано як typedef). Фактичне звертання до функції fopen у програмі має вигляд: fp = fopen( name, mode);

Першим аргументом функції fopen є "ім'я" файлу, що задається у виді символьного рядка. Другий аргумент mode ("режим") також є символьним рядком, що вказує, як цей файл буде використовуватися. Допустимими режимами є: читання ("r"), запис ("w") і дописування в кінець ("a"). Також можна використовувати “r+”-відкриття існуючого файлу для читання та запису, “w+”-створення нового файлу для запису та читання, “a+”-відкриття для дописування в кінець чи читання. Якщо файл існує, то він перезапишеться.

Якщо ви відкриєте файл для запису, що не існує , то такий файл буде створений (якщо це можливо). Відкриття існуючого файлу на запис призводить до відкидання його старого вмісту. Спроба читання неіснуючого файлу є помилкою. Помилки можуть бути обумовлені й іншими причинами (наприклад, спробою читання з файлу, не маючи на те дозволу). При наявності якої-небудь помилки функція повертає нульове значення покажчика NULL (яке для зручності також визначається у файлі stdio.h).

При роботі з вже відкритими файлами найпростішими є функції getc і putc. Функція getc повертає наступний символ з файлу; їй необхідний вказівник файлу, щоб знати, з якого файлу читати. Таким чином, c=getc(fp) поміщає в "C" наступний символ з файлу-потоку, зазначеного за допомогою fp, і EOF, якщо досягнуто кінець файлу.

Функція putc putc(c,fp) поміщає символ "с" у файл fp і повертає "с". Подібно функціям getchar і putchar, getc і putc можуть бути макросами, а не функціями.

Функції getchar і putchar можуть бути визначені в терміналах getc, putc, stdin і stdout у такий спосіб:

#define getchar() getc(stdin)

#define putchar(с) putc(c, stdout)

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

187

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

#include <stdio.h>

main(argc, argv) /*конкатенація файлів*/ int argc;

char *argv[];

{

FILE *fp, *fopen();

if(argc==1) /*якщо немає аргументів, копіює стандартний ввод */

filecopy(stdin); else

while (--argc > 0)

if ((fp=fopen(*++argv,"r"))==NULL) { printf("can't open %\n",*argv); break;

} else {

filecopy(fp);

fclose(fp);

}

}

filecopy(fp) /*копіює файл fp у стандартний вивід*/

FILE *fp;

{

int c;

while ((c=getc(fp)) !=EOF) putc(c, stdout);

}

Функція fclose є зворотною за дією стосовно fopen; вона розриває зв'язок між вказівником файлу і зовнішнім ім'ям, встановлений функцією fopen, і вивільняє вказівник файлу . Більшість операційних систем мають деякі обмеження на число одночасно відкритих файлів, якими може розпоряджатися програма. Є й інша причина для застосування функції fclose до вихідного файлу - вона викликає звільнення буфера (при нормальному завершенні роботи програми функція fclose викликається автоматично для кожного відкритого файлу).

188

7.9.2 ФУНКЦІЇ ВВОДУ-ВИВОДУ КОНСОЛЬНОГО ТЕРМІНАЛУ ТА

ПОРТА

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

cgets( )-читання рядка з консолі cprintf( )-аналог printf

cputs( )-запис рядка на консоль getch( )-читання символу

getche( )-читання символу з ехо-друком kbhit( )-перевірка натискання клавіші putch( )-запис символу на консоль

ungetch( )-повернення останнього прочитаного символу з консолі для того, щоб він став наступним символом для читання

cscanf( )-аналог scanf

getpass( )-ввід з термінала пароля без ехо-друку

Консольний термінал та порт не можуть бути відкриті чи закриті перед виконанням вводу-виводу, тому fopen та fclose не використовуються.

Приклад:

#include <conio.h>

int main(void)

{

char *password;

password = getpass("Input a password:"); cprintf("The password is: %s\r\n", password); return 0;

}

7.9.3 ФУНКЦІЇ-ВВОДУ ВИВОДУ НИЖНЬОГО РІВНЯ

Функції-вводу виводу нижнього рівня не працюють з буферизованими чи форматованими даними. При роботі з файлами вони використовують дескриптори файлів. Основні функції:

close( )-закриття файлу creat( )-створення

189

dup( )-створює другий дескриптор файлу dup2( )-перепризначує дескриптор файлу eof( )-перевірка на кінець файлу

lseek( )-позиціювання файлового вказівника open( )-відкриття

read( )-читання

sopen( )-відкриття файлу в режимі розділення tell( )-повертає біжучу позицію вказівника write( )-запис

Приклад:

#include <sys\stat.h> #include <string.h> #include <fcntl.h> #include <io.h>

int main(void)

{

int handle;

char buf[11] = "0123456789";

/* змінює режим відкриття файлу з текстового на бінарний */

_fmode = O_BINARY;

/* створює двійковий файл для читання та запису */ handle = creat("DUMMY.FIL", S_IREAD |S_IWRITE);

/* записує 10 байт в файл */ write(handle, buf, strlen(buf));

/* закриває файл */ close(handle); return 0;

}

7.9.4 Приклади програм

Приклад 1 Написати програму, яка друкує номер і код введенного символа в вісімковому

та шістнадцядковому вигляді.

#include<stdio.h> void main(void) {char c;

printf(“введіть символ\n”); scanf(“%c”,&c); printf(“номер десятковий:”); printf(“%d\n”,c-‘0’);

190

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]