• No results found

C++ Lektion Filhantering

N/A
N/A
Protected

Academic year: 2021

Share "C++ Lektion Filhantering"

Copied!
5
0
0

Loading.... (view fulltext now)

Full text

(1)

C++ Lektion Filhantering

Teori

Vi är bekanta med ett antal objekt för läsning och skrivning på bildskärmen, nämligen cout och cin. De hanterar automatiskt om vi ska läsa eller skriva en "följd av bytes" (i C++ begreppet "ström"). För att komma åt dessa objekt inkluderade vi filen iostream .

När det gäller filer behöver vi tillgång till klasserna ifstream(infilestream) och ofstream(outfilestream). För att få det inkluderar vi filen fstream .

När vi arbetar med filer gör vi i princip som när vi skriver och läser mot skärmen. Vi kan bara göra en sak, läsa eller skriva, mot en och samma fil. Det här gör att vi måste deklarera en variabel som antingen "läsa från"-fil eller "skriva till"-fil. Man deklarerar filen, öppnar filen, arbetar mot filen och slutligen stänger man filen.

Läsning från fil

Vi skiljer på formaterad och oformaterad läsning. Den förra innebär att vi vet vad och hur data (informationen) ligger lagrad på filen medan den senare vet vi inget om. Strategin är då att för den formaterade använder vi inläsningsoperatorn >> och för den oformaterade använder vi speciella funktioner som t.ex. get och getline.

Skriva till fil

På motsvarande sätt skiljer vi på formaterad och oformaterad skrivning.

Mer om filer

Vi kommer enbart att använda oss av textfiler i den här kursen. Det innebär att informationen ligger lagrad som bytes som innehåller ASCII-koden för ett tecken. Informationen ligger lagrad som vi är vana att se den i en ordbehandlare, d.v.s. med en radstruktur. När vi kompilerar och länkar våra program vi skriver skapas en exekverbar exe-fil. Den kallas binärfil, vilket är en annan typ av fil.

Vi har enbart tagit upp de två fallen att enbart läsa från eller skriva till en fil. Ofta kan det ju vara så att man vill ändra i en befintlig fil och hoppa fram och tillbaka i den. Det finns funktioner för att skapa denna direktaccess. Detta ligger utanför denna kurs.

Denna kod läser tecken för tecken

#include <iostream> //strömmarna cin/cout

#include <fstream> //filströmmar using namespace std;

main() {

int n=0;

char tecken;

ifstream infil("min_fil.txt"); //öppna filen som läsfil

while (infil.get(tecken)) //läs in ett tecken, så länge det går bra genereras värdet true till villkoret {

cout.put(tecken); //och skriv ut det på skärmen if (tecken == '\n')

n++;

}

infil.close(); //stäng infilen cout<<”\n\nFilen innehöll ”<<n<<” rader\n\n”;

system("PAUSE");

}

Lägg till denna kod och du får ett program som kopierar en textfil tecken för tecken

ofstream utfil("ny_fil.txt"); //öppna filen som skrivfil

utfil.put(tecken); //och skriv på nya texfilen jämför strömmarna cout/utfil utfil.close(); //stäng nya utfilen

(2)

Till filhantering hör alltid felhantering, en filläsning/skrivning som inte fungerar ska ju inte krascha hela programmet. Felhantering kan göras på flera sätt vi tittar på ett enkelt sätt, vi använder oss av

filströmmens namn som ”flagga” (failbit true eller false), fungerar öppningen av filen sätts flaggan till true anars false.

Vi bygger om koden ovan med felhantering

if(!infil) // vi läser av flaggan

cout << "filen kan ej läsas! " << endl;

else if(!utfil) // vi läser av flaggan cout << "filen kan ej skrivas! " << endl;

else // här kommer gamla koden som körs om inte if/elseif körts

Vi tittar vidare på läsning och skrivning till textfil och läser/skriver nu hela meningar. Här får vi felhanteringen på köpet i inmatningssatsen ( while (infil.getline(klyscha,99)) ).

#include <iostream> //strömmarna cin/cout

#include <fstream> //filströmmar using namespace std;

main() {

char klyscha[100]; //textsträng

ifstream infil("klyschor.txt"); //öppna filen som läsfil while (infil.getline(klyscha,99)) //läs in en filrad till klyscha cout<<klyscha<<endl //och skriv ut den på skärmen infil.close(); //stäng infilen

ofstream utfil("klyschor.txt"); //öppna samma fil som skrivfil, cout<<"Mata in dina bästa klyschor, avsluta med CTRL+Z: ";

while (cin.getline(klyscha,99))

utfil<<klyscha<<endl; //skriv till filen p.s.s. som för cout

utfil.close(); //stäng utfilen

system("PAUSE");

}

där klyschor.txt från början har följande utseende:

Det finns inga dåliga väder bara dåliga kläder Den som väntar på något gott väntar aldrig för länge Kan något gå fel så gör det det

