Четене и писане във файл на C++ - първо писмо до позната студентка

Върху статията се работи

Здравейте госпожице Радева,

Ще се опитам да обясня операторите, които отговарят за четене и писане на различни видове данни във файл на С++, доколкото съм ги разбрал.
Дефинирана е структурата
1 struct strPerson{
2    char EGN[11];
3    char Name[20];
4    string str_egn;
5    string str_name;
6 };

Заглавната част на програмата трябва да изглежда така:
1 #include "stdafx.h"
2 #include "string"
3 using namespace std;
Номерата на операторите са дадени за удобство и разбира се не се изписват в програмата.
Краят на поредицата от символи се определя с последен символ (char)0.
Така, че в EGN[11] значимата информация е в първите 10 символа - с индекси от 0 до 9.
Последният EGN[10] трябва да е (char)0.

Писане


0 void WritePr(){
1	FILE *pFile;
2	int i=0,nWr=0;
3	if( (pFile=fopen("Stancho.txt","wb")) !=NULL){
4		nWr=fwrite((void *)&nInputsG,sizeof(int),1,pFile);
5		printf("InputsG=%d",nWr);
6		for(i=0;i "по-малко от"  nInputsG;i++){
7			nWr=fwrite((void *)&i,sizeof(int),1,pFile);
8			printf("i= %d",nWr);
9			nWr=fwrite(arrPersonsG[i].EGN,sizeof(char),9,pFile);
10		printf("EGN= %d",nWr);
11		nWr=fwrite((void *)&arrPersonsG[i].Name,sizeof(arrPersonsG[i].Name),1,pFile);
12		printf("Name= %d",nWr);
			
14		nWr=fwrite(arrPersonsG[i].str_egn.c_str(),arrPersonsG[i].str_egn.length(),1,pFile);
15		LengthOfString=arrPersonsG[i].str_name.length();
16		nWr=fwrite((void *)&LengthOfString,sizeof(int),1,pFile);
17		nWr=fwrite(arrPersonsG[i].str_name.c_str(),LengthOfString,1,pFile);

18	}
19	fclose(pFile);
20	}
21	return;
22 }


"по-малко от" е записано така, защото моят "браузер" приема знака за команда.
1 FILE *pFile; дефинира указател към файл за по-нататъшно използване.
Процедурата 3 конструира този указател и проверява неговото съществуване.
Ако съществува във файл в него се записват някои неща в поредицата команди от 3 до 14.
Stancho.txt трябва да е съществуващ файл в работния проект.
15 затваря файла.
Командата 4 nWr=fwrite((void *)&nInputsG,sizeof(int),1,pFile); записва цялото число nInputsG във файла Stancho.txt.
Това става чрез указателя на променливата който е от типа (void *), защото указателите също имат типове.
(void *) е тип универсален указател.
Втория аргумент sizeof(int) определя броя на записянете байтове а третият -1 броят на записаните екземпляри с този размер.
В случая се записва едно цяло число с размер 4 байта.
Определя се и къде ще се записва, което става с четвъртия аргумент.
Процедурата fwrite((void *)&nInputsG,sizeof(int),1,pFile) връща цяло число- броят на записаните байтове.
Този брой се присвоява на променлисата nWr, която впоследствие извеждаме, за да се уверим, че нещо се е случило.
Между другото, чрез режима "постъпково изпълнение" (Debug) може да се извърши проверка за грешки при изпълнение на програмата.
Командата 11 nWr=fwrite((void *)&arrPersonsG[i].Name,sizeof(arrPersonsG[i].Name),1,pFile); записва arrPersonsG[i].Name, която е от тип char[20]. Записът на стринговете се извършва с операциите:
14		nWr=fwrite(arrPersonsG[i].str_egn.c_str(),arrPersonsG[i].str_egn.length(),1,pFile);
15		LengthOfString=arrPersonsG[i].str_name.length();
16		nWr=fwrite((void *)&LengthOfString,sizeof(int),1,pFile);
17		nWr=fwrite(arrPersonsG[i].str_name.c_str(),LengthOfString,1,pFile);

Функцията c_str() дава поредицата от символи в стринга със завършващ знак за край - (char)0.
length() връща дължината на стринга.
Единният граждански номер е с фиксирана дължина - 10 символа и затова дължината
му не е необходимо да се съхранява във файла.
С имената обаче не е така и дължината им ще изписваме непосредствено пред тях.
Това става с оператор 16.
Етикетът изисква файлът да се затвори, коего става с 19 fclose(pFile);

Четене

