Лекции по увод в програмирането



страница10/16
Дата25.07.2016
Размер0.96 Mb.
#5224
ТипЛекции
1   ...   6   7   8   9   10   11   12   13   ...   16

14 ноември

16. Форматиран вход. Функция scanf.


Форматиран вход – от външен носител постъпва входен поток от символи; функцията, която ги обработва задава вида на данните като елементи от този входен поток и ги преобразува в променливи, представени в оперативната памет;
Функция scanf
Синтаксис:

scanf (“форматиращи параметри”, списък от аргументи);


scanf връща резултат от тип int; този резултат е броят на успешно въведените символи; връща EOF, ако има грешка при въвеждането или ако е въведен символ за край на файла;
форматиращите параметри при scanf съвпадат с параметрите от втори тип на printf; модификаторите, които се допускат са l, L - те променят очаквания тип на променливата (l променя int на long int, unsigned int на unsigned long int, double на float; L променя float на long double); друг модификатор, който се допуска е цяло число, записано непосредствено след %, което задава дължината на полето за въвеждане; по този начин на съответната променлива се присвоява число или низ от входното поле със зададена дължина

в рамките на един въведен елемент, а останалите въведени символи до разделителя се преобразуват съгласно следващата форматна спецификация и се присвояват на следващата променлива, ако няма следваща променлива те се игнорират;
въвеждана информация чрез scanf се присвоява на определени променливи; затова аргументите на scanf са адресите на съответните променливи;
адресът на една променлива се получава като пред името на променливата се постави символ &; изключение са имената на низовите променливи, тъй като те се разглеждат като символни масиви; името на един символен масив е адресът на първия елемент на този масив;
информацията, която се въвежда от клавиатурата се нарича входен поток от данни; този поток от данни е разбит на елементи, като разделители между елементите се използват празните символи (интервал, символ за нов ред, символ за табулация);
при форматна спецификация s, можем да използваме

модификатор *, който е записан непосредствено след % (преди дължината на полето за въвеждане); този модификатор задава игнорирането на частта от входния поток, за която се отнася съответната спецификация;


Важно: scanf не въвежда празни символи!!; винаги, когато въвеждаме масив от символи, трябва да се съобразяваме с това, че последният символ в масива трябва да е нулевият байт; тогава дължината на най-дългия възможен низ, записан в един символен масив е с едно по-малка от размерността му;
Примери:
float x, y; int z; unsigned t;

scanf(“%6f%f%3d%o”, &x, &y, &z, &t);


нека е въведен входния поток (_ означава интервал):

25.12345678 _ 12376


тогава на x ще се присвои 25.123, на y ще се присвои 45678; на z ще се присвои 123, на t ще се присвои 62 (76 в осмична = 62 в десетична бройна система);
нека е въведен входния поток:

25.4 _ 123 _ 12 _ 76

тогава на x ще се присвои 25.4 (независимо от това, че за x сме задали по-голямо поле, тъй като сме достигнали празен символ), на y ще се присвои 123, на z ще се присвои 12, на t ще се присвои 62;
char x, y, z;

scanf(“%c%c%c”, &x, &y, &z);

нека е въведен входния поток:

abc
тогава на x се присвоява ‘a’, на ‘y’ се присвоява ‘b’, на z се присвоява ‘c’;


нека е въведен входния поток:

ab
тогава на x се присвоява ‘a’, на ‘y’ се присвоява ‘b’, на z се присвоява ‘\n’;


char m[5], a[5];

scanf(“%s%2s”, m, a);


нека е въведен входния поток:

abc _ def


тогава: m[0]=’a’, m[1]=’b’, m[2]=’c’, m[3]=’\0’; a[1]=’d’, a[2]=’e’, a[3]=’\0’;
scanf(“%2s%*2s%s”, m, a);
нека е въведен входния поток:

abcdefgh


тогава: m[0]=’a’, m[1]=’b’, m[2]=’\0’; a[0] = ‘e’, a[1] = ‘f’, a[2] = ‘g’, a[3]=’h’, a[4]=’\0’;
Обобщение: за scanf се отнасят същите забележки като за printf; тя е неефективна и не се препоръчва нейната употреба, когато е възможно използването на по-прости функции;
17. Функции. Общ вид. Оператор return.
Една програма на C представлява съвкупност от функции;

Общ вид на една функция:


[ тип ] име на функцията (списък от тип и име на формални параметри)

{

тяло на функцията



}
типът на една функция е типът на резултата, който тя връща; функцията може да не връща резултат, ако на мястото на типа е записано void; ако типът е пропуснат, той по подразбиране се смята за int;
името на функцията е идентификатор; главната функция има име main, това е запазена дума и не може да се използва за име на потребителска функция;
тялото на функцията се състои от дефиниции на променливи и оператори;
резултатът от една функция се формира с оператор return;

синтаксис:

return (израз);

изпълнение: пресмята се израза, типа на израза се преобразува към типа на функцията и се прекратява изпълнението на функцията; ако функцията е void можем да използваме return без израз за да прекратяваме изпълнението на функцията; ако една функция е void, но в нея няма оператор return, тогава достигането до затварящата фигурна скоба на тялото на функцията е еквивалентно на изпълнението на оператор return;