Längre steg och oftare

Vi provkör. Förhoppningsvis funkar koden men………

Vi vill kanske att de nya klyschorna läggs till de gamla, det gör vi med koden ios::app (app=append)

ofstream utfil("klyschor.txt", ios::app);

Att göra:

Börja med och se till att få exemplen i texten ovan att fungera Läs tecken för tecken från fil.

Kopiera textfil tecken för tecken.

Skriva och läsa meningar Studera noga bifogad exempelkod, ex1 ex2.

Läs Läs avsnitten på webben.

Öva Se nedan

(3)

Övningar Övning 1

Skriv ett program som läser in resultatet (från två prov) från en separat fil (resultat.txt). Ditt program ska beräkna medelvärdet på båda proven och skriva ut resultatet. Ditt program ska också beräkna totalpoängen för varje deltagare och skriva ut namn och totalpoäng.

Filen resultat.txt ser ut enligt följande (som du skriver in och spar i samma mapp som ditt program):

(Om du vill kan du lägga in på första raden, antalet elever, dvs hur många poster som kommer senare i filen!!) Kalle 12 24

Kajsa 14 19

Musse 9 28

Långben 1 37

Mimmi 21 22

Övning 2

Lägg till i ditt program så att det även skriver ut totalresultatet på en fil som heter total.txt.

Övning 3

Skriv ett program som analyserar en C++-fil (.cpp-fil) och ser hur många rader filen består av, hur många {-tecken, och }-tecken som finns, samt hur många (-tecken och )-tecken och ;-tecken. Skriv ut resultatet snyggt på skärmen.

Övning 4

Skriv ett program som läser in en text från terminalen och sparar texten i en ny textfil med namnet minfil.txt . Den nya textfilen ska ha samma radstruktur som det som skrivs in på terminalen. Dessutom ska alla små bokstäver som läses in översättas till stora.

Övning 5

Man har sparat ett hemligt meddelande i en textfil med namnet hemlig.txt . För att ingen obehörig utan vidare ska kunna förstå meddelandet har det kodats. Man har översatt varje bokstav i meddelandet till någon annan bokstav med hjälp av en tabell ( kodningstabellen på en egen fil) :

Kodbokstav: guwyrmqpsaeicäbönoåzlfhdkjxtv Klartext: abcdefghijklmnopqrstuvwxyzåäö

Om t ex filen innehåller texten ”egiir ftäzgo bäåygq ei zalqb” så betyder det ”kalle väntar onsdag kl tjugo”. Skriv ett program som läser filen med det hemliga meddelandet och skriver ut det i klartext. Programmet ska börja med att läsa in kodningstabellen.

Utöka ditt program så att du kan välja om du vill skapa en fil med hemlig kod eller läsa en fil med hemlig kod.

Övning 6

Skriv ett personregister med minst dessa fält , efternamn, förnamn, adress, postadress, telefon. Registret ska jobba mot en flerdimensionell array. Registret ska vara menystyrt med följande funktioner. Registret ska ha felhantering.

1. Inläsning av post 2. Visning av poster 3. Sortering 4. Ändra i post 5. Ta bort post 6. Läsa från fil 7. Skriva på fil

Tillägg: sortera på valfritt fält, starta från inifil som håller reda på senast använda register och andra inställningar.

(4)

Ex 1:

// filform.cpp

//*****************************************************************

//** Formaterad inmatning **

//vi vet hur data ligger lagrat på filen, vi använder operatorn >>

//t ex vill vi läsa följande fil testsiff.txt

// --- // 3

// KALLE 43

// MUSSE 21

// LÅNGBEN 35

// ---

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

int main() {

int r, rader;

double summa=0, points;

string namn;

ifstream infil("testsiff.txt");

infil>>rader;

cout<<rader<<endl; //Kan kommenteras bort när testningen är klar for (r=1;r<(rader+1);r++)

{

infil >> namn >> points;

summa=summa+points;

cout << namn <<" "<< points<<endl;

}

cout<<endl<<"Medelpoängen var "<<summa/rader<<" poäng."<<endl; //Kan kommenteras bort infil.close();

cout<<"\n*** TACK FÖR IDAG! ***\n"<<endl;

system("PAUSE");

return 0;

}

Ex2.

// filoform.cpp

//*****************************************************************

//** Oformaterad inmatning **

//vi vet inte hur data ligger lagrat på filen,vi använder här funktionen get(c) där c är en //char-variabel, t ex vill vi läsa en cpp fil och undersöka några saker

#include <iostream>

#include <fstream>

using namespace std;

