- Lecția 1. Noțiuni introductive
- Lecția 2. Tipuri standard de date
- Lecția 3. Operații de intrare - ieșire
- Lecția 4. Aplicație: rezolvarea ecuațiilor prin metode numerice
- Lecția 5. Funcții
- Lecția 6. Instrucțiunile if, else și switch
- Lecția 7. Instrucțiunile while, do while și for
- Lecția 8. Aplicații
- Tablouri
Lecția 1. Noţiuni introductive
Vocabularul limbajului de programare C++
Setul de caractere
Orice program este scris cu ajutorul următoarelor caractere: literele mari și mici ale alfabetului englez (A-Z, a-z), numite și caractere alfabetice, cifrele zecimale 0...9, numite și caractere numerice, și caracterele speciale + , / , * , = , & , [,], { , } ,blank (spațiu) , _ , @.
Caracterele sunt codificate intern pe câte un octet, folosind standardul de codificare ASCII, prin care fiecărui caracter i se asociază o valoare întreagă pozitivă cuprinsă între 0 și 255.
Identificatori
Un identificator este o succesiune de litere, cifre sau caracterul special _; primul caracter nu trebuie să fie cifră. Identificatorii pot avea orice lungime. Exemple: MarilynManson, b121, anexa_14.Orice identificator trebuie definit sau declarat într-o linie anterioară folosirii sale într-o expresie.
Identificatorii sunt nume prin care desemnăm în program valori. Valorile pot fi constante sau variabile.
Există un set de identificatori predefiniți, numiți cuvinte cheie rezervate: while, void, for, do, struct, char, float, switch, NULL, include, const, if, define.
Separatori
Unitățile de structură ale programului sunt separate între ele prin separatori, care pot fi, de la caz la caz: blankul (spațiul), punctul și virgula ";", parantezele acolade { și }.Comentarii
Comentariile sunt explicații care nu sunt parte a programului, ci au rol de clarificare pentru programator. Comentariile se pot scrie fie pe o singură linie, și atunci trebuie să le precedăm de două slash-uri //, fie se pot scrie pe mai multe rânduri consecutive, și atunci le încadrăm între grupurile de semne speciale /* și */.Mediul de programare
Mediul de programare este o aplicație software cu ajutorul căreia scriem programe într-un limbaj de programare, le putem modifica și corecta, iar în cele din urmă le putem lansa în execuție. Un program este de regulă un fișier cu o extensie specială, care în cazul limbajului C++ este cpp. Acest fișier, pe care îl scrie programatorul, se numește program sursă.Mediul de programare conține mai multe programe speciale, cu ajutorul cărora acest program sursă este dezvoltat și transformat într-un program executabil. Cel mai important program din această grupă de componente ale mediului de programare se numește compilator. Acest compilator realizează faza inițială de depistare a erorilor de formă ale programului și dacă nu sunt erori, convertește programul într-o formă intermediară, numită program obiect.
Din forma intermediară se ajunge la forma finală printr-o nouă prelucrare, numită editare de legături, sau build. Aceasta constă în atașarea anumitor module de program indispensabile, ce sunt furnizate tot de către mediul de programare . Această etapă este efectuată de către mediul de programare fie înlănțuit cu compilarea (printr-o singură comandă) fie separat, prin două comenzi diferite. Abia după ce s-a realizat editarea de legături se poate lansa programul în execuție, prin comanda Run.
Aceste fișiere se află localizat într-un director dedicat, alături de mai multe alte fișiere ajutătoare, atașate de către sistemul de operare. Tot în acest director se mai află eventualele fișiere de date, atât cele de intrare cât și cele de ieșire. Tot acest ansamblu de fișiere formează un proiect. Proiectul are un nume ales de către programator.
Există mai multe medii de programare dedicate limbajului C++, care funcționează pe principii asemănătoare. În privința alegerii unui mediu sau altul, sau a diverselor versiuni ale lor, un rol important îl are puterea calculatorului (dimensiunea spațiului de hard disk, memoria internă, viteza microprocesorului), dar și obișnuința și preferințele programatorului. Pentru C++, cele mai folosite medii de programare sunt: Code Blocks, Microsoft Visual C++ Express, Microsoft Visual Studio, DevCpp și altele.
Pentru început, la prima lansare în execuție a mediului de programare ales, vom alege un Proiect Nou (New project) de tipul Empty Project. În pagina goală afișată, vom introduce primul program C++:
#include <iostream>
using namespace std;
int main
{
cout<<"Hello world!";
}
Vom avea grijă în prealabil să configurăm tastatura pentru limba engleză, deoarece nu dorim diacritice în corpul programului.
Compilăm și lansăm în execuție.
Se va afișa o fereastră neagră, pe care va scrie textul Hello world!
Cum realizăm un program
Scopul programării calculatoarelor poate fi rezumat în câteva cuvinte astfel: dăm calculatorului niște date și niște metode de lucru și vrem să primim în schimb niște rezultate.Exemplu: găsirea celui mai mare divizor comun a două numere. Datele de intrare sunt cele două numere, pe care le numim a și b. Metodele pot fi mai multe:
Metoda 1: se caută cmmdc din 1 în 1, începând de la 1 și până la cel mai mic dintre cele două numere. Cel mai mare număr la care se divid atât a cât și b este cmmdc.
Metdoda 2: se împarte cel mai mare număr (să zicem că este a) la celălalt (adică la b) și se obține un rest r. Dacă r=0, atunci cmmdc=numărul cel mai mic, adică b. Dacă r>0, atunci facem modificările: a<-b și b<-r apoi reluăm algoritmul de la capăt.
Metoda 3: Dacă cele două numere sunt egale, atunci cmmmc = a=b. Dacă a>b, se scade cel mai mic număr (să zicem că este b) din cel mai mare (deci a) și se obține o diferență d >0. Înlocuim cel mai mare dintre numere (a) cu diferența d și reluăm algoritmul de la capăt până când descăzutul și scăzătorul devin egale.
Vom implementa în limbajul C++ algoritmul cu scăderi repetate, generalizat pentru 3 numere:
//calculeaza cel mai mare divizor comun prin scaderi repetate
#include <iostream> //directive pentru compilator
using namespace std;
int a,b,c; // declararea variabilelor. Acum se alocă spațiu de memorie pt date.
int cmmdc(int x,int y) // declararea funcției cmmmc cu parametri formali
{
while(x!=y) // cat timp a<>b execută
{
if(x>y)x=x-y; // daca a>b atunci a<–a-b
else //altfel
y=y-x; //b<–b-a
}
return x; // funcția returnează valoarea x
}
int main() // funcția main este începutul programului
{
cout<<"a, b, c="; // scrie pe monitor un mesaj explicativ care solicită inputul datelor
cin>>a>>b>>c; // se așteaptă introducerea celor 3 numere
cout<<endl<<"cmmdc="<<cmmdc(a,cmmdc(b,c)); // se apelează funcția cmmmc // cu parametrii actuali care înlocuiesc
// in calcule parametrii formali.
}
Noțiuni utilizate în acest program:
- date de intrare a,b,c
- date de ieșire cmmmc(a, cmmmc(b,c))
- algoritm
- funcție cmmmc()
- parametri formali x,y
- parametri actuali a,b,c
- citire date de la dispozitivul de intrare cin<<
- scriere date în dispozitivul de ieșire cout>>
- instrucțiuni: while, if, else
__________________________________________
Lecția 2. Tipuri standard de date
Un tip de dată este caracterizat prin mulțimea de valori pe care le poate lua data respectivă și prin numărul de octeți alocat pentru memorarea ei. În C++ lucrăm cu două seturi de tipuri de date: tipuri simple și tipuri structurate (sau compuse).
Tipuri de date
|
Grupare după natură
|
Tip (cuvinte cheie)
|
Număr de
octeți
|
Mulțimea de valori
|
Tipuri simple
|
Întregi
|
Int
|
2
|
-32767 … 32767
|
shortint
|
2
|
-32767 … 32767
|
||
unsigned int
|
2
|
0 … 65535
|
||
long
|
4
|
-2,147,483,647 … 2,147,483,647
|
||
unsigned long
|
4
|
0 … 4,294,967,295
|
||
Reale
|
float
|
4
|
± 3.4 · 10± 38
|
|
double
|
8
|
± 1.7 · 10± 308
|
||
long double
|
10
|
|||
caracter
|
char
|
1
|
0… 255
|
|
logice
|
bool
|
2
|
||
Tipuri structurate
|
Tablouri (vectori, matrici)
Fișiere text
|
Mulțimea de valori ale unui tip este ușor de aflat dacă se cunoaște numărul de octeți alocați: cel mai mare număr memorat pe un octet este 2 la puterea 8, respectiv 256. Cel mai mare număr reprezentat pe 2 octeți este 2 la puterea 16, adică 65536, și așa mai departe. La tipurile cu semn, dimensiunea zonei de memorie alocată pentru număr se reduce cu 1 bit, unde se memorează semnul.
Definirea constantelor și variabilelor
Atât constantele cât și variabilele sunt recunoscute în program doar după definirea lor, când li se fixează numele, tipul și eventual valoarea. diferența dintre constante și variabile este aceea că valoarea unei constante nu se mai poate modifica în program.
Exemple:
const pi = 3.14; // const = cuvânt cheie, pi = identificator, 3.14 = valoare
const unu = '1';
int s; // int = cuvânt cheie = tipul întreg, s = identificator
float p, t, y; // float = tip, p, t, y = identificatori.
Expresii
O expresie este formată din unul sau mai mulți operanzi legați prin operatori. Orice expresie are o valoare și un tip. Operanzii pot fi constante, variabile sau funcții. Operatorii sunt specifici tipurilor de date: aritmetici, relaționali, logici și alții.
Clasificarea operatorilor
1. operatori aritmetici
- unari: +, -
- binari multiplicativi: *, /, % (rest)
- binari aditivi: +, -
3. operatori de egalitate == (egal), != (diferit)
4. operatori logici: ! (negare), && (ȘI logic), || (SAU logic)
5. operatori pentru biți: ~ (complementare bit), << (deplasare biți la stânga), >> (deplasare biți la dreapta), & (ȘI logic pe biți), | (SAU logic pe biți).
6. Operatori de incrementare și decrementare (care pot fi prefixați sau postfixați): ++, -- //my_var++
7. operatori de atribuire:
varianta simplă: = // my_var = 75;
varianta compusă: +=, -=, *=, /= // my_var += 33 echivalent cu my_var=my_var + 33
Exerciții
Scrie în C++ următoarele expresii:
1. E1=x este număr par și y nu se divide la 3, 5 și 7
Răspuns: E1=x%2==0 && y%3!=0 && y%5!=0 && y%7 !=0
2. E2 = x este mai mic sau cel mult egal cu y și y este multiplu de 11 și 9
3. E3 = x este divizibil la y sau y este impar și este mai mare cu 5 decât x.
Întrebare: care este tipul expresiilor E1, E2 și E3?
Program:
se citesc de la tastatură numerele întregi a și b. Să se afișeze pe ecran produsul lor și dacă a este divizibil cu b, să se afișeze textul "a este divizibil cu b", altfel să se afișeze textul "a nu este divizibil cu b".
Indicații:
- întotdeauna programul are următoarea structură:
#include <iostream>
using namespace std;
// niște declarații de constante și variabile ..............
int main()
{
// corp program
}
- instrucțiunea de citire de la tastatură este
cin>>id_var;
- instrucțiunea de afișare pe ecran este
cout<<id_var; cu varianta cout<<endl<<id_var; pentru scriere pe rândul următor.
Lecția 3. Șiruri de caractere. Operații de intrare - ieșire
Șiruri de caractere
În C++ un șir de caractere este o succesiune de caractere cuprinsă între două ghilimele și poate să conțină orice caractere: litere mari și mici, caractere speciale (#, $, &, etc), delimitatori, cifrele de la 0 la 9 (ca elemente de text, nu ca numere).
Exemplu:
"Programare în limbajul C++"
În C++, un șir de caractere poate fi definit astfel:
char nume-șir[dimensiune maximă]; declară un șir de caractere cu numele nume_șir și cu dimensiunea maximă specificată între parantezele drepte.
Exemplu:
char nume_elev[30];
Într-un șir de caractere se poate memora o valoare atât prin citire, cât și prin atribuire.
Numărul de caractere ale șirului se numește lungimea șirului sau dimensiunea efectivă. Această dimensiune nu coincide neapărat cu dimensiunea alocată de compilator ca efect a declarației șirului.
Caracterele succesive din șir au un număr de ordine, începând cu primul care are indicele 0. Deci dacă șirul s este "Programare", primul caracter este s[0]='P'.
În urma operației de citire, după ultimul caracter citit compilatorul scrie întotdeauna un caracter special 0 binar, sau NULL. Acest caracter este marcherul de sfârșit de șir. Deci dacă se citește șirul "C++" de la tastatură, caracterele succesive vor fi: s[0]='C', s[1]='+', s[2]='+', s[3]=0. Deci un șir cu lungimea n caractere se memorează pe n+1 celule de memorie consecutive. Fiecare caracter în C++ se memorează pe un octet.
Atenție la sintaxă: 'C' înseamnă caracterul C, el este o variabilă de tip char și se memorează pe un octet. "C" este un șir de caractere de lungime 1 și se memorează pe 1+1 = 2 octeți.
Operații de intrare / ieșire
Operațiile de citire a datelor de intrare și de scriere a datelor de ieșire se pot realiza prin două căi:
INTRARE (CITIRE) | IEȘIRE (SCRIERE)
- de la tastatură | pe ecran; cin>>variabilă_memorie | cout<<variabilă_memorie
- din fișiere text | în fișiere text; fisier>>var_memorie | fisier<<var_memorie
Comenzile pentru operațiile de intrare / ieșire necesită includerea în aplicație a unor biblioteci de sistem. Pentru tastatură și ecran folosim #include <iostream>
iar pentru fișiere folosim #include <fstream>.
Citirea de la tastatură.
Tastatura nu poate trimite către program decât caractere și șiruri de caractere. Totuși, operatorul de citire >> realizează conversia de la tipul caracter la orice tip de dată de memorie, în funcție de tipul variabilei de memorie utilizate în citire.
Exemplu:
char nume[10]; //declarăm variabila nume de tip șir, cu lungime maximă 10.
cin>>nume; // lansăm operația de citire de la tastatură. Dacă tastăm "Alexandru"
// variabila nume va conține șirul "Alexandru".
int puncte; //declarăm variabila întreagă puncte.
cin puncte; // se citesc cifrele una după alta până se tastează enter.
// dacă se tastează 3455, variabila puncte va conține numărul 3455
// reprezentat în binar pe 2 octeți.
char data_nașterii[15]; // se declară variabila data_nașterii cu lungime de 15 elemente;
cin>>data_nașterii; // dacă se tastează 30-martie-2002, șirul data_nașterii va primi
// valoarea "30-martie-2002" pe primele 14 poziții ale sale, fiecare
// caracter ocupând 1 octet reprezentat prin codul ASCII.
Scrierea pe ecran.
Ecranul nu poate afișa decât caractere și șiruri de caractere. Totuși, operatorul << realizează conversia de la orice tip ar avea data de memorie de afișat către tipul caracter.
Exemple:
1. dacă variabila inițiala_tatalui este de tipul char și are valoarea 'P', instrucțiunea
cout<<inițiala_tatalui;
va determina afișarea caracterului P.
2. Instrucțiunea cout<<data_nașterii va determina afișarea textului 30-martie-2002.
3. Instrucțiunea cout<< puncte; va determina afișarea textului / numărului 3455.
Scrieri / citiri multiple.
Pe o singură instrucțiune cin sau cout se pot înlănțui mai mulți operatori de intrare - ieșire de același tip:
cin>>nume>>initiala_tatalui>>data_nasterii;
cout<<nume<<" "<<initiala_tatalui<<" "<<data_nasterii;
Scriere pe rândul următor.
Pentru a scrie pe ecran pe un rând nou, folosim instrucțiunea cout<<endl sau echivalent cout<<'\n';
Exemplu: cout<<endl<<nume<<endl<<data_nasterii; // va scrie pe rânduri succesive.
Citirea din fișier de tip text
Fișierele de tip text conțin rânduri de lungime variabilă, similar cu textele dintr-o pagină de carte. Fiecare caracter este codificat pe 1 octet în codificare ASCII, exact ca și în memoria internă. Fiecare linie de text este delimitată de un caracter special de sfârșit de linie, care are aceași valoare ASCII ca și caracterul de rând nou pentru ecran, '\n', sau endl. Sfârșitul fișierului este marcat de alt caracter special, numit EOF (End Of File).
Fișierele sunt localizate pe hard disc într-un folder și au un nume extern compus dintr-un nume și un tip, de exemplu "Capra cu trei iezi.docx". În practica programării în C++ nu vom folosi aceste tipuri de fișiere, ci doar fișiere text create nu notepad, în folderul proiectului de lucru, cu extensie txt sau la alegerea noastră. exemplu: date. txt sau date.in.
Nu vom folosi în program numele extern al fișierului, ci un nume intern fără tip, pe care îl asociem la început cu fișierul extern prin intermediul unei declarații speciale fstream făcându-se mențiunea că este un fișier de intrare (in):
de reținut că de aici încolo ne vom referi la fișierul fizic date.txt numai prin numele logic fisier_intrare.
Citirea efectivă se va realiza la fel ca și citirea din tastatură, cu operatorul >> și conversia de la tipul caracter la tipul variabilei de memorie. Procesul se desfășoară într-un singur sens, de la începutul către sfârșitul fișierului. Fiecare cuvânt (șir de caractere delimitat prin spații sau sfârșit de linie) se citește într-o variabilă de memorie individuală. Acest proces unidirecțional se numește flux de intrare (stream).
Dacă se ajunge accidental cu citirea la sfârșitul de fișier, operația de citire trimite o atenționare, care poate fi testată prin program printr-o instrucțiune specifică.
exemplu:
fișier_intrare>>nume>>initiala_tatalui>>data_nasterii;
Scrierea în fișier de tip text
Pentru a scrie într-un fișier text, este nevoie în prealabil să se asocieze un nume intern cu un nume extern de fișier, cu mențiunea că este un fișier de ieșire (out):
// caracter ocupând 1 octet reprezentat prin codul ASCII.
Scrierea pe ecran.
Ecranul nu poate afișa decât caractere și șiruri de caractere. Totuși, operatorul << realizează conversia de la orice tip ar avea data de memorie de afișat către tipul caracter.
Exemple:
1. dacă variabila inițiala_tatalui este de tipul char și are valoarea 'P', instrucțiunea
cout<<inițiala_tatalui;
va determina afișarea caracterului P.
2. Instrucțiunea cout<<data_nașterii va determina afișarea textului 30-martie-2002.
3. Instrucțiunea cout<< puncte; va determina afișarea textului / numărului 3455.
Scrieri / citiri multiple.
Pe o singură instrucțiune cin sau cout se pot înlănțui mai mulți operatori de intrare - ieșire de același tip:
cin>>nume>>initiala_tatalui>>data_nasterii;
cout<<nume<<" "<<initiala_tatalui<<" "<<data_nasterii;
Scriere pe rândul următor.
Pentru a scrie pe ecran pe un rând nou, folosim instrucțiunea cout<<endl sau echivalent cout<<'\n';
Exemplu: cout<<endl<<nume<<endl<<data_nasterii; // va scrie pe rânduri succesive.
Citirea din fișier de tip text
Fișierele de tip text conțin rânduri de lungime variabilă, similar cu textele dintr-o pagină de carte. Fiecare caracter este codificat pe 1 octet în codificare ASCII, exact ca și în memoria internă. Fiecare linie de text este delimitată de un caracter special de sfârșit de linie, care are aceași valoare ASCII ca și caracterul de rând nou pentru ecran, '\n', sau endl. Sfârșitul fișierului este marcat de alt caracter special, numit EOF (End Of File).
Fișierele sunt localizate pe hard disc într-un folder și au un nume extern compus dintr-un nume și un tip, de exemplu "Capra cu trei iezi.docx". În practica programării în C++ nu vom folosi aceste tipuri de fișiere, ci doar fișiere text create nu notepad, în folderul proiectului de lucru, cu extensie txt sau la alegerea noastră. exemplu: date. txt sau date.in.
Nu vom folosi în program numele extern al fișierului, ci un nume intern fără tip, pe care îl asociem la început cu fișierul extern prin intermediul unei declarații speciale fstream făcându-se mențiunea că este un fișier de intrare (in):
fstream fisier_intrare("date.txt",ios::in);
de reținut că de aici încolo ne vom referi la fișierul fizic date.txt numai prin numele logic fisier_intrare.
Citirea efectivă se va realiza la fel ca și citirea din tastatură, cu operatorul >> și conversia de la tipul caracter la tipul variabilei de memorie. Procesul se desfășoară într-un singur sens, de la începutul către sfârșitul fișierului. Fiecare cuvânt (șir de caractere delimitat prin spații sau sfârșit de linie) se citește într-o variabilă de memorie individuală. Acest proces unidirecțional se numește flux de intrare (stream).
Dacă se ajunge accidental cu citirea la sfârșitul de fișier, operația de citire trimite o atenționare, care poate fi testată prin program printr-o instrucțiune specifică.
exemplu:
fișier_intrare>>nume>>initiala_tatalui>>data_nasterii;
Scrierea în fișier de tip text
Pentru a scrie într-un fișier text, este nevoie în prealabil să se asocieze un nume intern cu un nume extern de fișier, cu mențiunea că este un fișier de ieșire (out):
fstream fisier_iesire("date.out", ios::out);
Scrierea în fișier se face asemănător cu scrierea pe ecran, folosind operatorul << și conversia de la tipul datei către tipul caracter.
exemplu:
fișier_ieșire<<nume<<" "<<initiala_tatalui<<" "<<data_nasterii;
Exercițiu:
Din fișierul date.in creat în directorul curent cu Notepad se citesc variabilele întregi a, b și c, separate prin câte un spațiu sau mai multe spații. În fișierul date.out se for scrie valorile citite, pe prima linie, cu câte un spațiu între ele, iar pe următoarele linii, suma și produsul lor.
#include <iostream>
#include <fstream>
using namespace std;
fstream f("date.in",ios::in);
fstream g("date.out",ios::out);
int a,b,c;
int main()
{
f>>a>>b>>c;
int suma=a+b+c;
int produs=a*b*c;
g<<a<<" "<<b<<" "<<c<<endl<<suma<<endl<<produs;
}
După execuția programului, se va vizualiza fișierul date.out cu Notepad.
exemplu:
fișier_ieșire<<nume<<" "<<initiala_tatalui<<" "<<data_nasterii;
Exercițiu:
Din fișierul date.in creat în directorul curent cu Notepad se citesc variabilele întregi a, b și c, separate prin câte un spațiu sau mai multe spații. În fișierul date.out se for scrie valorile citite, pe prima linie, cu câte un spațiu între ele, iar pe următoarele linii, suma și produsul lor.
#include <iostream>
#include <fstream>
using namespace std;
fstream f("date.in",ios::in);
fstream g("date.out",ios::out);
int a,b,c;
int main()
{
f>>a>>b>>c;
int suma=a+b+c;
int produs=a*b*c;
g<<a<<" "<<b<<" "<<c<<endl<<suma<<endl<<produs;
}
După execuția programului, se va vizualiza fișierul date.out cu Notepad.
Aplicații
1. Să se afișeze valoarea funcției f:R->R în punctul b (b este o valoare introdusă de la tastatură), funcția având următoarea lege de corespondență:
Lecția 4. Aplicație: rezolvarea ecuațiilor prin metode numerice
Rezolvarea ecuațiilor prin metode numerice este o modalitate de a găsi o soluție aproximativă, în lipsa unei formule algebrice acceptabile. Există mai multe astfel de metode numerice, cu o eficiență mai ridicată sau mai scăzută. Prin eficiența unei metode se înțelege durata (sau numărul de iterații sau de pași sau de operații elementare) necesară pentru obținerea unei soluții cu o precizie dorită.
Vom exemplifica în continuare metoda numită "Metoda generală", cea mai simplă metodă numerică.
Această metodă presupune că știm deja capetele unui interval închis [a, b] între care există o soluție (o rădăcină) a ecuației f(x)=0. Problema noastră este să aproximăm această soluție cu o precizie pe care ne-o propunem (de exemplu, 10^-3, adică 0.001).
Pentru a reuși acest lucru, calculăm valoarea funcției f(x) pentru un șir de valori ale lui x, generate echidistant între a și b. Acest șir se generează împărțind segmentul [a, b] în n secțiuni. Dacă într-un astfel de punct xk din șir obținem o valoare absolută a funcției f(xk)<precizia cerută, am rezolvat problema. Dacă nu am obținut, vom genera un alt șir, mai des, adică pentru un n mai mare de 10 ori. Repetăm divizarea din ce în ce mai deasă a intervalului [a, b] până când obținem precizia dorită.
Să se aproximeze soluția ecuației f(x) = x^2 – 5x + 4, cu o eroare er = 10^-3, știind că are o soluție cuprinsă în intervalul: ξ∈(0,3).
#include <iostream>
using namespace std;
//rezolvarea ecuatiei x^2 – 5x + 4 prin metoda generala.
//intervalul de existenta a radacinii este [0, 3].
float a=0;
float b=3;
int n; //numărul de diviziuni
float er; //precizia
float f(float x)
{
return x*x-5*x+4;
}
int main()
{
cout<<"introdu precizia sub forma 0.0000...1: ";
cin>>er;
float fx=100; //o valoare arbitrara cu care incepem ciclul de rezolvări
float xk; // element din sirul de diviziuni ale intervalului [a, b]
n=10; //incepem prin a imparti intervalul in 10 subintervale
bool rezolvat=false;
while(!rezolvat)
{
{
for(int k=1;k<=n&&!rezolvat;k++)
{
xk=a+(float)k*(b-a)/n; //casting, convertire forțată de la întreg la float
fx=f(xk);
if(fx<0)fx=-fx; //luam in considerare valoarea absoluta (modulul)
if(fx<=er)rezolvat=true;
}
if(!rezolvat)
n*=10;
}
}
cout<<endl<<"n="<<n<<" x="<<xk<<" f(x)="<<fx;
}
Problemă: Să se găsească o aproximare prin metoda numerică generală de mai sus a ecuației f(x) = x^3 - 8x^2 + 19x -12, cu o eroare de maxim er = 10^-5, știind că are o soluție ξ∈(−1,2).
În figura de mai sus, intervalul [a, b] a fost împărțit în 5 segmente, rezultând un număr de 5-1 = 4 puncte interioare: x1, x2, x3, x4.
Aceste puncte fiind echidistante, mărimea oricărui subinterval este (b-a)/5. valorile punctelor intermediare x1, x2, ..., x5 sunt:
x1=a+(b-a)5
x2=x1+(b-a)5=a+2*(b-a)/5
...
x4=a+4(b-a)/5
x5=a+5(b-a)/5 = b.
În cazul general, xk=a+k(b-a)/n, unde n este numărul de segmente egale în care s-a divizat [a, b]. pentru k=n, obținem xn=b.
Vom calcula valoarea funcției f(x) pentru x=x1, x2, ... xn.
Dacă vom obține o valoare absolută |f(xp)|<=precizia cerută, am găsit o soluție. Dacă nu găsim nici o valoare mai mică decât precizia, creștem pe n (de 10 ori, de exemplu) și reluăm calculele.
Exemplu:
Să se aproximeze soluția ecuației f(x) = x^2 – 5x + 4, cu o eroare er = 10^-3, știind că are o soluție cuprinsă în intervalul: ξ∈(0,3).
x^2 înseamnă x la puterea a 2-a, 10^-3 înseamnă 10 la puterea -3.
Algoritmul metodei
program Metoda_generală
real a,b ; domeniul de definiţie al funcţiei f
real er ; eroarea maximă admisibilă a soluţiei
real eps ; eroarea curentă
întreg n ; numărul de iteraţii de efectuat
întreg k ; contorul iteraţiilor
citeşte a, b, n, er
pentru k = 1, n-1 repetă
x = a + k * (b - a) / n
dacă f(x) < er atunci
eps = f(x)
scrie x ; soluţia aproximativă a ecuaţiei
scrie eps ; eroarea între f(x) şi 0
stop
program Metoda_generală
real a,b ; domeniul de definiţie al funcţiei f
real er ; eroarea maximă admisibilă a soluţiei
real eps ; eroarea curentă
întreg n ; numărul de iteraţii de efectuat
întreg k ; contorul iteraţiilor
citeşte a, b, n, er
pentru k = 1, n-1 repetă
x = a + k * (b - a) / n
dacă f(x) < er atunci
eps = f(x)
scrie x ; soluţia aproximativă a ecuaţiei
scrie eps ; eroarea între f(x) şi 0
stop
#include <iostream>
using namespace std;
//rezolvarea ecuatiei x^2 – 5x + 4 prin metoda generala.
//intervalul de existenta a radacinii este [0, 3].
float a=0;
float b=3;
int n; //numărul de diviziuni
float er; //precizia
float f(float x)
{
return x*x-5*x+4;
}
int main()
{
cout<<"introdu precizia sub forma 0.0000...1: ";
cin>>er;
float fx=100; //o valoare arbitrara cu care incepem ciclul de rezolvări
float xk; // element din sirul de diviziuni ale intervalului [a, b]
n=10; //incepem prin a imparti intervalul in 10 subintervale
bool rezolvat=false;
while(!rezolvat)
{
{
for(int k=1;k<=n&&!rezolvat;k++)
{
xk=a+(float)k*(b-a)/n; //casting, convertire forțată de la întreg la float
fx=f(xk);
if(fx<0)fx=-fx; //luam in considerare valoarea absoluta (modulul)
if(fx<=er)rezolvat=true;
}
if(!rezolvat)
n*=10;
}
}
cout<<endl<<"n="<<n<<" x="<<xk<<" f(x)="<<fx;
}
Problemă: Să se găsească o aproximare prin metoda numerică generală de mai sus a ecuației f(x) = x^3 - 8x^2 + 19x -12, cu o eroare de maxim er = 10^-5, știind că are o soluție ξ∈(−1,2).
x^3 înseamnă x la puterea a 3-a, x^2 înseamnă x la puterea a 2-a
10^-5 înseamnă 10 la puterea -5.
10^-5 înseamnă 10 la puterea -5.
Test nr. 1
Blocul de instrucțiuni dintre acolade (poate fi și o singură instrucțiune, terminată prin caracterul ;) este executat condiționat, numai dacă expresia logică din paranteze are valoarea logică true. Dacă expresia are valoarea false, blocul dinntre acolade nu se execută, iar programul continuă direct cu instrucțiunea care urmează după acesta.
Condiția din paranteze este o expresie logică a cărei valoare poate fi doar true sau false. La fel de bine, expresia poate fi numerică, în care caz, dacă are valoarea 0 este interpretată ca false, iar dacă are o valoare nenulă este interpretată ca true.
Exemplu:
Dacă expresia logică are valoarea true se va executa blocul 1, altfel se va executa blocul 2. În ambele cazuri, după aceea se va continua execuția programului cu ceea ce urmează după ... Diferența față de instrucțiunea if simplă, este că blocul 2 nu se va executa în cazul în care expresia logică este adevărată. Blocul 2 se va executa numai dacă expresia este falsă.
Când expresia testată este egală cu una dintre constantele case, execuția programului continuă cu blocul de instrucțiuni aferent acelei constante și se oprește la întâlnirea primului break, apoi continuă cu ceea ce urmează după acolada lui switch.
Opțional, putem prevedea o etichetă default, care va capta situația în care expresia nu este egală cu nici una din constantele case.
2. Scrie o funcție care returnează suma cifrelor unui număr dat ca parametru.
3. Scrie o funcție care returnează numărul cifrelor pare dintr-un număr.
4. Scrie o funcție care returnează cifra de rang k dintr-un număr n. Rangul este numărul de ordine al cifrei începând din dreapta. Numerele n și k se dau ca parametri.
5. Se citesc de le tastatură două numere întregi a și b. Scrie un program care verifică dacă cele două numere au produsul cifrelor egale, folosind o funcție care calculează produsul cifrelor unui număr.
6. Să se calculeze valoarea expresiei E=1+4+7+... +(3n-2). Exemplu: pentru n=5, E=1+4+7+10+13=35.
7. Să se calculeze valoarea expresiei E=2-4+6-... +(-1)^(n+1)*(2n) Exemplu: pentru n=6, E=2-4+6-8+10-12=-6.
8. Să se calculeze produsul primelor n numere naturale impare. Pentru n=4, P=1*3*5*7=105.
9. Scrie o funcție care testează dacă un număr natural x dat ca parametru este prim sau nu.
10. Să se tipărească elementele prime ale unui șir de n numere întregi citit de la tastatură, precum și numărul acestora. Pentru n=5 și șirul 11 12 13 14 15 se va tipări 11 13.
14. Care din următoarele variante reprezintă formatul corect al unei funcții reale cu un parametru întreg?
15. Care este valoarea variabilei n în urma execuției programului următor?
int F(char a[2])
a) 9
16. De la tastatură se citesc trei numere reale a, b, c. Dacă cele trei numere pot forma un triunghi, să se afișeze pe ecran un mesaj corespunzător: echilateral, isoscel, dreptunghic, oarecare.
Între laturile unui triunghi a, b, c există următoarele relații: fiecare latură este mai mică decât suma celorlalte două, și mai mare decât modulul (valoarea absolută) diferenței celorlalte două:
17. Din fișierul date.in se citesc patru numere întregi x, y, u, v, separate prin spații. Să se determine maximul și minimul valorilor citite și apoi să se scrie aceste valori în fișierul date.out pelinii distincte.
18. Se citesc n numere întregi. Să se determine și să se afișeze:
a) câte din ele sunt pare;
b) suma elementelor pozitive;
c) valoarea maximă.
19. Din fișierul date.in se citesc p numere naturale. Să se afișeze suma divizorilor fiecărui număr, pe linii distincte, în fișierul date.out.
20. Fie n un număr natural nenul. Calculați valoarea expresiei
E=(1-1/2^3)(1-1/3^3)...(1-1/n^3)
21. Să se scrie un program pentru afișarea triunghiului de numere alăturat, unde n este un număr natural >=5 citit de la tastatură:
1
1 2
1 2 3
1 2 3 4
.....
1 2 3 4 5 ...n
22. Prelucrarea elementelor unei secvențe de numere întregi:
Scrieți o funcție care returnează:
Scrieți o funcție care returnează:
Scrieți o funcție recursivă care returnează:
Lecția 5. Funcții
Un
program are o structură modulară. Un caz particular de modul îl
constituie subprogramele. În C++, subprogramele se numesc funcții. Să
luăm cazul unui program care calculează media a două numere, pe care îl
vom scrie în 4 variante:
La apel, valorile parametrilor actuali înlocuiesc parametrii formali în operațiile efectuate în corpul funcției calcul_media.
4. Funcție cu parametri și valoare returnată
Într-un program putem avea o variabilă globală și una locală cu același nume, fără a se crea confuzie: variabila locală o ascunde pe cea globală, adică în cadrul funcției este vizibilă numai variabila locală, iar în rest este vizibilă numai cea globală. Evident, celelalte variabile globale, care nu sunt dublate de variabile locale sinonime, sunt vizibile în cadrul funcției.
Putem apela o funcție de mai multe ori, cu date diferite, atât constante cât și variabile. Valorile parametrilor actuali înlocuiesc de fiecare dată în calcule parametrii formali. Adresa parametrilor actuali nu este transmisă funcției. De aceea funcția nu poate modifica partametrii actuali în locația lor reală, deoarece nu le cunoaște adresa, ea primește doar o copie a valorii lor.
Rescriem funcția calcul_suma de mai sus, în așa fel încât aceasta să lucreze direct asupra parametrilor actuali:
1. Fără funcție
#include <iostream>
using namespace std;
float M, x, y;
void main()
{
cout<<"dați numerele:\n";
cin>>x >>y;
M=(x+y)/2;
cout<<"Media="<<M;
}
Vom
scrie acum același program, structurat în două module: un program
principal și o funcție. Acest mod de a scrie programul ține seama de
funcționalitatea modulelor. Există mai multe variante de a scrie
această funcție:
2. Funcție fără parametri și fără valoare returnată (cu variabile globale)
#include <iostream>
float M,x,y;
void calcul_media()
{
M=(x+y)/2; //M, x și y sunt variabile globale, vizibile în interiorul funcției
cout<<"Media="<<M;
}
void main()
{
cout<<"dați numerele:\n";
cin>>x >>y;
calcul_media();
}
3. Funcție cu parametri și fără valoare returnată
#include <iostream>
float M,x,y; //M global, x și y transmiși prin valoare
void calcul_media(float u, float v) //u și v parametri formali
{
M=(u+v)/2;
cout<<"Media="<<M;
}
void main()
{
cout<<"dați numerele:\n";
cin>>x >>y;
calcul_media(x,y); //x și y parametri actuali
}
La apel, valorile parametrilor actuali înlocuiesc parametrii formali în operațiile efectuate în corpul funcției calcul_media.
4. Funcție cu parametri și valoare returnată
#include <iostream>
float M,x,y; //M global, x și y transmiși prin valoare
float calcul_media(float u, float v) //u și v parametri formali
{
float media=(u+v)/2; //media este variabilă locală, invizibilă în exteriorul funcției
return media;
}
void main()
{
cout<<"dați numerele:\n";
cin>>x >>y;
M=calcul_media(x,y);//x și y parametri actuali
cout<<M;
}
Într-un program putem avea o variabilă globală și una locală cu același nume, fără a se crea confuzie: variabila locală o ascunde pe cea globală, adică în cadrul funcției este vizibilă numai variabila locală, iar în rest este vizibilă numai cea globală. Evident, celelalte variabile globale, care nu sunt dublate de variabile locale sinonime, sunt vizibile în cadrul funcției.
Parametri transmiși prin valoare
Putem apela o funcție de mai multe ori, cu date diferite, atât constante cât și variabile. Valorile parametrilor actuali înlocuiesc de fiecare dată în calcule parametrii formali. Adresa parametrilor actuali nu este transmisă funcției. De aceea funcția nu poate modifica partametrii actuali în locația lor reală, deoarece nu le cunoaște adresa, ea primește doar o copie a valorii lor.
int calcul_suma(int u,int v) //u și v parametri formali transmiși prin valoare
{
u=u+v; //aparent, parametrul u este modificat, dar el este parametru formal, nu actual
return u;
}
void main()
{
int x,y;
cout<<calcul_suma(5,7);
cout<<endl<<calcul_suma(122,359);
cout<<endl<<"x șiy=";
cin>>x>>y;
cout<<endl<<calcul_suma(x,y);
cout<<endl<<x; // se poate verifica faptul că x nu este modificat în urma apelului
}
Parametrii actuali trebuie să corespundă ca număr, ordine și tip cu parametrii formali.
Parametrii transmiși prin valoare constituie date de intrare pentru o funcție, niciodată nu pot constitui date de ieșire.
Parametri transmiși prin referință
Rescriem funcția calcul_suma de mai sus, în așa fel încât aceasta să lucreze direct asupra parametrilor actuali:
int calcul_suma(int &u,int &v) //u și v parametri formali transmiși prin referință
{
u=u+v; //parametrul u este modificat, și fiind transmis prin referință, modificarea are efect
//și asupra parametrului actual.
return u;
}
void main()
{
int x,y;
cout<<endl<<"x șiy=";
cin>>x>>y;
cout<<endl<<calcul_suma(x,y);
cout<<endl<<x; // se poate verifica faptul că x este modificat în urma apelului
}
Parametrii
transmiși prin referință se pot modifica în urma apelului funcției,
deoarece funcția are acces la locația lor de memorie. Parametrii
transmiși prin referință pot constitui atât date de intrare, cât și date
de ieșire pentru o funcție.
Un
parametru transmis prin referință se comportă asemănător cu o
variabilă globală pentru funcția respectivă. Totuși, ei nu sunt
accesibili și altor funcții, precum adevăratele variabile globale.
Operatorul & se numește operator de adresare, și semnificația lui este "adresa lui...".
Lecția 6. Instrucțiunile de decizie if, else și switch
Instrucțiunea if simplă
Instrucțiunea if ramifică execuția programului către două direcții în funcție de îndeplinirea unei condiții. Forma simplă a acestei instrucțiuni este
if (expresie logică)
{bloc de instrucțiuni}
......
Blocul de instrucțiuni dintre acolade (poate fi și o singură instrucțiune, terminată prin caracterul ;) este executat condiționat, numai dacă expresia logică din paranteze are valoarea logică true. Dacă expresia are valoarea false, blocul dinntre acolade nu se execută, iar programul continuă direct cu instrucțiunea care urmează după acesta.
Condiția din paranteze este o expresie logică a cărei valoare poate fi doar true sau false. La fel de bine, expresia poate fi numerică, în care caz, dacă are valoarea 0 este interpretată ca false, iar dacă are o valoare nenulă este interpretată ca true.
Exemplu:
int age;
cin >> age;
if(age == 16)
{
cout << "Wow, I'm 16 too!";
}
Instrucțiunea if - else
Pentru a putea trata valori și condiții mai variate, există grupul de instrucțiuni if - else.
if (expresie logică)
{bloc 1 de instrucțiuni}
else
{bloc 2 de instrucțiuni}
...
Dacă expresia logică are valoarea true se va executa blocul 1, altfel se va executa blocul 2. În ambele cazuri, după aceea se va continua execuția programului cu ceea ce urmează după ... Diferența față de instrucțiunea if simplă, este că blocul 2 nu se va executa în cazul în care expresia logică este adevărată. Blocul 2 se va executa numai dacă expresia este falsă.
int age, height;
cin >> age;
cin >> height;
if(height == age)
{
cout << "Your height is equal to your age!";
}
else if(height < age)
{
cout << "Your height is less than your age!";
}
else if(height > age)
{
cout << "Your height is greater than your age!";
}
În blocul de instrucțiuni de mai sus avem mai multe instrucțiuni if - else - if înlănțuite. Regula este că fiecare else aparține instrucțiunii if care îl precedă.#include <iostream>
using namespace std;
int main(){
int mark;
cout << "What mark did you get in the test?" << endl;
cin >> mark;
if(mark >= 90)
{
cout << "You got an A*" << endl;
cout << "You Passed!" << endl;
}
else if(mark >= 80)
{
cout << "You got an A" << endl;
cout << "You Passed!" << endl;
}
else if(mark >= 70)
{
cout << "You got an B" << endl;
cout << "You Passed!" << endl;
}
else if(mark >= 60)
{
cout << "You got an C" << endl;
cout << "You Passed!" << endl;
}
else if(mark >= 50)
{
cout << "You got an D" << endl;
cout << "You Failed!" << endl;
}
else if(mark >= 40)
{
cout << "You got an E" << endl;
cout << "You Failed!" << endl;
}
else
{
cout << "You got an U" << endl;
cout << "You Failed!" << endl;
}
return 0;
}
Instrucțiunea switch case
Instrucțiunea switch testează valoarea unei variabile întregi dacă este egală cu una din valorile dintr-o listă de constante sau case-uri. Dacă variabila testată are o valoare care se regăsește în lista de cazuri, se va executa instrucțiunea su blocul de instrucțiuni atașate acelei valori.switch(expressie){ case constantă : {instrucțiuni;} break; //optional case constantă : {instrucțiuni;} break; //optional // oricâte etichete case default : //Optional {instrucțiuni;} }
Când expresia testată este egală cu una dintre constantele case, execuția programului continuă cu blocul de instrucțiuni aferent acelei constante și se oprește la întâlnirea primului break, apoi continuă cu ceea ce urmează după acolada lui switch.
Opțional, putem prevedea o etichetă default, care va capta situația în care expresia nu este egală cu nici una din constantele case.
#include <iostream> using namespace std; int main () { // local variable declaration: int nota = 8; switch(nota) { case 10 : cout << "Foarte bine" << endl; break; case 9 : case 8 : cout << "Bine" << endl; break; case 7 : cout << "Ai trecut" << endl; break;
case 6 :
case 5 : cout << "Mai bine mai încearcă o dată" << endl; break; default : cout << "Notă invalidăe" << endl; } cout << "Your grade is " << grade << endl; return 0; }
Lecția 7. Instrucțiuni repetitive: while, do while, for
while
Instrucțiunea while determină executarea repetată a unui bloc de instrucțiuni cât timp o condiție se menține adevărată. Sintaxă:
while(condiție){ {instrucțiuni;} }
Exemplu:
#include <iostream> using namespace std; int main () { int a = 10; while( a < 20 ) { cout << "value of a: " << a << endl; a++; } return 0; }
Rezultatul afișat al programului:
value of a: 10 value of a: 11 value of a: 12 value of a: 13 value of a: 14 value of a: 15 value of a: 16 value of a: 17 value of a: 18 value of a: 19
do while
Instrucțiunea do while este similară instrucțiunii while, cu diferența că mai întâi se execută blocul de instrucțiuni și apoi se face testul:
do { instrucțiuni; }while( condition );
Exemplu:
#include <iostream>
using namespace std;
int main () {
int a = 10;
do {
cout << "value of a: " << a << endl;
a = a + 1;
}while( a < 20 );
return 0;
}
Rezultat:
value of a: 10 value of a: 11 value of a: 12 value of a: 13 value of a: 14 value of a: 15 value of a: 16 value of a: 17 value of a: 18 value of a: 19
Diferența dintre cele două instrucțiuni constă în falptul că blocul din do while
se va executa cel puțin o dată, deoarece testul se face la sfârșit.
Exemplu:
#include <iostream>
using namespace std;
int main () {
int a = 10;
do {
cout << "value of a: " << a << endl;
a = a + 1;
}while( a < 10 );
return 0;
}
afișează value of a:10
dar
int main () {
int a = 10;
while( a < 10 ) {
cout << "value of a: " << a << endl;
a++;
}
return 0;
}
nu afișează nimic.
for
Instrucțiunea for permite executarea unui bloc în mod repetat de un număr
cunoscut de ori. Sintaxa:
for ( inițializare; condiție; incrementare ) { instrucțiuni; }
În lista dintre paranteze există trei blocuri de instrucțiuni și expresii, care
se execută astfel:
Mai întâi, o singură dată blocul inițializare;
În al doilea rând se evaluează expresia logică condiție. Dacă este adevărată,
se va executa blocul for; dacă este falsă, blocul for nu se mai execută și se trece
la instrucțiunea imediat următoare.
După executarea blocului for, se execută blocul incrementare, care asigură actuali-
zarea variabilei contor.
Exemplu:
#include <iostream> using namespace std; int main () { for( int a = 10; a < 20; a = a + 1 ) { cout << "value of a: " << a << endl; } return 0; }
Rezultatul:
value of a: 10 value of a: 11 value of a: 12 value of a: 13 value of a: 14 value of a: 15 value of a: 16 value of a: 17 value of a: 18 value of a: 19
Lecția 8. Aplicații
1. Unde este eroarea în funcția de mai jos?
int demo(float x, y)
{ return (x+y)/2}
2. Scrie o funcție care returnează suma cifrelor unui număr dat ca parametru.
3. Scrie o funcție care returnează numărul cifrelor pare dintr-un număr.
4. Scrie o funcție care returnează cifra de rang k dintr-un număr n. Rangul este numărul de ordine al cifrei începând din dreapta. Numerele n și k se dau ca parametri.
5. Se citesc de le tastatură două numere întregi a și b. Scrie un program care verifică dacă cele două numere au produsul cifrelor egale, folosind o funcție care calculează produsul cifrelor unui număr.
6. Să se calculeze valoarea expresiei E=1+4+7+... +(3n-2). Exemplu: pentru n=5, E=1+4+7+10+13=35.
7. Să se calculeze valoarea expresiei E=2-4+6-... +(-1)^(n+1)*(2n) Exemplu: pentru n=6, E=2-4+6-8+10-12=-6.
8. Să se calculeze produsul primelor n numere naturale impare. Pentru n=4, P=1*3*5*7=105.
9. Scrie o funcție care testează dacă un număr natural x dat ca parametru este prim sau nu.
10. Să se tipărească elementele prime ale unui șir de n numere întregi citit de la tastatură, precum și numărul acestora. Pentru n=5 și șirul 11 12 13 14 15 se va tipări 11 13.
11.
(Bac 2000) Scrie un program care generează toate numerele prime strict
mai mici decât x (x număr natural). Numerele vor fi scrise în fișierul
"bac.txt" câte unul pe linie.
12 (Bac 2000) Ce valori va afișa programul următor?
int n,m;
void T(int n, int &m)
{n+=2; m--}
int main()
{
n=2; m=5;
T(n,m);
cout<<endl<<"n<<" "<<m;
n=10; m=20;
T(n,m);
cout<<endl<<"n<<" "<<m;
}
a) 4 4 12 19
b) 4 5 12 20
c) 2 4 10 19
d) 2 5 10 20
e) 7 2 22 10
13.
(Bac 2000) În fișierul BAC.txt se află mai multe numere naturale de cel
mult 3 cifre fiecare, despărțiote prin spații. Scrieți un program care
creează un alt fișier BAC2.txt care conține exact aceleași numere, câte
unul pe linie, în ordinea crescătoare a valorilor acestora. Programul
ca conține o funcție care interschimbă între ele două numere întregi
date ca parametru.
14. Care din următoarele variante reprezintă formatul corect al unei funcții reale cu un parametru întreg?
a) integer f(float x) b) float f(int &x) c) float f(float &x); d) int f(float x)
15. Care este valoarea variabilei n în urma execuției programului următor?
int F(char a[2])
{
int i=0;
while(a[i++]);
return i;
}
int main()
{
int n=F("abcdefgh");
}
a) 9
b) 8
c) 2
d) programul ciclează.
e) programul este greșit deoarece șirul dat ca parametru actual nu corespunde ca lungime cu parametrul formal a al funcției F.
16. De la tastatură se citesc trei numere reale a, b, c. Dacă cele trei numere pot forma un triunghi, să se afișeze pe ecran un mesaj corespunzător: echilateral, isoscel, dreptunghic, oarecare.
Între laturile unui triunghi a, b, c există următoarele relații: fiecare latură este mai mică decât suma celorlalte două, și mai mare decât modulul (valoarea absolută) diferenței celorlalte două:
|b-c|<a<b+c
Deci trei segmente pot forma un triunghi numai dacă respectă aceste inegalități.17. Din fișierul date.in se citesc patru numere întregi x, y, u, v, separate prin spații. Să se determine maximul și minimul valorilor citite și apoi să se scrie aceste valori în fișierul date.out pelinii distincte.
18. Se citesc n numere întregi. Să se determine și să se afișeze:
a) câte din ele sunt pare;
b) suma elementelor pozitive;
c) valoarea maximă.
19. Din fișierul date.in se citesc p numere naturale. Să se afișeze suma divizorilor fiecărui număr, pe linii distincte, în fișierul date.out.
20. Fie n un număr natural nenul. Calculați valoarea expresiei
E=(1-1/2^3)(1-1/3^3)...(1-1/n^3)
21. Să se scrie un program pentru afișarea triunghiului de numere alăturat, unde n este un număr natural >=5 citit de la tastatură:
1
1 2
1 2 3
1 2 3 4
.....
1 2 3 4 5 ...n
22. Prelucrarea elementelor unei secvențe de numere întregi:
Scrieți o funcție care returnează:
- numărul elementelor negative dintr-o secvență de numere întregi citită de la tastatură.
- numărul elementelor pare,
- numărul elementelor prime,
- numărul pătratelor perfecte;
- suma elementelor pare,
- suma elementelor impare,
- suma elementelor prime,
- suma elementelor pătrate perfecte.
- afișează numerele impare mai mici decât un număr dat n în ordine inversă (funcție void)
- maximul dintre elementele șirului
- minimul dintre elementele șirului
- verifică dacă o valoare dată există în secvență
Scrieți o funcție care returnează:
- suma cifrelor unui număr
- numărul cifrelor pare ale unui număr
- produsul cifrelor unui număr
- afișarea oglinditului unui număr (funcție void)
- testează dacă un număr este prim
- x^k, folosind relația x^k=x*(x^(k-1))
- verifică dacă un număr este palindrom
Scrieți o funcție recursivă care returnează:
- Numărul vocalelor dintr-un șir de caractere
- Numărul consoanelor dintr-un șir de caractere
- verifică dacă o literă dată există în cuvânt
- Afișarea oglinditului unui cuvânt (funcție void)
- Transformarea din litere mici în litere mari (funcție void)
- Afișează literele alfabetului în ordine inversă (void)
- Afișează în ordine inversă doar cifrele care apar într-un cuvânt citit de la tastatură (void)
- Afișează în ordine directă literele și semnele speciale care apar într-un cuvânt
citit de la tastatură - fără cifre (void) - Verifică dacă un cuvânt este palindrom
- Verifică dacă un cuvânt este anagrama altui cuvânt
Tablouri
Organizarea datelor în tablouri unidimensionale (vectori)
În situațiiile în care problema de rezolvat implică mai multe date cu aceeași semnificație, este preferabil ca în loc să definim un număr mare de variabile cu nume distincte, să definim o singură variabilă de tip tablou (sau vector) cu mai multe componente, identificabile printr-un număr de ordine.
De exemplu, dacă pe parcursul unei călătorii cu mașina vrem să memorăm în program toate alimentările de pe traseu, este preferabil ca, în loc de 10 variabile numerice diferite, de exemplu a1, a2, a3,... care să primească valori concrete exprimate în numărul de litri de combustibil, să avem un vector A cu mai multe componente.
Elementele individuale ale vectorului au un aspect comun: semnificația. De aici rezultă că ele vor memora date de același tip, cu alte cuvinte sunt omogene. Tablourile sunt structuri de date omogene.
În memoria calculatorului, elementele unui vector se memorează unul după altul:
Compilatorul trebuie să cunoască încă din faza de proiectare capacitatea maximă pe care poate să o atingă tabloul. În timpul execuției, programul va folosi efectiv doar locațiile necesare potrivit problemei, deși compilatorul alocă în întregime toată memoria solicitată pentru depozitarea tabloului.
Identificarea unui element particular al tabloului se face pe baza numelui tabloului și a indicelui elementulu scris între paranteze pătratei. Indicele este numărul de ordine, începând cu 0 și terminând cu n-1, unde n este numărul efectiv de elemente ocupate.
Exemplu: A[0] este primul element, A[1] este al doilea, etc.
Implementarea în C++
Alocarea tabloului pentru o dimensiune acoperitoare (să presupunem că nu vor fi mai mult de 20 de alimentări):
Int a[20]; // tabloul are numele a și un număr maxim de 20 de elemente.
Memorarea unei valori în tablou:
a[3]=15; // elementul a[3] (al 4-lea în ordine) primește valoarea 15
Afișarea unui element din tablou:
cout<<a[3];
Includerea unui element într-o expresie:
int consum_total;
consum_total+=a[3]; // se adaugă valoarea lui a[3] la consum_total.
În practică, se vor folosi indici sub forma de variabile întregi.
Programul următor realizează alocarea unui vector, memorarea unor valori în el, totalizarea valorilor și afișarea totalului.
#include <iostream>
using namespace std;
Int a[20];
Int n,i,total=0;
Int main()
{
i=0;
do
{
cout<<”a[“<<i<<”]”;
cin>>a[i];
i++;
}while(a[i-1]>0&&i <20);
n=i-1;
for(i=0;i<=n ; i++)total+=a[i];
cout<<”total =”<<total;
}
APLICAȚII
- Un tren de marfă poate avea cel mult 20 de vagoane. Fiecare vagon poate transporta o încărcătură de maxim 5000 Kg. Realizați un program pentru rezolvarea următoarelor cerințe:
- Introducerea și afișarea încărcăturii fiecărui vagon;
- Afișarea vagoanelor încărcate la întreaga capacitate;
- Afișarea vagoanelor cu cea mai mică încărcătură;
Construiți date de test pentru verificarea fiecărui program.
2. Scrieți un program pentru introducerea și afișarea caracter cu caracter a codului numeric personal.
3. Se cunoaște temperatura înregistrată zilnic la stația meteo locală, timp de n zile. Scrieți un program care determină temperatura maximă, temperatura minimă și zilele în care a fost atinsă temperatura medie. Scrieți date de test pentru verificarea programului.
4. Cunoscând numărul de locuitori din n orașe, se dorește determinarea numărului de orașe a căror populație depășește o valoare p specificată. La o singură execuție a programului pot fi specificate mai multe valori p, până la introducerea valorii 0, având semnificația sfârșit prelucrare.
5. Clienții unui magazin on-line au la dispoziție oferta cu prețurile pentru cel mult 25 de tricouri imprimate cu formații de muzică rock. Fiecare cumpărător introduce cantitatea din modelul ales. Realizați un program care afișează valoarea totală a încasărilor de la toți cumpărătorii dintr-o singură sesiune (execuție a programului). Indicație: sunt necesare 2 tablouri, unul pentru prețuri și unul pentru cantitățile comandate.
6. Un cod poate fi format din cel mult 20 de caractere cifre și litere mari. Să se formeze un cod nou care să înceapă cu literele primului cod grupate la început, urmate de cifrele acestuia. Exemplu: cod=17A3R9E cod nou = ARE1739.
7. După n aruncări cu două zaruri, se cunoaște numărul de puncte obținute la fiecare aruncare. Suma punctelor formează punctajul aruncării. Să se determine numărul de apariții ale fiecărui punctaj. Exemplu:
Date de intrare: zarul 1 zarul 2
6 4
5 3
5 5
4 3
2 6
Date de ieșire: Punctaj Număr de apariții
10 2
8 2
7 1
6 1
Algoritmi de sortare
Problemă: să se rearanjeze elementele unui vector în ordinea crescătoare a mărimii.
Rezolvare: Trecerea elementelor de la configurația inițială (vector neordonat) la configurația finală (vector ordonat) se face prin compararea elementelor învecinate și schimbarea poziției lor astfel încât valorile mici să se deplaseze spre stânga, iar valorile cele mari spre dreapta.
Metoda bulelor (Bubble sort)
.Vectorul se parcurge de mai multe ori de la primul la penultimul element, până când, la ultima parcurgere, vectorul este găsit ordonat (nu se mai face nici o inversiune).
Este folosită o variabilă logică numită invers, și un indice întreg i pentru accesarea elementelor șirului.
Vectorul V are n elemente.
#include <iostream>
using namespace std;
Int V[100];
Int n;
bool invers=false;
Int main()
{
cin>>n;
for(int i=1; i<=n;i++) cin>>V[i];
do
{
invers=false;
for(int i=1; i<=n-1;i++)
{
if(V[i]>V[i+1]
{
//inverseaza vecinii
Int aux=V[i+1];
V[i+1]=V[i];
V[i]=aux;
invers=true;
} //if
} //for
} while(invers);
cout<<endl<<”sirul ordonat:”<<endl;
for(int i=1;i<=n;i++)
cout<<V[i]<<” “;
}
2. Metoda selecției
Se alege cel mai mic element din vector și se așează pe prima poziție. Se repetă această operație pentru subșirul rămas, care este din ce în ce mai scurt, până când sbșirul rămas are lungimea 1.
Se foloseste o variabila intreaga min care va retine valoarea minima dintr-un subsir, si o variabila intreaga poz, care va retine pozitia acelei valori minime. Pentru inceput, se va considera ca valoarea V[1] este valoarea minima, urmand a se inlocui cu minimul efectiv dupa ce se viziteaza toate elementele de la 2 la n. Se mai foloseste variabila i, care va retine locul unde am ajuns cu construirea subsirului sortat. Pentru inceput i=1. Sirul deja sortat se afla intre pozitiile 1 si i.
#include <iostream>
using namespace std;
Int V[100];
Int n;
Int main()
{
cin>>n;
for(int i=1; i<=n;i++) cin>>V[i];
Int min=V[1];
Int poz=1;
Int i=1;
for(i=1;i<=n-1;i++)
{
min=V[i];
poz=i;
for(int j=i+1;j<=n;j++)
{
if(V[j]<min)
{
poz=j;
min=V[j];
} //if
} //for
//aduce valoarea minima pe pozitia i prin interschimbare
V[poz]=V[i];
V[i]=min;
} //for
cout<<endl<<”sirul ordonat:”<<endl;
for(int i=1;i<=n;i++)
cout<<V[i]<<” “;
} //main
Probleme
- Problema rucsacului, prin metoda Greedy. Într-un rucsac pot încăpea maxim G kilograme. Într-o încăpere există n obiecte, cu greutăți cunoscute. Se cere să se transporte toate obiectele din încăpere cu ajutorul rucsacului, făcând cât mai puține drumuri. Indicație: mai întâi se citesc cele n greutăți într-un vector V, apoi se sortează vectorul V crescător prin oricare din cele două metode învățate, apoi se încarcă obiectele în rucsac în ordinea greutăților, în mod repetat, ținându-se seama de capacitatea de transport G.
- Căutare secvențială într-un vector neordonat. Organizatorii unui eveniment cu premii au distribuit participanților (cel mult 100) câte un tichet pe care se află înscris un număr mai mic sau egal cu 999. Fiecare participant este identificat prin numărul său de ordine. La sfârșit, posesorul tichetului cu numărul nr extras la tombolă este declarat câștigător. Se cere să se afle câștigătorul care deține tichetul nr. Se poate întâmpla să nu existe nici un câștigător, caz în care se va afișa un mesaj corespunzător.
- Căutare secvențială în vector ordonat. După desfășurarea Olimpiadei de informatică a fost afișat clasamentul participanților, în ordinea descrescătoare a punctajului. Să se scrie un program care să afișeze pe ce poziție se află în clasament concurentul care a obținut punctajul p, introdus de la tastatură. Se poate întâmpla ca nimeni să nu fi obținut acest punctaj, caz care se va semnala cu un mesaj corespunzător.
- Căutare binară în vector ordonat. Rezolvați problema 3 prin metoda căutării binare (divide et impera).
- Căutare secvențială într-un vector neordonat.. Meteorologii de la stația meteo au înregistrat temperatura timp de n zile (n<=30). Determinați prima zi în care a fost înregistrată temperatura t. Dacă această temperatură nu a fost înregistrată, se va afișa un mesaj corespunzător.
Niciun comentariu:
Trimiteți un comentariu