То се прави съглсувано със записа и двете процедури се тестват едновременно, последователно и съгласувано.
0 void ReadPr(){
1	FILE *pFile;

	char ch[100];
	ch[100]=(char)0;

2	int i=0,j=0,nRr=0;
3	if( (pFile=fopen("Stancho.txt","r")) !=NULL){
4		nInputsG=0;
5		nRr=fread((void *)&nInputsG,sizeof(int),1,pFile);
6		printf("InputsG=%d",nRr);
7		for(i=0;i"по-малко от"nInputsG;i++){
8			nRr=fread((void *)&j,sizeof(int),1,pFile);
9			printf("%d %d",nRr,j);
10			nRr=fread(arrPersonsG[i].EGN,sizeof(char),9,pFile);
11			printf("EGN= %d",nRr);
12			nRr=fread((void *)&arrPersonsG[i].Name,sizeof(arrPersonsG[i].Name),1,pFile);

14			nRr=fread((void *)&ch,sizeof(char),10,pFile);
15			for(j=0;j"по-малко от"10;j++) arrPersonsG[i].str_egn +=ch[j];
16			nRr=fread((void *)&LengthOfString,sizeof(int),1,pFile);
17			nRr=fread((void *)&ch,sizeof(char),LengthOfString,pFile);
18			for(j=0;j"по-малко от"LengthOfString;j++) arrPersonsG[i].str_name +=ch[j];

19		}
20		fclose(pFile);
21	}
22	ShowPr();
23	return;
24 }


14 прочита точно 10 символа а 15 ги поставя в променливата str_egn.
16 прочита дължината на стринга, който предстои да бъде прочетен.
Нататък операциите са аналогични.
Мисля и горещо се надявам че всичко е ясно.
Госожице Радева, пожелавам Ви успхи от всякакво естество.
Пожелавам Ви също здраве, щастие и всичките техни производни, както се изрази един професор.

Пълният текст на програмата е тук

Статията е преведена от руски език от страницата на Елисавета Калинина .        Написана е от Лари Филипс.

Сумата на реда на реципрочните квадрати

Leonhard Euler
Леонард Ойлер
(1707 - 1783)

В историята на математиката има много случаи, когато някой е поставял задача пред математическото общество като цяло и тази задача оставяла нерешена в продължение на десетилетия. Или дори векове. Често, в процеса на решаване на такава задача, са се появявали нови области в математиката. Тази статия е разказ за един такъв случай - така наречената "Базелска проблема" (задача за сумата на реципрочните квадрати, Базел е град в Швейцария), поставена за първи път през 1644г.

Тя се е съпротивлявала на всички опити за решение, докато младият математик Леонард Ойлер през 1734 г. не отрил отговора. Както ще види читателят, откритието е изключително изобретателно, макар, че нивото на математическите методи не надминава знанията от началния курс по алгебра.

Задачата

Базелската проблема се формулира просто: Трябва да се намери сумата на реда         Реда на реципрочните квадрати
Както при всички безкрайни редове възниква въпросът за сходимостта.
Това, че членовете стават безкрайно малки не е достатъчно за това.
Например реда         Хармоничен ред има безкрайна сума, т.е. е разходящ, въпреки че членовете му стават безкрайно малки
( този ред се нарича хармоничен и доказателството на неговата разходимост е приведено по-нататък).

За реда на реципрочните квадрати било показано, че е сходящ и сумата му е по-малка от 2, но каква точно било известно.

Два съперника и техния учител правят безуспешни опити

Първи се опитали да решат Базелската проблема братята Якоб (1654-1705) и Йохан (1667-1748) Бернули. Проблемата била наречена така, защото Базел бил родния им град. Братята били сред първите математици, които разбрали и започнали да прилагат новото смятане , за което научили от Готфрид Лайбниц (1646-1716) -един от неговите автори. Към 1690 г. те се считали за водещи математици в Европа.

За съжаление по това време те станали ожесточени и непримирими съперници помежду си, изглеждало, че изпитват убийствена ненавист един към друг. Всеки един от тях бил в сътояние да лъже, интелектуално да краде, да плагиатства, ако това би способствало да изглежда по-добър от другия. Съперничеството не престанало даже след смъртта на Якоб. Йохан се е опитвал да публикува някои работи на брат си от свое име, и даже е отказал да помогне за публикуването на трактат на му по теория на вероятностите, страхувайки се, че това ще подрони собствения му авторитет.

Може би Йохан е бил просто ... лош човек, след като по-късно, когато собственият му син - Данаил спечелил математическа награда , (за която се е борил и баща му), той го изгонил от дома си и го лишил от наследство.
(бележка на преводача:
По ирония на съдбата, сега тази фамилия се приема от математическия свят общо, без да се различават много-много баща от синове и внуци. )

Дълги години братята се борили със задачата,
(което вероятно и частично, е било породено от желание да се победи съперника) но нямали успех.
Лайбниц също работил над този проблем в продължение на години но не получил никакъв резултат.

Появата на Ойлер

