Lecție pentru bacalaureat · Informatică

Fișiere text

Clasa a XII-a

Ideile de bază pe scurt și, unde există, exercițiile din subiectele de BAC care le verifică. Lecția completă, animată, cu grile și exerciții corectate, e în aplicația Tomomi.

Pe scurt

Formulă

Șablon: citirea unui fișier până la sfârșit

Nu ai nevoie să știi câte valori sunt:

#include <fstream>
using namespace std;

ifstream fin("bac.in");
int x;
while (fin >> x) {
    // prelucrează x
}
fin.close();
Idee

Idee: citirea îți spune când s-a terminat

fin >> x are o valoare logică: adevărat dacă a citit ceva, fals la sfârșitul fișierului. De aceea while (fin >> x) se oprește singur, iar pe un fișier gol corpul buclei nu se execută niciodată - motiv pentru care acumulatorii se inițializează ÎNAINTE de buclă.

Formulă

Sintaxă: scrierea într-un fișier

fout se folosește ca cout, dar separatorii sunt treaba ta:

ofstream fout("bac.out");
fout << rezultat;
fout << x << " ";
fout << x << "\n";
fout.close();
Sfat

Capcana: cout nu scrie în fișier

cout scrie pe ecran, fout scrie în fișier: sunt fluxuri complet separate, iar la BAC se punctează conținutul FIȘIERULUI. Al doilea pericol este separatorul: fără spațiu sau linie nouă, fout << 1; fout << 2; produce 12, adică un singur număr.

Formulă

Șablon: Subiectul III complet

Deschide, inițializează, parcurge o dată, scrie, închide:

ifstream fin("bac.in");
ofstream fout("bac.out");
int x;
int rezultat = 0;
while (fin >> x) {
    // actualizează rezultat
}
fout << rezultat;
fin.close();
fout.close();
Sfat

Capcana: valoarea inițială a maximului

Suma și contorul pornesc de la 0, mereu corect. Maximul NU pornește de la 0: pe un fișier cu numai valori negative ai scrie 0, o valoare care nici nu se află în fișier. Pornește de la un număr foarte mic sau de la prima valoare citită. Simetric pentru minim.

Din subiectele de BAC

Exerciții reale din subiectele anilor trecuți. Încearcă-le singur înainte să deschizi rezolvarea.

Un tânăr pasionat de călătorii are o listă cu muzee virtuale și, pentru fiecare, câte un singur interval orar, în care acesta poate fi vizitat online, gratuit. Tânărul dispune zilnic de același interval orar pentru vizite; un muzeu este convenabil dacă poate fi vizitat online gratuit în timpul disponibil și dacă pentru vizită îi poate aloca cel puțin o oră. Muzeele din listă sunt numerotate cu valori naturale consecutive, începând cu 1, și cel puțin unul este convenabil.

Fișierul text bac.in conține cel mult 10510^5 linii, iar pe fiecare linie câte o pereche de numere, reprezentând limitele câte unui interval orar: pe prima linie intervalul orar de care tânărul dispune zilnic, iar pe fiecare dintre următoarele linii, intervalul orar de vizitare gratuită pentru câte un muzeu, în ordinea din listă. Limitele intervalelor sunt ore fixe, numere naturale din intervalul [8,22][8,22], iar cele aflate pe aceeași linie a fișierului sunt în ordine strict crescătoare și sunt separate printr-un spațiu.

Se cere să se afișeze pe ecran, separate printr-un spațiu, două valori, reprezentând numărul de muzee convenabile, respectiv numărul de ordine al ultimului astfel de muzeu din lista tânărului. Utilizați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

Exemplu: dacă fișierul conține valorile 16 19, 15 18, 17 21, 19 21, 18 20, 12 13, atunci pe ecran se afișează numerele 3 4 (pot fi vizitate trei muzee cu numerele de ordine 1, 2 și 4, în intervalele 16-18, 17-19, respectiv 18-19).

Scrieți programul C/C++ corespunzător algoritmului proiectat.

Vezi rezolvarea

Programul citește din fișier pereche cu pereche, fără să memoreze nimic în plus:

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream f("bac.in");
    int h1, h2, c1, c2, v1, v2;
    int nr = 0, ultim = 0, crt = 0;
    f >> h1 >> h2;
    while (f >> c1 >> c2)
    {
        crt++;
        v1 = (h1 > c1) ? h1 : c1;
        v2 = (h2 < c2) ? h2 : c2;
        if (v2-v1 >= 1)
        {
            nr++;
            ultim = crt;
        }
    }
    f.close();
    cout << nr << " " << ultim;
    return 0;
}

Pe exemplul din enunț, cu intervalul disponibil [16,19][16,19]:

muzeuintervalintersecțiecel puțin o oră?
115-1816-18da
217-2117-19da
319-2119-19nu
418-2018-19da
512-13vidănu