int main() {

ifstream infil;

char infilnamn[30], c;

int tecken=0,rader=0, vseagull=0, hseagull=0;

cout<<"Vilken cpp-fil ska vi analysera?\n";

cin>>infilnamn;

infil.open(infilnamn); //OBS! open-funktionen vill ha en textsträng av typen teckenarray //en string-variabel fungerar inte !! Tyvärr!!

while (infil.get(c) ) //läser in nästa tecken i strömmen till c,

{ //ger EOF om filslut påträffas, dvs värdet av eof läggs i c, (flaggan eofbit sätts) cout<<c; //För att se att det är rätt fil, kommenteras bort om man vill

tecken++;

if ( c=='\n' ) rader++;

else if ( c=='{' ) vseagull++;

else if ( c=='}' ) hseagull++;

}

infil.close();

cout<<" Antal rader = "<<rader<<endl;

cout<<" Antal vänstermåsar = "<<vseagull<<endl;

cout<<" Antal högermåsar = "<<hseagull<<endl;

cout<<"\n*** TACK FÖR IDAG! ***\n"<<endl;

system("PAUSE");

return 0;

(5)

Ex3:

#include <iostream>

#include <fstream>

#include <stdlib.h>

using namespace std;

void formaterad(char infilnamn[]);

void oformaterad(char infilnamn[]);

int alternativ(int start);

int main() {

int start=1;

while (start) {

start= alternativ(start);

}

cout<<"*** TACK FÖR IDAG! ***"<<endl;

system("PAUSE");

return 0;

}

int alternativ(int start) {

char infilnamn[30], val;

ifstream infil;

cout<<endl<<"*******************************"<<endl;

cout<<" Vad vill du göra med filen? "<<endl;

cout<<" 1: Läsa in en formaterad fil."<<endl;

cout<<" 2: Läsa in en oformaterad fil."<<endl;

cout<<" 3: SLUTA"<<endl;

cin>>val;

cout<<endl;

switch(val) {

case '1':

cout<<" Ange infilnamn : ";

cin>>infilnamn;

cout<<endl;

formaterad(infilnamn);

break;

case '2':

cout<<" Ange infilnamn : ";

cin>>infilnamn;

cout<<endl;

oformaterad(infilnamn);

break;

default:

start=0;

}

return start;

}

//*****************************************************************

//** Formaterad inmatning **

// Se Ex1

//vi vet hur data ligger lagrat på filen //vi använder operatorn >>

//t ex vill vi läsa följande fil testsiff.txt //---

//3

//KALLE 43 //MUSSE 21 //LÅNGBEN 35 //---

void formaterad(char infilnamn[]) {

ifstream infil;

char namn[20];

int r, rader;

double points, summa=0;

infil.open(infilnamn);

infil>>rader;

//cout<<rader<<endl;

for (r=1;r<(rader+1);r++) {

infil >> namn >> points;

summa=summa+points;

cout << namn <<" "<< points<<endl;

}

cout<<endl<<"Medelpoängen var "<<summa/(r-1)<<"

poäng."<<endl;

infil.close();

}

//*****************************************************************

//** Oformaterad inmatning **

// Se Ex2

//vi vet inte hur data ligger lagrat på filen

//vi använder här funktionen get(c) där c är en char- variabel

//t ex vill vi läsa en cpp fil och undersöka några saker void oformaterad(char infilnamn[])

{

ifstream infil;

char c;

int tecken=0,rader=0, vseagull=0, hseagull=0;

infil.open(infilnamn);

while (infil.get(c) ) //läser in nästa tecken i strömmen till c,

{ //ger EOF om filslut påträffas, dvs värdet av eof // läggs i c, (flaggan eofbit sätts)

// cout<<c;

tecken++;

if ( c=='\n' ) rader++;

else if ( c=='{' ) vseagull++;

else if ( c=='}' ) hseagull++;

}

cout<<" Antal tecken = "<<tecken<<endl;

cout<<" Antal rader = "<<rader<<endl;

cout<<" Antal vänstermåsar = "<<vseagull<<endl;

cout<<" Antal högermåsar = "<<hseagull<<endl;

infil.close();

}

References

Related documents

Hans kritik mot Eliasson uppmärksammas sedan och når de traditionella medierna i form av en artikel på Expressen där Jomshof uttalar sig: “Alltid tyckt han är

Kvinna 55 år med neurologisk sjukdom söker för feber och

Den huvudfrågeställning vilken styrt analysarbetet är: Vilka egenskaper och kompetenser konstrueras som viktiga för lärare att inneha i Maciej Zarembas artikelserie Hem till

Vi anser också att med den kunskap vi har fått genom detta arbete så uppfattar vi att med hjälp av tecken så blir man mer rättvis mot de barn som inte har något språk,

De bilder som vi tar till oss som barn har stor betydelse för vår framtida tolkning av visuella tecken.. Den grafiska formgivningen formar även vår blick och man kan därför tala om

[r]

Vi brukar inte skriva ut plustecknet framför tal men det

Syftet är inte att göra narr av Stravinskij eller att vara respektlös för sakens skull – utan snarare att förhålla mig kritisk till tanken om GENIET som jag nämnt