Леонард Ойлер (1707-1786), бил родом от Базел и се случило така, че баща му познавал Йохан Бернули. Когато Леонард станал на 14, баща му помолил Йохан да го учи на математика. Йохан се съгласил без желание но бързо разбрал, че ученикът му има способности, надминаващи всичко с което се е срещал досега. Скоро ролите се сменили и учителят се е учил от Ойлер. Йохан посъветвал бащата да се откаже да прави от ученика му министър и предложил да стане математик. Бащата се съгласил, което му прови чест. След няколко години Ойлер заел пост в академията в Санкт-Петербург, в Русия.
Именно там, в 1734 г. Ойлер решил Базелската проблема. В резултат на това той веднага станал "най-добрия математик в Европа".

Решението

Да разгледаме алгебрично уравение от произволна степен, да кажем четвърта.
Formula 1_3
Да предположим, че корените му са b, c, d и e.
Тогава можем да разложим полинома на множители:     (b-x)(c-x)(d-x)(e-x)=0
Ако нито един от множителите не е равен на нула можем да запишем:
Frm1_5

По-нататък има и полиноми от безкрайна степен, например:
Frmula 1_6

Тези особени безкрайни редове са били открити от Нютон, и се извеждат лесно с помоща на математическия анализ.
Този, тук ще го считаме за известен.
Ние знаем "нулите" на синуса       ± kπ .

Първата идея на Ойлер е била предположението, че теоремата за разлагане е вярна за полиноми от безкрайна степен, т.е.
Formula 1_8
Да забележим възможността за използване на формулата (a-b)(a+b)=a2-b2 и да запишем:
Formula 1_10

Сега Ойлер е получил, че безкрайна сума е равна на безкрайно произведение !?

Обърнете внимание и на това, че в знаменателите участват квадратите на естествените числа, което намеква за реда от реципрочните квадрати. Макар, че произведението е безкрайно, ние можем да намерим коефициента пред всяка степен на x.

Дано не обидим многобройните читатели с това обяснение. Да разгледаме произведението
(a+b)(c+d)(e+f)=ace+acf+ade+adf+bce+bcf+bde+bdf
Всеки елемент в произведението , например е равен на произведението на събираемите, взети от всяка скоба по един.

Така Ойлер е намерил коефициента пред x2
Formula 1_12
Но от друга страна в безкрайния ред на sinx/x коефициента пред x2 е       1/3 факториел
Приравнявайки коефициентите получаваме:
Formula 1_16
И така след 90 години отговорът е намерен.

Този резултат остава един от най-странните чудеса в математиката.
Обикновено свързваме π с кръга а Базелската проблема съдържа реципрочни квадрати.
И какво прави тука тригонометричния синус?
Когато Йохан Бернули е видял това решение е трябвало да си каже: "Ех, да беше жив брат ми да види това".
Може би той се е смекчил с годините.

Това не е всичко, което е открил Ойлер в своя исторически труд.
Той е показал, че             Formula 1_17           и           Formula 1_18

Остава въпросът за нечетните степени.
При тях подобни методи не работят.
През целия си живот Ойлер се е мъчил над този проблем. В края на крайщата той казал "Изглежда, че тази задача е сложна". Ако човек като него е казал това, за нас, обикновените математици, не си струва да се мъчим. И разбира се сега, 200 години по-късно отговорът не е намерен, многобройни читатели.

Следствия

Прагматиците могат да запитат за ползата от тези усилия водещи до резултат, от който няма никаква практическа полза. Обичайният отговор е че тази задача е от теория на числата, а в нея подобни въпроси не се поставят. Не толкова циничен отговор би бил, че резултатите от тази теория, все пак намират своя път в реалността. Добър пример за това е "малката теорема на Ферма", открита през 1640 г. , на която се основава криптографски метод за предаване на данни по Интернет. Без това търговията в Интернет би била невъзможна. А що се отнася до Базелската проблемма, по-късно се оказало, че тя е свързана с "хипотезата на Риман", една от най-важните и нерешени проблеми до ден-днешен. Тази хипотеза е била формулирана от Риман през 1859 г. Счита се за вярна, но досега не е доказана от никого. Може би ни е нужен нов Леонард Ойлер.

Приложение     -   Разсходимост на хармоничния ред

Якоб Бернулли доказал, както вече бе казано, че сумата на реда Formula 1_2 е безкрайност.
Той е забелязъл, че събираемите могат да се групират: Formula 1_20
Предположил, че сумата във всяка група е по-голяма или равна на 1.
Ако е така, сумата на хармоничния ред е безкрайна, понеже е равна на сумата на безброй много събираеми, всяко от които е 1 или по-голямо.
За да докаже това, той е разгледал една група, без първото събираемо.
Formula 1_21 Броят на събираемите е k2-k. Най-малкото събираемо е последното. Така че:
Formula 1_22 или Formula 1_23
Прибавайки към двете части на неравенството 1/k , получаваме търсения резултат.

Превел: Станчо Павлов

Какво ще научим: Редове на Маклорен за елементарни функции - таблица       Пример 3 от страницата за редове на Фурие