Se afișează 3 4, ca în enunț.

De-a lungul unui traseu montan este utilizată o succesiune de marcaje turistice, care trebuie urmate în acea ordine. Pentru fiecare marcaj se cunoaște cota (înălțimea, măsurată în metri) la care este plasat. Numim scară într-un traseu o secvență de marcaje aflate pe poziții consecutive în cadrul traseului, care au drept cote numere consecutive, ordonate strict crescător. O scară este formată din cel puțin două marcaje, iar lungimea acesteia este egală cu numărul de marcaje care o compun.

Fișierul bac.txt conține un șir de cel mult 10610^6 numere naturale din intervalul [10,104][10,10^4], separate prin câte un spațiu, reprezentând cotele marcajelor turistice din cadrul unui traseu, în ordinea în care se succed în acesta. Se cere să se afișeze pe ecran, separate prin câte un spațiu, în ordine strict crescătoare, cotele corespunzătoare marcajelor unei scări de lungime maximă pe acest traseu. Dacă există mai multe astfel de scări, se afișează cotele uneia dintre ele, iar dacă nu există nicio scară, se afișează mesajul nu exista. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al spațiului de memorie utilizat.

Exemplu: dacă fișierul conține numerele 500 600 601 405 569 570 700 701 625 626 627 520, atunci pe ecran se afișează 625 626 627.

Scrieți programul C/C++ corespunzător algoritmului proiectat.

Vezi rezolvarea
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream f("bac.txt");
    int x, ultCrt = 0, lgCrt = 0, lgMax = 0, ultMax = 0, c;
    while (f >> x)
    {
        if (x == ultCrt + 1)
            lgCrt++;
        else
            lgCrt = 1;
        ultCrt = x;
        if (lgCrt > lgMax)
        {
            lgMax = lgCrt;
            ultMax = x;
        }
    }
    f.close();
    if (lgMax < 2)
        cout << "nu exista";
    else
        for (c = ultMax - lgMax + 1; c <= ultMax; c++)
            cout << c << " ";
    return 0;
}

Programul parcurge fișierul o singură dată (timp liniar) și folosește doar câteva variabile simple (memorie constantă); scara de lungime maximă este reconstituită din ultima sa cotă și lungime. Pe exemplul dat, scările sunt 600-601, 569-570, 700-701 (lungime 2) și 625-627 (lungime 3), deci se afișează 625 626 627.

Un număr natural x este numit prefix al unui număr natural y dacă se obține din acesta prin eliminarea a cel puțin unei cifre de la dreapta sa, și este numit sufix al lui y dacă se obține din acesta prin eliminarea a cel puțin unei cifre de la stânga sa.

Exemplu: 15 este prefix pentru 154 sau 1521, este sufix pentru 3415 sau 5115, dar nu este nici prefix, nici sufix pentru 15.

Fișierul bac.txt conține maximum 10610^6 numere naturale din intervalul [10,104)[10, 10^4), separate prin câte un spațiu. Se cere să se afișeze pe ecran numărul valorilor de două cifre care apar de același număr de ori ca sufix, respectiv ca prefix al numerelor din șirul aflat în fișier. Proiectați un algoritm eficient din punctul de vedere al timpului de executare.

Exemplu: dacă fișierul are conținutul 342 1684 2134 5434 111 98 98 3405 3412 7016 8634 1010 102 310 se afișează pe ecran: 4 (pentru valorile 10, 11, 16, 34).

Scrieți programul C/C++ corespunzător algoritmului proiectat.

Vezi rezolvarea
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ifstream fin("bac.txt");
    int pf[100] = {0}, sf[100] = {0};
    int x, s, p, cnt = 0;
    while (fin >> x)
        if (x > 99) {
            s = x % 100;
            if (s >= 10)
                sf[s]++;
            if (x < 1000)
                p = x / 10;
            else
                p = x / 100;
            pf[p]++;
        }
    fin.close();
    for (int v = 10; v <= 99; v++)
        if (pf[v] == sf[v] && sf[v] != 0)
            cnt++;
    cout << cnt;
    return 0;
}

Fiecare număr de trei cifre are exact un prefix de două cifre ([x/10][x/10]), iar fiecare număr de patru cifre, de asemenea ([x/100][x/100]); sufixul de două cifre este x%100x \% 100, valid doar dacă este cel puțin 10. Algoritmul este liniar: o singură parcurgere a fișierului și doi vectori de frecvență de 100 de elemente. Pentru exemplul dat, valorile numărate sunt 10, 11, 16 și 34, deci se afișează 4.

Toate lecțiile de Informatică

Descarcă

Începe azi. Bacul nu așteaptă.

Descarcă Tomomi pe telefonul copilului tău și pornește perioada de probă gratuită.