In och utmatning Dagens kluring Deklarera en struct
- Slides: 20
In- och utmatning
Dagens kluring Deklarera en struct som kan användas för att representera en rät linje Använd den I main för att deklarera en variabel som du initierar så att den representerar en linje som går genom punken (0, 2) och (4, -2) Hemma (eller om du hinner) skriv en funktion som tar en linje och returnerar för vilket x den skär x-axeln
struct linje//här kan man göra andra val, tex repr med två punkter som linjen { //skär double k, m; }; typedef struct linje Linje; double x. Skarning(Linje rl) { return -rl. m/rl. k; } int main(){ Linje min. Linje; min. Linje. k=-1; min. Linje. m=2; printf("Skarningen med x-axeln sker vid x = %f", x. Skarning(min. Linje)); return 0; }
In- och utmatning • • Strömmar (streams) Binärfiler och textfiler Skriva till textfil med fprintf Läsa från textfil med fscanf Läsa in till bilregistret med fscanf Läsa med fgets Skriva och läsa binärt i bilregistret
Strömmar • En ström betyder en källa för indata (tangentbordet, hårddisk, DVD, nätverksportar, …) eller ett mål för utdata (hårddisk, printer, portar, …) • I C kommer vi åt strömmar via en filpekare och en ström kallas ofta helt enkelt för en fil (vilket det ofta är) • När vi från vårt program vill kommunicera med hårddisken öppnar vi en ström och associerar den till en fil på hårddisken, det gör vi med fopen som returnerar en filpekare • När man har läst eller skrivit klart bör man alltid stänga strömmen. Det gör man med fclose. (Ofta skrivs data inte direkt till filen utan till en buffert, stänger vi då inte filen kanske datat aldrig skriv till den fysiska filen) • Printf som vi tidigare har använt för utmatning använder en ström som alltid är öppen och kallas standard output, stdout. Den skriver normalt till kommandotolken men går att omdirigera • Scanf använder på samma sätt strömmen standard input, stdin • Alla funktioner vi behöver bor i stdio. h så glöm inte #include <stdio. h>
Textfiler och binära filer • Består inte alla filer av 1 or och 0 or? Jo frågan här är hur dessa 1 or och 0 or ska tolkas • I en textfil ska alla ettor och nollor tolkas som ascii-tecken. Dessutom har textfiler radslut (i unix tecken 10 och i windows tecken 13 följt av tecken 10). De kan också ha ett filslutstecken. • I en binärfil skrivs alla 1 or och 0 or ner precis som programmet har dem lagrade i minnet. Hur de ska tolkas beror på vad man skrivit. Har man skrivit ett heltal ska de tolkas så som C skriver heltal. Endast om man vet exakt vilken sorts data som skrivits är det möjligt att tolka filen. Binärfiler saknar också radslut och filslut. • Ett exempel. Ska vi spara heltalet 32767 i en textfil sparar vi 5 tecken vilket tar 5 byte: 0011|00110010|00110111|00110110|00110111 ’ 3’ ’ 2’ ’ 7’ ’ 6’ ’ 7’ Sparar vi samma heltal binärt representeras det i datorn av 2 byte: 01111111|1111111 • Binära filer blir mindre, går fortare att läsa och skriva. Textfiler kan man öppna i en texteditor och se vad de innehåller.
Skriva till textfil med fprintf int main(){ FILE *fp; fp = fopen("min. Fil. txt", "w"); fprintf(fp, "%sn", "Hej på dig. "); fprintf(fp, "%sn", "Hur mår du? "); fprintf(fp, "%dn", 234); fclose(fp); return 0; }
Med kontroll. . int main(){ FILE *fp; fp = fopen("min. Fil. txt", "w"); if(fp!=NULL){//viktigare vid inläsning fprintf(fp, "%sn", "Hej på dig. "); fprintf(fp, "%sn", "Hur mår du? "); fprintf(fp, "%dn", 234); fclose(fp); }else{ printf("Kunde inte öppna filen? "); } }
Läsa från fil med fscanf int main(){ FILE *fp; char s 1[ORDLANGD], s 2[ORDLANGD]; int i; fp = fopen ("min. Fil. txt", "r"); if(fp!=NULL){ fscanf(fp, "%s", s 1); fscanf(fp, "%s", s 2); fscanf(fp, "%d", i); printf("Last: %s, %d", s 1, s 2, i); fclose(fp); Precis som med scanf finns risken att vi läser in längre ord än vad som får plats. } Fördelen är att vi kan använda formatsträngar och return 0; därmed tex heltal. Om vi med säkerhet vet att vi inte } har längre ord än ORDLANGD tex för att vi använt det när vi skrivit filen kan man överväga att använda det ändå
Läsa in med fscanf till bilregistret • Vi förutsätter här att registret är sparat till en fil kallad minfil. txt enligt följande format: volvo 1976 21000 saab 1999 34000 fiat 2013 3000
void las. In(Bil reg[], int *antal) { FILE *fp; fp=fopen("min. Fil. txt", "r"); if(fp!=NULL){ char marke[ORDLANGD]; int arsmodell, mil; while(fscanf(fp, "%s", marke)==1){//Alternativt kan man först i filen skriva antalet bilar och då läsa fscanf(fp, "%d", &arsmodell); // in det och använda en for-loop fscanf(fp, "%d", &mil); reg[*antal]=skapa. Bil(marke, arsmodell, mil); (*antal)++; } fclose(fp); } } int main(){ Bil bil. Register[MAX]; int antal=0; las. In(bil. Register, &antal); skriva. Ut. Register(bil. Register, antal); return 0; }
Snitsigare inläsning • Har man lite koll på formaterad inläsning kan man göra en snyggare fil och dessutom läsa in en hel bil med en inläsning. • Vi arrangerar nu textfilen enligt nedan: volvo 1976 21000 saab 1999 34000 fiat 2013 3000
void las. In(Bil reg[], int *antal) { FILE *fp; fp=fopen("min. Fil. txt", "r"); if(fp!=NULL){ char marke[ORDLANGD]; int arsmodell, mil; while(fscanf(fp, "%s %d %d", marke, &arsmodell, &mil)==3){ reg[*antal]=skapa. Bil(marke, arsmodell, mil); (*antal)++; } fclose(fp); } }
fgets • fscanf har precis som scanf problemet att den riskerar att läsa in större saker än var som får plats. Mycket säkrare då att använda fgets där man kan ange maximalt antal lästa tecken. • Den läser endast strängar så behöver man läsa tex ett heltal får man läsa in heltalet som en sträng och sedan använda funktionen atoi (ascii to int) för att omvandla till ett heltal eller atof för decimaltal. • fgets läser en hel rad och lägger in i en sträng. En egenhet är att den till skillnad från gets också lägger in ’n’ sist i strängen. Detta vill man oftast inte och man får då manuellt byta ut det mot ’ ’. • Man kan använda fgets istället för gets för att läsa från standard in genom att helt enkelt ange stdin som ström och på så sätt få säkrare inmatning
fgets läser från fil • Här kommer ett program där vi läser textrader från en fil till dess att filen är slut. • Eftersom vi inte vill ha med radslutstecknet byter vi också ut det mot ’ ’
#include <stdio. h> #include <string. h> #define ORDLANGD 30 #define MAX 100 int main(){ char s[MAX][ORDLANGD]; fp = fopen ("min. Fil 2. txt", "r"); if(fp!=NULL){ int antal=0; while(fgets(s[antal], sizeof(s[antal]), fp)){ s[antal][strlen(s[antal])-1]='