скобите, които заграждат изразът не са задължителни;

функцията може да няма формални параметри, но скобите са задължителни;


концепция за скобите в различните версии на C:

    • в Кърнингън и Ричи C ако е зададено (), това означава, че не се уточнява броя на параметрите;

    • в ANSI C за да зададем функция без формални параметри между кръглите скобки трябва да има void

    • в C++ () задава функция без формални параметри



19 ноември

в тялото на една функция може да има няколко оператора return, но ще се изпълни само един или нито един тях;

Пример:

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

char toupper( c : char)

{ return ( (c>=’a’ && c<=’z’ )?c – ‘a’ + ‘A’:c ); }

намиране на n!

long int fact (int n)

{ long nf; nf = 1; int i;

for (i = 2; i<=n; i++)

nf = nf * i;

return nf;

}
18. Обръщение към функция.
За да се изпълни една функция, трябва да и се предаде управлението; това става чрез обръщение към тази функция;

функцията, която предава управлението е извикваща, а тази която приема управлението е извикана; една извикана функция може да извика друга функция;

Синтаксис на обръщението:

име_на_функцията (списък_от_фактически_параметри);
обръщението към функция може да се използва по два различни начина:


    • като операнд в израз; резултатът, който се връща от return замества операнда; ако обръщението към функцията е в операнд, тя обезателно трябва да връща резултат, в противен случай операндът ще има неопределена стойност;

    • обръщението към функцията завършва с точка със

запетая (;) – това обръщение се разглежда като оператор; естествено е в този случай функцията да е от тип void; ако тя не е от тип void резултатът от функцията не се използва (той се губи);
В общия случай фактическите параметри са изрази; въпросът за съответствие между тях и формалните параметри търпи развитие; в общия случай броят на фактическите параметри трябва да е равен на броя на формалните параметри; това не се спазва в случая, когато функцията е с променлив брой параметри; въпросът е дали типовете на фактическите параметри съвпадат с тези на формалните;

в Кърнингън и Ричи C се изисква съвпадение;

в ANSI C, C++ няма такова изискване, т.е. типа на фактическия параметър може да се различава от типа на формалния параметър; в такъв случай стойността на фактическия параметър се преобразува към типа на формалния параметър;

Реализация на обръщението – използва се програмен стек, разположен в частта от оперативната памет, разпределена за програмата;



    • пресмятат се фактическите параметри; проверява се дали типа на съответните формални параметри съвпадат с типа на фактическите параметри; ако някъде няма съотвествие се извършва преобразуване на стойността на фактическия параметър; в C фактическите параметри се пресмятат от дясно на ляво (за разлика от Pascal, където е от ляво на дясно) и стойностите им една по една се записват в стека; повечето компилатори имат опция с която се задава реда на пресмятане на фактическите параметри;

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

Ако променяме стойностите на формалните параметри, тогава стойностите на съответните фактически параметри не се променят; ако искаме да променяме един фактически параметър, трябва в обръщението към функцията да зададем неговия адрес;


Примери:
#include
char toupper( c : char)

{ return ( (c>=’a’ && c<=’z’ )?c – ‘a’ + ‘A’:c ); }


void main ()

{ char a, b;

int br;

printf (“Въведи символи: \n”);



br = 0;

do {


a = getchar();

b = toupper (a);

if (br==0)

printf (“Преобразуваната последователност от символи: \n”);

printf(“%c”,b);

br++; }


while (b != ‘\n’);

br--;


printf (“Брой обработени символи: %d\n”, br);

}

#include


long int fact (int n)

{ long nf; nf = 1; int i;

for (i = 2; i<=n; i++)

nf = nf * i;

return nf;

}
void main ()

{ int x;

printf (“Въведи x = “);

scanf (“%d”, &x);

printf (“x! = %ld\n”, fact(x) );

}
19. Прототипи на функция.
Прототипите на една функция са нужни за да може правилно да стане заместването на формалните с фактическите параметри; когато транслаторът реализира обръщение към функция, той трябва предварително да има информация за броя и типовете на формалните параметри за да знае дали стойностите на съответните фактически параметри трябва да бъдат преобразувани и към какъв тип; освен това, той трябва да знае какъв е типа на връщания резултат, за да може да прецени дали този тип трябва да се преобразува;

в програмите по-горе, компилаторът научава функцията преди да има обръщение към нея; ако обаче разменим местата на двете функции, компилаторът ще даде съобщение за грешка, тъй като той попада на обръщението, но няма необходимата информация;



именно затова в този случай трябва да запишем прототипа на функцията преди обръщението към нея (прието е, прототипите на функциите да се поставят непосредствено след директивите към препроцесора);

Синтаксис:



тип_на_функция име_на_функция (списък от формални параметри);

в прототипа на една функция можем да пропуснем имената на формалните параметри;

Примери:

char toupper (char c);

long fact (int);
Един заглавен файл съдържа (не само) прототипи на функции; по същата причина, за да се обръщаме към стандартна функция, след като не сме я описали, трябва да зададем нейния прототип, който е записан в заглавния файл; затова го включваме в началото на програмата;




Сподели с приятели:
1   ...   6   7   8   9   10   11   12   13   ...   16




©obuch.info 2024
отнасят до администрацията

    Начална страница