x - Politechnika Śląska

Transkrypt

x - Politechnika Śląska
Programowanie komputerów
Jacek Lach
Zakład Oprogramowania
Instytut Informatyki
Politechnika Śląska
Plan
• Biblioteka standardowa
• funkcje operujące na łańcuchach
Jacek Lach. Programowanie komputerów
• funkcje operujące na plikach
• funkcje matematyczne
• funkcje pomocnicze
Jacek Lach. Programowanie komputerów
Biblioteka standardowa
• <assert.h> <complex.h> <ctype.h> <errno.h> <fenv.h> <float.h> <inttypes.h> <iohw.h> <iso646.h> <limits.h> <locale.h> <math.h> <setjmp.h> <signal.h> <stdarg.h> <stdbool.h> <stddef.h> <stdint.h> <stdio.h> <stdlib.h> <string.h> <tgmath.h> <time.h> <uchar.h> <wchar.h> <wctype.h> Funkcje operujące na łańcuchach
• Plik nagłówkowy: <string.h>
Jacek Lach. Programowanie komputerów
• Wszystkie funkcje przyjmują, że łańcuchy kończą się znakiem ’\0’
• Większość funkcji nie alokuje pamięci dla łańcuchów
• Ich użytkownik jest odpowiedzialny za dostarczenie miejsca w pamięci na wynik
strcpy()
• char *strcpy(char *dest, const char *src);
Jacek Lach. Programowanie komputerów
• Kopiuje łańcuch src do dest
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[10];
char *str1 = "abcdefghi";
strcpy(string, str1);
printf("%s\n", string);
return 0;
}
strcpy() ­ implementacja
/* strcpy: kopiowanie t do s; wersja
z tablicami i indeksami */
Jacek Lach. Programowanie komputerów
void strcpy(char *s, char *t)
{
int i;
i = 0;
while ((s[i] = t[i]) != '\0')
i++;
}
Jacek Lach. Programowanie komputerów
strcpy() ­ implementacja
/* strcpy: kopiowanie t do s; wersja
ze wskaźnikami */
void strcpy(char *s, char *t)
{
int i;
i = 0;
while ((*s = *t) != '\0') {
s++;
t++;
}
}
strcpy() ­ implementacja
/* strcpy: kopiowanie t do s; druga
wersja ze wskaźnikami */
Jacek Lach. Programowanie komputerów
void strcpy(char *s, char *t)
{
while ((*s++ = *t++) != '\0')
;
}
strncpy()
• char *strncpy(char *dest, const char *src, size_t maxlen);
Jacek Lach. Programowanie komputerów
• Kopiuje najwyżej maxlen znaków ze src do dest.
• Docelowy łańcuch, dest, może być pozbawiony końcowego zera, jeśli długość src wynosi maxlen lub więcej.
Jacek Lach. Programowanie komputerów
strncpy()
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[3+1];
char *str1 = "abcdefghi";
strncpy(string, str1, 3);
string[3] = '\0'; /* inaczej
zabrakłoby ’\0’ */
printf("%s\n", string);
return 0;
}
/* Wynik: abc */
strcmp()
• int strcmp(const char *s1, const char*s2);
Jacek Lach. Programowanie komputerów
• strcmp dokonuje porównania łańcuchów s1 i s2 traktując je jak ciąg wartości unsigned char
• Wartość zwracana:
• < 0 jeśli s1 < s2
• == 0 jeśli s1 == s2
• > 0 jeśli s1 > s2
Jacek Lach. Programowanie komputerów
strcmp()
#include <string.h>
#include <stdio.h>
int main(void)
{
char *buf1 = "alice", *buf2 = ”andrew";
int p;
p = strcmp(buf2, buf1);
if (p > 0)
printf("buffer 2 is greater than buffer 1\n");
else
printf("buffer 2 is not greater than buffer 1\n");
return 0;
}
/* Wynik: buffer 2 is greater than buffer 1 */
strcmp()
/* strcmp: zwraca <0 jeśli s<t,
0 jeśli s==t, >0 jeśli s>t */
Jacek Lach. Programowanie komputerów
int strcmp(char *s, char *t)
{
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == '\0')
return 0;
return s[i] - t[i];
}
strcmp()
/* strcmp: zwraca <0 jeśli s<t,
0 jeśli s==t, >0 jeśli s>t */
Jacek Lach. Programowanie komputerów
int strcmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == '\0')
return 0;
return *s - *t;
}
strlen()
• size_t strlen(const char *s);
Jacek Lach. Programowanie komputerów
• Zwraca liczbę znaków w łańcuchu s, nie licząc kończącego ten łańcuch zera
#include <stdio.h>
#include <string.h>
int main(void)
{
char *string = ”The ANSI C compiler";
printf("%d\n", strlen(string));
return 0;
}
/* Wynik: 19 */
strcat()
• char *strcat(char *dest, const char *src);
• strcat dołącza kopię src do końca łańcucha dest.
Jacek Lach. Programowanie komputerów
• dest musi być wystarczająco pojemny
• Długość wynikowego łańcucha jest równa strlen(dest) + strlen(src)
• strcat zwraca wskaźnik na połączone łańcuchy.
Jacek Lach. Programowanie komputerów
strcat()
#include <string.h>
#include <stdio.h>
int main(void)
{
char destination[25];
char *blank = " ", *c = "C ", *a = ”ANSI";
strcpy(destination, a);
strcat(destination, blank);
strcat(destination, c);
printf("%s\n", destination); /* ANSI C */
return 0;
}
strchr()
• char *strchr(const char *s, int c);
Jacek Lach. Programowanie komputerów
• Szuka w łańcuchu pierwszego wystąpienia podanego znaku
• Kończące zero uznawane jest za część łańcucha
• Jeśli c nie występuje w s, funkcja zwraca NULL
Jacek Lach. Programowanie komputerów
strchr()
#include <string.h>
#include <stdio.h>
int main(void)
{
char string[15];
char *ptr, c = 'r';
strcpy(string, "This is a string");
ptr = strchr(string, c);
if (ptr)
printf("The character %c is at position: %d\n",
c, ptr-string);
else
printf("The character was not found\n");
return 0;
} /* Wynik: The character r is at position: 12 */
strrchr()
• char *strrchr(const char *s, int c);
Jacek Lach. Programowanie komputerów
• strrchr szuka ostatniego wystąpienia znaku c w łańcuchu s
strpbrk()
Jacek Lach. Programowanie komputerów
• char *strpbrk(const char *s1, const char *s2);
• strpbrk szuka w łańcuchu s1 pierwszego wystąpienia jakiegokolwiek znaku występującego
w łańcuchu s2
• Jeśli znajdzie, strpbrk zwraca wskaźnik na pierwsze wystąpienie takiego znaku
• Jeśli nie znajdzie, zwrócona zostanie wartość NULL
Jacek Lach. Programowanie komputerów
strpbrk()
#include <stdio.h>
#include <string.h>
int main(void)
{
char *string1 = "value=123";
char *string2 = ",:=;";
char *ptr;
ptr = strpbrk(string1, string2);
if (ptr)
printf("strpbrk found first character: %c\n",
*ptr);
else
printf("strpbrk didn't find character in set\n");
return 0;
} /* strpbrk found first character: = */
strstr()
• char *strstr(const char *s1, const char *s2);
Jacek Lach. Programowanie komputerów
• strstr szuka w łańcuchu s1 pierwszego wystąpienia łańcucha s2
• Jeśli znajdzie, strstr zwraca wskaźnik na ten element s1, od którego zaczyna się s2 (wskaźnik na wystąpienie s2 w s1)
• Jeśli nie znajdzie, strstr zwraca NULL
strstr()
#include <stdio.h>
#include <string.h>
Jacek Lach. Programowanie komputerów
int main(void)
{
char *str1 = ”Computer Programming",
*str2 = ”ram", *ptr;
ptr = strstr(str1, str2);
printf("The substring is: %s\n", ptr);
return 0;
}
/* The substring is: ramming */
strtok()
Jacek Lach. Programowanie komputerów
• char *strtok(char *s1, const char *s2);
• strtok traktuje s1 jako sekwencję tokenów, rozdzielonych ciągami separatorów zdefiniowanych przez s2
• Pierwsze wywołanie strtok – zwraca wskaźnik do pierwszego znaku pierwszego tokenu w s1oraz zapisuje znak 0 do s1 bezpośrednio za tym tokenem
• Kolejne wywołania tej funkcji z pierwszym argumentem równym NULL zwracają wskaźniki do kolejnych tokenów w s1, aż do ich wyczerpania
Jacek Lach. Programowanie komputerów
strtok()
#include <string.h>
#include <stdio.h>
int main(void)
{
char input[16] = "abc,d";
char *p;
/* strtok umieszcza znak 0 za ewentualnie
znalezionym tokenem */
p = strtok(input, ",");
if (p) printf("%s\n", p);
/* Drugie wywołanie z pierwszym argumentem
równym NULL zwraca wskaźnik do kolejnego tokenu
*/
p = strtok(NULL, ",");
if (p)
printf("%s\n", p);
return 0;
}
Funkcje operujące na pamięci ­ memcpy()
• void *memcpy (void *dest, const void *src, size_t n);
Jacek Lach. Programowanie komputerów
• Kopiuje blok n bajtów z src do dest
• Jeśli obszary src i dest nakładają się, wynik jest niezdefiniowany (nie mogą nakładać się)
Jacek Lach. Programowanie komputerów
memcpy()
#include <stdio.h>
#include <string.h>
int main(void)
{
char src[] = "******************************";
char dest[] ="abcdefghijlkmnopqrstuvwxyz0123456709";
char *ptr;
printf("destination before memcpy: %s\n", dest);
ptr = (char *) memcpy(dest, src, strlen(src));
if (ptr)
printf("destination after memcpy: %s\n", dest);
else
printf("memcpy failed\n");
return 0;
}
destination before memcpy:
abcdefghijlkmnopqrstuvwxyz0123456709
destination after memcpy:
******************************456709
memmove()
• void *memmove(void *dest, const void *src, size_t n);
Jacek Lach. Programowanie komputerów
• Kopiuje blok n bajtów z src do dest
• Nawet jeśli bloki pamięci nakładają się, wynik kopiowania jest poprawny (bufor pomocniczy)
Jacek Lach. Programowanie komputerów
memmove()
#include <string.h>
#include <stdio.h>
int main(void)
{
char dest[] =
"abcdefghijklmnopqrstuvwxyz0123456789";
char *src = "******************************";
printf("destination prior to memmove: %s\n",
dest);
memmove(dest, src, 26);
printf("destination after memmove:
%s\n", dest);
return 0;
}
destination prior to memmove:
abcdefghijklmnopqrstuvwxyz0123456789
destination after memmove:
**************************0123456789
memset()
• void *memset (void *s, int c, size_t n);
Jacek Lach. Programowanie komputerów
• memset ustawia pierwszych n bajtów tablicy s na znak c
• Zwraca s
Makra klasyfikujące znaki
Jacek Lach. Programowanie komputerów
• Zdefiniowane w ctype.h
• Służą do stwierdzenia, czy dany znak należy do określonej klasy, np. czy znak c jest cyfrą:
if (isdigit(c))
printf(”To jest cyfra %c\n”, c)
• Zwracana wartość: niezerowa, jeśli znak należy do danej klasy
Makra klasyfikujące znaki
• Możliwe realizacje:
Jacek Lach. Programowanie komputerów
• wyrażenia warunkowe, np.
#define isdigit(c) ((c)>=’0’ && (c)<=’9’)
• predefiniowane tablice
Makra klasyfikujące znaki
Jacek Lach. Programowanie komputerów
• Predefiniowana tablica opisująca klasy
#define _IS_SP 1
/* is space */
#define _IS_DIG 2
/* is digit indicator */
#define _IS_UPP 4
/* is upper case */
#define _IS_LOW 8
/* is lower case */
#define _IS_HEX 16
/* [0..9] or [A-F] or [a-f] */
#define _IS_CTL 32
/* Control */
#define _IS_PUN 64
/* punctuation */
extern char _ctype[]; /* Character type array */
...
#define isdigit(c) (_ctype[(c) + 1] & _IS_DIG)
#define isalnum(c) (_ctype[(c) + 1] & (_IS_DIG |
_IS_UPP \
| _IS_LOW))
#define isalpha(c) (_ctype[(c) + 1] & (_IS_UPP |
_IS_LOW))
Makra klasyfikujące znaki
Jacek Lach. Programowanie komputerów
• ...zawartość tablicy
0:
8:
16:
24:
32:
40:
48:
56:
64:
72:
80:
88:
96:
104:
112:
120:
128:
136:
0
32
32
32
32
64
64
2
64
4
4
4
64
8
8
8
32
0
1:
9:
17:
25:
33:
41:
49:
57:
65:
73:
81:
89:
97:
105:
113:
121:
129:
137:
32
32
32
32
1
64
2
2
64
4
4
4
64
8
8
8
0
0
2:
10:
18:
26:
34:
42:
50:
58:
66:
74:
82:
90:
98:
106:
114:
122:
130:
138:
32
33
32
32
64
64
2
2
20
4
4
4
24
8
8
8
0
0
3:
11:
19:
27:
35:
43:
51:
59:
67:
75:
83:
91:
99:
107:
115:
123:
131:
139:
32
33
32
32
64
64
2
64
20
4
4
4
24
8
8
8
0
0
4:
12:
20:
28:
36:
44:
52:
60:
68:
76:
84:
92:
100:
108:
116:
124:
132:
140:
32
33
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
5:
13:
21:
29:
37:
45:
53:
61:
69:
77:
85:
93:
101:
109:
117:
125:
133:
141:
32
33
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
6:
14:
22:
30:
38:
46:
54:
62:
70:
78:
86:
94:
102:
110:
118:
126:
134:
142:
32
33
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
7:
15:
23:
31:
39:
47:
55:
63:
71:
79:
87:
95:
103:
111:
119:
127:
135:
143:
32
32
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
Makra klasyfikujące znaki
Jacek Lach. Programowanie komputerów
• ...zawartość tablicy
:
:
:
:
:
(:
0:
8:
@:
H:
P:
X:
`:
h:
p:
x:
:
:
0
32
32
32
32
64
64
2
64
4
4
4
64
8
8
8
32
0
:
:
:
:
!:
):
1:
9:
A:
I:
Q:
Y:
a:
i:
q:
y:
:
:
32
32
32
32
1
64
2
2
64
4
4
4
64
8
8
8
0
0
:
:
:
:
":
*:
2:
::
B:
J:
R:
Z:
b:
j:
r:
z:
:
:
32
33
32
32
64
64
2
2
20
4
4
4
24
8
8
8
0
0
:
:
:
:
#:
+:
3:
;:
C:
K:
S:
[:
c:
k:
s:
{:
:
:
32
33
32
32
64
64
2
64
20
4
4
4
24
8
8
8
0
0
:
:
:
:
$:
,:
4:
<:
D:
L:
T:
\:
d:
l:
t:
|:
:
:
32
33
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
:
:
:
:
%:
-:
5:
=:
E:
M:
U:
]:
e:
m:
u:
}:
:
:
32
33
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
:
:
:
:
&:
.:
6:
>:
F:
N:
V:
^:
f:
n:
v:
~:
:
:
32
33
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
:
:
:
:
':
/:
7:
?:
G:
O:
W:
_:
g:
o:
w:
:
:
:
32
32
32
32
64
64
2
64
20
4
4
64
24
8
8
64
0
0
Makra klasyfikujące znaki
• Deklaracje:
int isalnum(int c); int islower(int c);
Jacek Lach. Programowanie komputerów
int isalpha(int c); int isprint(int c);
int isascii(int c); int ispunct(int c);
int iscntrl(int c); int isspace(int c);
int isdigit(int c); int isupper(int c);
int isgraph(int c); int isxdigit(int c);
Pliki
• Zanim plik będzie czytany lub zapisywany, musi zostać otworzony
Jacek Lach. Programowanie komputerów
• Funkcja biblioteczna fopen otwiera plik
• fopen na podstawie nazwy pliku dokonuje pewnych negocjacji z systemem operacyjnym i zwraca wskaźnik na strukturę danych FILE; ten wskaźnik jest potem stosowany przez funkcje dostępu do plików • Wskaźnik ten (ang. file pointer) wskazuje na strukturę zawierającą informacje o pliku:
• położenie bufora
• bieżącą pozycję w buforze
• informację, czy plik jest czytany czy pisany
• informację o ewentualnych błędach, końcu pliku itp.
• Użytkownicy nie muszą znać szczegółów
Pliki
Jacek Lach. Programowanie komputerów
• W pliku nagłówkowym <stdio.h> zawarta jest deklaracja struktury nazywanej FILE
• Jedyną definicją wymaganą do użycia fopen jest definicja wskaźnika na taką strukturę:
FILE *fp;
FILE *fopen(char *name, char *mode);
• Powyższe instrukcje mówią, że fp jest wskaźnikiem na FILE, a fopen zwraca wskaźnik na FILE.
• Zauważmy, że FILE jest nazwą typu, jak int, a nie etykietą struktury; jest zdefiniowane przez typedef
Pliki
Jacek Lach. Programowanie komputerów
• Wywołanie fopen w programie:
fp = fopen(name, mode);
• Pierwszy parametr przekazany fopen to łańcuch zawierający nazwę pliku.
• Drugi parametr jest trybem dostępu, opisywanym również przez łańcuch znakowy określający, jak użytkownik zamierza używać pliku.
Pliki
• Dopuszczalne tryby dostępu (standard):
• do czytania ("r")
Jacek Lach. Programowanie komputerów
• do pisania ("w")
• do rozszerzania ("a")
• do aktualizacji ("r+")
• nowy do aktualizacji ("w+")
• do aktualizacji części rozszerzającej ("a+").
• Niektóre systemy odróżniają pliki znakowe i binarne; dla tych ostatnich, należy dołączyć "b" do opisu trybu dostępu: rb, wb, ab, r+b (rb+), w+b (wb+), a+b, (ab+).
Pliki
Jacek Lach. Programowanie komputerów
• Jeśli podejmowana jest próba otwarcia nieistniejącego pliku do zapisu lub dołączania, jest on tworzony (jeśli to możliwe)
• Otwieranie istniejącego pliku do zapisu powoduje usunięcie poprzedniej jego zawartości
• Otwierania do dołączania zachowuje ją
• Próba czytania nieistniejącego pliku jest błędem
• Inne przyczyny błędów: próba dostępu do pliku, do którego użytkownik nie ma odpowiednich praw
• W razie błędu, fopen zwraca NULL
Pliki
Jacek Lach. Programowanie komputerów
• Co zrobić po otwarciu pliku...
• getc zwraca następny znak odczytany z pliku; wymaga podania wskaźnika do FILE:
int getc(FILE *fp)
• getc zwraca EOF jeśli wystąpił koniec pliku lub błąd
• W przypadku wystąpienia błędu ustawiany jest znacznik błędu dla strumienia
• putc jest funkcją wyprowadzającą dane:
int putc(int c, FILE *fp)
• putc zapisuje znak c do pliku fp i zwraca ten znak w razie sukcesu lub EOF w razie błędu
Pliki
• Plik w Dos/Windows:
• abracadabra\r\n
Jacek Lach. Programowanie komputerów
• czary­mary\r\n //CR/LF
• Plik w Linux/Unix:
• abracadabra\n
• czary­mary\n
• „Wewnątrz” programu w C (działającego w DOS lub Unix) pliki przechowywane są zawsze w konwencji Unix
Pliki
Jacek Lach. Programowanie komputerów
• W trybie tekstowym znak nowej linii \n jest na wyjściu tłumaczony na kombinację \r\n. Na wejściu kombinacja \r\n jest tłumaczona na \n
• W trybie binarnym takie tłumaczenie nie następuje
Pliki
Jacek Lach. Programowanie komputerów
• W trybie tekstowym koniec pliku oznaczony jest odczytaniem znaku CTRL­Z (kod dziesiętny 26 lub 1A szesnastkowo).
• W trybie binarnym koniec pliku sygnalizowany jest wartością całkowitą –1 (FFFFh). Jeżeli więc w pliku występują dane w formacie binarnym lub tekst w innym kodzie niż ASCII, to w trybie tekstowym, przypadkowe wystąpienie bajtu o wartości 1A, zostanie potraktowane jako koniec pliku.
Pliki
Jacek Lach. Programowanie komputerów
• Kiedy uruchamiany jest program w C, system operacyjny jest odpowiedzialny za otwarcie trzech plików i powiązanie z nimi odpowiednich wskaźników
• Tymi plikami są:
• wejście standardowe, ang. standard input,
• wyjście standardowe, ang. standard output,
• strumień błędów, ang. standard error.
• Odpowiednie wskaźniki nazywane są stdin, stdout, stderr, i zadeklarowane są w <stdio.h>
• Normalnie stdin jest połączony z klawiaturą, stdout
Pliki
Jacek Lach. Programowanie komputerów
• Dla formatowanego wejścia i wyjścia, stosowane są funkcje fscanf i fprintf
• Działają analogicznie jak scanf i printf; dodatkowo wymagają wskaźnika na plik czytany lub pisany:
• int fscanf(FILE *fp, char *format, ...)
• int fprintf(FILE *fp, char *format, ...)
Jacek Lach. Programowanie komputerów
Program cat
#include <stdio.h>
/* cat: polacz pliki, wersja 1 */
main(int argc, char *argv[])
{
FILE *fp;
void filecopy(FILE *, FILE *)
if (argc == 1) /* brak par.; kopiuj stand. wej. */
filecopy(stdin, stdout);
else
while(--argc > 0)
if ((fp = fopen(*++argv, "r")) == NULL) {
printf("cat: can't open %s\n, *argv);
return 1;
} else {
filecopy(fp, stdout);
fclose(fp);
}
return 0;
Jacek Lach. Programowanie komputerów
Program cat
/* filecopy: kopiuj plik ifp do pliku ofp */
void filecopy(FILE *ifp, FILE *ofp)
{
int c;
while ((c = getc(ifp)) != EOF)
putc(c, ofp);
}
Zamykanie plików
Jacek Lach. Programowanie komputerów
• Funkcja int fclose(FILE *fp) działa odwrotnie do fopen, przerywa połączenie między wskaźnikiem fp a plikiem; zwalnia wskaźnik, który może być użyty do obsługi innego pliku
• Większość SO ma limit liczby jednocześnie otwartych plików; należy więc zwalniać te zasoby, kiedy pliki nie są już używane • Jest też inny powód stosowania fclose ­ ta funkcja opróżnia bufor, w którym putc i inne funkcje gromadzą dane.
• fclose jest wywoływane automatycznie dla każdego otwartego pliku, jeśli program kończy się normalnie
Obsługa błędów
Jacek Lach. Programowanie komputerów
• Jeśli do któregoś z plików cat nie może się dostać, wypisywany jest komunikat o błędzie na końcu danych wyjściowych
• Jest to niedopuszczalne, jeśli wyjście trafia do pliku albo na wejście innego programu przez potok
• Strumień wyjściowy, nazywany stderr, jest stosowany do wypisywania komunikatów dla użytkownika. Pojawiają się one normalnie na ekranie nawet, jeśli stdout zostało przekierowane
Jacek Lach. Programowanie komputerów
cat ­ obsługa błędów
#include <stdio.h>
#include <stdlib.h>
/* cat: concatenate files, version 2 */
main(int argc, char *argv[])
{
FILE *fp;
void filecopy(FILE *, FILE *);
char *prog = argv[0]; /* program name for errors */
if (argc == 1 )
/* no args; copy standard input */
filecopy(stdin, stdout);
else
while (--argc > 0)
if ((fp = fopen(*++argv, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", prog, *argv);
exit(1);
} else {
filecopy(fp, stdout);
fclose(fp);
}
if (ferror(stdout)) {
fprintf(stderr, "%s: error writing stdout\n", prog);
exit(2);
}
exit(0);
}
Kopiowanie
#include <stdio.h>
int main()
Jacek Lach. Programowanie komputerów
{
int c;
while ((c=getc(stdin))!=EOF)
putc(c,stdout);
return 0;
}
Jacek Lach. Programowanie komputerów
• Kopiowanie plików
#include <stdio.h>
int main()
{
FILE *f1, *f2;
int c;
f1 = fopen("data.bin","rb");
/* otwieranie do odczytu */
f2 = fopen("output.bin","wb"); /* otwieranie do zapisu */
if (!(f1 && f2)) return -1; /* problemy z otwieraniem? */
while ((c=getc(f1))!=EOF)
/* pętla główna */
putc(c,f2);
fclose(f1);
fclose(f2);
return 0;
}
Inne funkcje
Jacek Lach. Programowanie komputerów
• feof testuje warunek końca pliku (end­of­file):
int feof( FILE *stream );
• Funkcja feof zwraca wartość niezerową po pierwszej nieudanej próbie czytania poza końcem pliku
• Zwraca 0, jeśli nie było prób czytania poza końcem pliku
• Nie informuje o innych błędach
Jacek Lach. Programowanie komputerów
feof()
#include <stdio.h>
int main(void)
{
FILE *stream;
/* open a file for reading */
stream = fopen(”TEST.TXT", "r");
/* read a character from the file */
fgetc(stream);
/* check for EOF */
if (feof(stream))
printf("We have reached end-of-file\n");
/* close the file */
fclose(stream);
return 0;
}
Jacek Lach. Programowanie komputerów
feof()
#include <stdio.h>
#include <stdio.h>
int main()
int main()
{
{
int c;
int c;
while (!feof(stdin)) {
while (1) {
c = getc(stdin);
c = getc(stdin);
putc(c,stdout);
if (feof(stdin))
}
break;
return 0;
putc(c,stdout);
}
}
return 0;
}
ferror()
Jacek Lach. Programowanie komputerów
• Testuje, czy wystąpił błąd w obsłudze strumienia
int ferror( FILE *stream );
• Jeśli nie wystąpił błąd, ferror zwraca 0. W innym przypadku zwraca wartość niezerową.
• Funkcja ferror testuje błędy zapisu lub odczytu pliku związanego ze strumieniem stream
• Jeśli wystąpił błąd, znacznik błędu dla tego strumienia jest ustawiony aż do zamknięcia strumienia, przewinięcia lub wywołania dla niego funkcji clearerr
Jacek Lach. Programowanie komputerów
ferror()
#include <stdio.h>
int main(void)
{
FILE *stream;
/* otwieramy plik do zapisu */
stream = fopen("DUMMY.FIL", "w");
/* wymuszamy błąd przez próbę odczytu */
(void) getc(stream);
if (ferror(stream)) /* test wystąpienia błędu */
{
/* wypisujemy komunikat */
printf(”Błąd odczytu z pliku DUMMY.FIL\n");
/* zerujemy znacznik błędu i EOF */
clearerr(stream);
}
fclose(stream);
return 0;
}
clearerr()
Jacek Lach. Programowanie komputerów
• Zeruje znacznik błędu dla strumienia
void clearerr( FILE *stream );
• Funkcja clearerr zeruje znacznik błędu i końca pliku (EOF) dla strumienia stream.
• Znaczniki błędów nie są automatycznie zerowane; kiedy jeden z nich zostanie ustawiony, kolejne operacje na strumieniu zwracają komunikat o błędzie do czasu wywołania clearerr, fseek, fsetpos lub rewind
perror()
Jacek Lach. Programowanie komputerów
• Wyprowadzenie komunikatu o błędzie, który wystąpił podczas wykonywania programu
void perror(const char *string);
• „Mapuje” numer błędu przechowywanego w zmiennej errno w komunikat o błędzie
• Wyprowadza komunikat do pliku identyfikowanego przez stderr. Komunikat składa się z ciągu znaków wskazywanego przez string, znaku : oraz tekstu związanego z błędem (+ znak nowego wiersza)
Przykład
Jacek Lach. Programowanie komputerów
/*
crt_clearerr.c - from MSDN
* This program creates an error on the standard input
* stream, then clears it so that future reads won't fail.
#include <stdio.h>
int main( void )
{
int c;
/* Create an error by writing to standard input. */
putc( 'c', stdin );
if( ferror( stdin ) ) {
perror( "Write error" );
clearerr( stdin );
}
/* See if read causes an error. */
printf( "Will input cause an error? " );
c = getc( stdin );
if( ferror( stdin ) ) {
perror( "Read error" );
clearerr( stdin );
}
}
fflush()
Jacek Lach. Programowanie komputerów
• Opróżnia bufor obsługujący strumień
int fflush( FILE *stream );
• Jeśli plik związany ze strumieniem stream został otwarty do zapisu, fflush zapisuje do pliku zawartość bufora związanego ze strumieniem
• W niektórych systemach, jeśli plik jest otwarty do odczytu, fflush czyści zawartość bufora (poza standardem). W innych systemach, fflush w takich przypadkach nie działa (zgodnie ze standardem)
• fflush zwraca 0 po poprawnym wykonaniu. Po wykryciu błędu zwraca EOF i ustawia znacznik błędu.
ftell() Jacek Lach. Programowanie komputerów
• Podaje bieżącą pozycję w pliku
long ftell( FILE *stream );
• Funkcja ftell podaje bieżącą pozycję w pliku związanym ze strumieniem stream, jeśli jest z nim związany plik
• Pozycja podawana jest względem początku strumienia
fseek()
Jacek Lach. Programowanie komputerów
• Zmienia bieżącą pozycje w pliku na wskazaną
int fseek( FILE *stream, long offset, int origin );
• Funkcja fseek przesuwa „wskaźnik” w pliku (jeśli jest związany ze strumieniem stream) do nowego położenia oddalonego o offset bajtów od origin
• Następna operacja na strumieniu wykonywana jest w nowej pozycji
• Jeśli plik jest otwarty do uaktualniania („a”), następną operacją może być zapis lub odczyt
fseek()
Jacek Lach. Programowanie komputerów
• Parametr origin musi być jedną z następujących stałych, zdefiniowanych w stdio.h:
• SEEK_CUR
Bieżąca pozycja „wskaźnika”
• SEEK_END
Koniec pliku
• SEEK_SET
Początek pliku
Jacek Lach. Programowanie komputerów
Przykład
#include <stdio.h>
long filesize(FILE *stream)
{
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET)
return length;
}
rewind()
Jacek Lach. Programowanie komputerów
• Przemieszcza „wskaźnik” pliku na początek pliku.
void rewind( FILE *stream );
• Funkcja rewind przemieszcza „wskaźnik” pliku związanego ze strumieniem stream na początek pliku
• Wywołanie rewind jest podobne do
(void) fseek( stream, 0L, SEEK_SET );
• Ale, w przeciwieństwie do fseek, rewind zeruje znaczniki błędów dla strumienia oraz znacznik końca pliku (end­
of­file). Ponadto, w przeciwieństwie do fseek, rewind nie zwraca wartości
tmpfile()
Jacek Lach. Programowanie komputerów
• Tworzy tymczasowy plik.
FILE *tmpfile( void );
• Funkcja tmpfile tworzy tymczasowy plik i zwraca wskaźnik do tego strumienia (tj. struktury FILE)
• Jeśli plik nie może zostać utworzony, tmpfile zwraca wskaźnik NULL
• Plik tymczasowy jest automatycznie usuwany kiedy plik jest zamykany, kiedy program normalnie się kończy lub wywołana zostanie funkcja _rmtmp
• Plik tymczasowy jest otwierany w trybie w+b (binary read/write)
Pliki tymczasowe
• char *tmpnam(char *s);
• FILE *tmpfile(void);
Jacek Lach. Programowanie komputerów
• char *mktemp(char *template);
• int mkstemp(char *template)
fread() / fwrite()
Jacek Lach. Programowanie komputerów
• size_t fread( void *buffer,
size_t size,
size_t count,
FILE *stream );
• size_t fwrite( void *buffer,
size_t size,
size_t count,
FILE *stream );
fread()
Jacek Lach. Programowanie komputerów
• Czyta do count elementów o rozmiarze size bajtów każdy z wejściowego strumienia stream i zapisuje je w buforze o adresie buffer
• Zwraca liczbę pełnych elementów odczytanych z pliku
• „Wskaźnik” na pozycję w pliku (jeśli jest) jest zwiększany o liczbę przeczytanych bajtów
• Jeśli plik jest otwarty w trybie tekstowym, pary cr­lf są zastępowane pojedynczym znakiem lf (linefeed)
• Wartość częściowo odczytanych elementów jest nieokreślona
fwrite()
• Zapisuje do count elementów o rozmiarze size bajtów każdy, z bufora buffer to strumienia stream
Jacek Lach. Programowanie komputerów
• Zwraca liczbę pełnych zapisanych elementów
• „Wskaźnik” zwiększany jest o liczbę zapisanych bajtów
• Jeśli plik jest otwarty w trybie tekstowym, cr jest zastępowany przez cr­lf
Inne
Jacek Lach. Programowanie komputerów
• Usunięcie pliku o podanej nazwie
int remove(const char *filename);
• Zmiana nazwy pliku
int rename(const char *oldname, const char *newname);
ungetc()
Jacek Lach. Programowanie komputerów
• Zwraca znak z powrotem do strumienia wejściowego (!)
int ungetc(int c, FILE *stream);
• Zwraca znak c do strumienia stream, który musi być otwarty do czytania.
• Ten znak zostanie zwrócony przez najbliższe wywołanie getc lub fread dla tego strumienia.
• Tylko jeden znak może zostać zwrócony do strumienia bez czytania.
• Drugie wywołanie ungetc bez getc spowoduje, że poprzedni znak zostanie zapomniany.
• Funkcje fflush, fseek, fsetpos, rewind kasują zwrócony znak.
Jacek Lach. Programowanie komputerów
ungetc()
#include <stdio.h>
#include <ctype.h>
int main( void )
{
int i=0;
char ch;
puts(”Wpisz liczbę całkowitą i literę:");
/* czytamy znaki aż do nie-cyfry lub EOF */
while((ch = getchar()) != EOF && isdigit(ch))
i = 10 * i + ch - 48; /*zamieniamy ASCII na wartość
cyfry*/
/* jeśli przeczytano nie-cyfrę, zwracamy ją do stdin */
if (ch != EOF)
ungetc(ch, stdin);
printf("i = %d, nast. znak w buforze = %c\n", i,
getchar());
return 0;
}
Jacek Lach. Programowanie komputerów
Funkcje biblioteczne – wywołania systemowe
Funkcje matematyczne
• Plik nagłówkowy: math.h
Jacek Lach. Programowanie komputerów
• Niektóre systemy wymagają ręcznego łączenia z biblioteką matematyczną (libm)
• Szybkość: zależy od typów danych i architektury procesora
Funkcje trygonometryczne
• Stopnie wyrażone w radianach
Jacek Lach. Programowanie komputerów
• Parametry i rezultaty są zawsze typu double
– sin(x) sinus x
– cos(x) cosinus x
– tan(x) tangens x
– asin(x) sin­1(x), x in [­1,1]
– acos(x) cos­1(x), x in [­1,1]
– atan(x) tan­1(x)
– atan2(y,x) tan­1(y/x)
Jacek Lach. Programowanie komputerów
Funkcje hiperboliczne
• sinh(x) hsinus x
• cosh(x) hcosinus x
• tanh(x) htangens x
Funkcje log, exp...
• exp(x) funkcja ex
Jacek Lach. Programowanie komputerów
• log(x) naturalny logarytm ln(x), x>0
• log10(x) logarytm 10 log10(x), x>0
• pow(x,y) xy
• sqrt(x) pierwiastek x, x>=0
Obcinanie
Jacek Lach. Programowanie komputerów
• ceil(x) najmniejsza liczba całkowita niemniejsza niż x
• floor(x) największa liczba całkowita niewiększa niż x
Inne
• fabs(x) |x|
Jacek Lach. Programowanie komputerów
• ldexp(x,n)
x*2n
• frexp(x, int *ip)
• modf(x, double *ip) • fmod(x,y)
Funkcje pomocnicze
• <stdlib.h>
• konwersje liczb
Jacek Lach. Programowanie komputerów
• allokacja
• liczby losowe
Liczby losowe
int rand(void);
• Zwraca pseudolosową liczbę od 0 do RAND_MAX
Jacek Lach. Programowanie komputerów
void srand(unsigned seed);
• Ustawia generator liczb pseudolosowych na nową liczbę startową
time.h
• Funkcje:
Jacek Lach. Programowanie komputerów
• asctime ctime difftime ftime gettime gmtime localtime mktime settime time_t tzset
• System oblicza czas w sposób ciągły w sekundach
• Czas startowy: 1 styczeń, 1970
• typ: long int (signed, 32­bitowy integer)
• Wartość maksymalna: 2^31­1 = 2 147 483 647
• Co się stanie po 2^31­1 sekundach od 1 I 1970?
Czas
• Czwartek, 19 Styczeń 2038
Jacek Lach. Programowanie komputerów
• Licznik "przekręci się" na wartość zerową
• Prawdopodobne rozwiązanie: użycie liczb 64bitowych
• Problem zostanie przesunięty do Soboty, 4 grudnia roku 292 277 026 596
• To chyba rozwiązanie docelowe, ponieważ data przekracza prognozowany czas istnienia Ziemi