110 likes | 226 Views
WEJŚCIE/WYJŚCIE, cd. 1. Formatowane przekształcenia w pamięci. Funkcje printf i scanf kierują na standardowe we/wy. Istnieją ich odpowiedniki kierujące wyjście na „wyjście wirtualne” oraz czytające z „wejścia wirtualnego”. Wirtualne - tzn. w pamięci
E N D
WEJŚCIE/WYJŚCIE, cd. 1. Formatowane przekształcenia w pamięci. Funkcje printf i scanf kierują na standardowe we/wy. Istnieją ich odpowiedniki kierujące wyjście na „wyjście wirtualne” oraz czytające z „wejścia wirtualnego”. Wirtualne - tzn. w pamięci komputera w postaci odpowiedniego łańcucha znaków. Zatem wyniki działań mogą być zapamiętywane w odpowiednich zmiennych (tablicach) a następnie na końcu „hurtem” kierowane np. na ekran. Odpowiednikiem funkcji printf jest sprintf, zaś funkcji scanf - sscanf. Obie te funkcje maja postać: sprintf/sscanf(lancuch,``control’’, agr1,arg2,...) Ich działanie jest nastepujące: argumenty arg1,agr2,.. są przekształ- cane zgodnie z opisem zawartym w argumencie kontrolnym control i zapisywane do lancuch. Przy czytaniu pobieramy wartość lancuch przekształcamy ją zgodnie z „control” i „rozdzielamy” po argumentach
Zadanie 18 Wybierz dowolny program z programów napisanych poprzednio i zmodyfikuj go tak aby zastosować funkcje sprintf lub/i sscanf
PLIKI - we/wy sekwencyjne Instrukcja otwarcia pliku ma postać cid=fopen(nazwa,atrybuty) gdzie nazwa jest WSKAŹNIKIEM do nazwy pliku (deklarowanym jako np. char *nazwa, zmienna cid jest WSKAŻNIKIEM do „zmiennej plikowej” (ang. channel identifier), deklarowanym jako FILE *cid; atrybuty - to “r” - plik to czytania; “w”- zapis (nadpisywanie!), “a” -zapis, ale dołączanie do istniejącego pliku. Dokładniej w systemie operacyjnym Unix/Linux cid jest wskaźnikiem do STRUKTURY predefiniowanego typu FILE. Funkcje związane z operacjami na plikach: getc, putc, fscanf, fprintf, (analogi getchar,potchar,scanf,printf) oraz fclose Przykład użycia funkcji plikowych
program oblicza kwadraty kolejnych liczb main() { FILE *cid; int n; cid=fopen(“kwadraty.dat”, “w”); for(n=1;n<=100;n++); fprintf(cid, “%d %d\n”, n,n*n); flose(cid); } gdybyśmy chcieli zadeklarować nazwę pliku (w celu np. czytania jej funkcją scanf, to deklaracja by była : char *nazwa; .... scanf(“%s”,nazwa); Deklaracja fopen wygląda FILE *fopen(); main() { FILE *cid; int n,v,vsq; cid=fopen(„kwadraty.dat”,”r”); for(n=1;n<=100;n++) { ffscanf(cid, “%d %d”,&v,&vsq); printf(“%d %d”,v,vsq); } fclose(cid); }
Funkcja fclose(cid) - zamknięcie pliku. W momencie otwarcia z jednym cid może być związana tylko jedna nazwa pliku; po zamknięciu pliku „channel identifier” może być „powtórnie użyty” (w FORTRANIE zamiast zmiennej cid stosujemy numery „kanałów”) Funkcje getc(cid) i putc(cid,nazwa_zmiennej_typu_char_lub_int) wyprowadzają i wprowadzają znak z/do pliku. Np. program „przepisujący” jeden znak z pliku1 do pliku2 ma postać:
Slowa stdin i stdout definiują standardowe wejście i wyjście. Stosowane poprzednio funkcje putchar() i getchar() to w istocie definicje: #define getchar() getc(stdin) #define putchar(c) putc(c,stdout) main() { FILE *cid1,cid2; int n; cid1=fopen(“plik1”, “r”); cid2=fopen(“plik2”, “w”); n=getc(cid1); putc(n,cid2); flose(cid1); fclose(cid2); }
Przykład programu kopiującego plik1 na plik2 main() { FILE *cid_in,cid_out; char c,wejscie[20],wyjscie[20]; printf(“podaj plik wejsciowy\m”); scanf(“%s”,wejscie); printf(“podaj plik wyjsciowy\m”); scanf(“%s”,wyjscie); cid_in=fopen(wejscie,”r”); cid_out=fopen(wyjscie,”w”); while((c=getc(cid_in))!=EOF) putc(c,cid_out); fclose(cid_in); fclose(cid_out); } nazwy max 20 znaków, a jak zrobić, aby dowolne? wskazówka: wwskaźniki! A co zrobić, aby dopisywało do istniejącego pliku?
Zadanie 19 napisz program, któren przepisuje z istniejącego pliku 1 linię do plik1, 2 - do plik2, 3- plik3, 4- plik4, 5-plik5, 6-plik1, 7-plik2, 8-plik3, itd. Przepisywanie z pliku do pliku ma być funkcją
stderr - standardowe wyjście komunikatu o błedach. Dane wysyłane na stderr pojawią się na końcówce (terminalu) uzytkownika nawet wtedy, gdy standardowe wyjście będzie skierowane gdzie indziej. Dla przykładu fprintf(stderr,” BŁĄD, nie mode otworzyć pliku!\n”); wyśle komunikat na ekran, nawet gdy stdout skierowane zostało na np. na drukarkę Funkcja exit i _exit (#include <stdlib.h>) Funkcja exit(int status) powoduje zakończenie działania programu. Wszystkie dane z buforów przenioesione do plików, pliki zamknięte, działanie programu zakończone. Warstość zmiennej status informuje o sukcesie (status=0) lub „problemach” (status<>0) z zakończeniem. UWAGA: wartość status zależna od implementacji programu, czasem to nie int ale łańcuch „EXIT_SUCCESS” LUB „EXIT_FAILURE”. Funkcja _exit() - natychmiastowe zakonczenie, bez zamykania, kopiowania buforów, etc. Obie funkcje są w <stdlib.h>
Inną funkcją ze <stdlib.h> jest system, system(const char *s) funkcja wywołuje komendę systemową, np. system(“moj.bat”); wywołuje wykonanie skryptu/programu użytkownika z pliku mój.bat (oczywiście plik ten musi znajdować się w tym samym katalogu, co program - albo trzeba podac np.: ~/student/home/Documents/mój.bat) Omówiony poprzednio program przepisywał jeden plik na drugi. Ale przytrafić się może, że np.. plik, który chcemy czytać nie istnieje. Program powinien „przewidzieć” taką możliwość. Podany niżej przykład ilustruje w jaki sposób ustrzec się błędów tego typu
main() { FILE *cid_in,cid_out; char c,wejscie[20],wyjscie[20]; printf(“podaj plik wejsciowy\m”); scanf(“%s”,wejscie); printf(“podaj plik wyjsciowy\m”); scanf(“%s”,wyjscie); if((cid_in=fopen(wejscie,”r”))==0) { printf(“ nie ma pliku %s\n”,wejscie) exit(0)}; if((cid_out=fopen(wyjscie,”w”))==0) { printf(“ nie mogę otworzyc %s\n”,wyjscie) exit(0)}; while((c=getc(cid_in))!=EOF) { if((putc(c,cid_out)==EOF){ printf(“nie mogę zapisać, disk error\n”); exit(0)}; fclose(cid_in); fclose(cid_out); }