Tutorium #7
Einführung in die (strukturierte) Programmierung
Gruppe 2 – Thomas Neff
prog-tutor-thomas@iicm.tugraz.at
Gruppe 3 – Michael Schwarz
prog-tutor-michael@iicm.tugraz.at
Gruppe 5 – Jörg Müller
prog-tutor-joerg@iicm.tugraz.at
Gruppe 6 – Christoph Hack
prog-tutor-hack@iicm.tugraz.at
Gruppe 8 – Anja Karl
prog-tutor-anja@iicm.tugraz.at
Gruppe 9 – Manuel Weber
prog-tutor-weber@iicm.tugraz.at
Tutoriumsinhalt
- Gruppensuche
- HW 5 Besprechung
- Strukturen
- File I/O
- HW 6
Gruppensuche
HW5 - Gut oder Schlecht?
int errorMemory()
{
printf("Error: Out of memory!\n");
return ERROR_MEM;
}
[...]
int main()
{
char *input = (char*)malloc(STRING_LENGTH * sizeof(char));
if(input == NULL)
{
errorMemory();
}
while((character_from_stdin = getchar()) != EOF)
{
input[input_counter] = character_from_stdin;
[...]
}
[...]
}
HW5 - Gut oder Schlecht?
[...]
int max_char = 32;
int pos = 0;
char *ptr = (char*) malloc(max_char * (sizeof(char)));
if (ptr == NULL)
{
printf ("Error: Out of memory!\n");
return 1;
}
char input;
do
{
input = getchar();
if (pos == max_char)
{
max_char += 16;
char* tmp = (char*) realloc (ptr, max_char * (sizeof(char)));
if (tmp == NULL)
{
printf ("Error: Out of memory!\n");
free(ptr);
return 1;
}
ptr = tmp;
}
[...]
}
[...]
HW5 - Gut oder Schlecht?
[...]
char* text = malloc(10000 * sizeof(char));
gets(text);
int length = strlen(text);
int i = 0;
for(i = length - 1; i >= 0; i--)
printf("%c", text[i]);
[...]
HW5 - Gut oder Schlecht?
[...]
#define BLOCKSIZE 50
char* text = malloc(BLOCKSIZE * sizeof(char));
[...] // NULL-Pointercheck
char letter = getchar();
int index = 0;
int size = BLOCKSIZE;
while(letter != EOF)
{
if(index == size)
{
size += BLOCKSIZE;
char* tmp = realloc(text, size * sizeof(char));
[...] //NULL-Pointer check
}
text[index] = letter;
letter = getchar();
}
while(index >= 0)
{
printf("%c", text[index]);
index--;
}
printf("\n");
[...]
HW5 - Häuftigste Fehler
-
Keine Überprüfung von NULL-Pointern nach malloc/realloc
-
Keine Verwendung von Temp-Pointern für realloc
-
Zeichenweises Vergrößern des Speichers
-
NULL-Byte vergessen
-
Memcopy nach realloc
-
Falsche Verwendung von realloc
Strukturen
Strukturen
Strukturen dynamisch anlegen
Selbstreferenzierende Strukturen
File I/O
- Textdateien und Binärdateien
- Textdateien
- enthalten nur Text
- können mit dem normalen Editor gelesen werden
- z.B. .txt Dateien
- Binärdateien
- enthalten beliebige binäre Daten
- sind nicht mit dem normalen Editor lesbar
- z.B. Bilder, Musik
struct
in Datei speichern
struct
s können in Binärdateien gespeichert werden
-
[...]
struct _Phone_ {
int country_code;
int number;
}__attribute__((packed));
[...]
struct _Phone_ number;
number.number = 1234567;
number.country_code = 43;
FILE* file = fopen("phone_numbers", "wb"); // wb = write binary
fwrite(&number, sizeof(struct _Phone_), 1, file);
fclose(file);
__attribute__((packed)) ?
- wichtig wenn
struct
in Datei gespeichert werden soll
- entfernt unnötige Padding-Bytes
struct _Code_ { |
0: | char symbol; |
1: | uint8_t bits; |
2: | 0 (Padding) |
3: | 0 (Padding) |
4: | char* code; |
} |
|
struct _Code_ { |
0: | char symbol; |
1: | uint8_t bits; |
2: | char* code; |
}__attribute__((packed)) |
|
struct
aus Datei lesen
struct
s können aus Binärdateien geladen werden
-
[...]
struct _Phone_ {
int country_code;
int number;
}__attribute__((packed));
[...]
struct _Phone_ number;
FILE* file = fopen("phone_numbers", "rb"); // rb = read binary
fread(&number, sizeof(struct _Phone_), 1, file);
fclose(file);
Wie schaut ein int
in einer Datei aus?
- Integer hat 4 Byte
- Jedes der Bytes kann wie eine »Ziffer« gesehen werden
- Die Umrechung zurück in einen Integer erfolgt dann wie in jedem anderen Zahlensystem
-
- Achtung Endianness: Intel ist Little-Endian, d.h. die Byte-Reihenfolge ist »verkehrt«
- Beispiel: Integer 0x12345678 (= 305.419.896) in einer Datei:
78 56 34 12
Beispiel zur Umrechnung
- Inhalt der Datei als
char
Array eingelesen: 02 01 00 00
- Umrechnung ins Dezimalsystem:
2560 | 2561 | 2562 | 2563 |
02 | 01 | 00 | 00 |
- = 0x02 * 2560 + 0x01 * 2561 + 0x00 * 2562 + 0x00 * 2563
- = 258
Beispieldatei von HW 6 - Hex-Editor
Geht das auch einfacher?
- Natürlich, wir lassen den Compiler für uns arbeiten
- Direktes Einlesen in einen Integer mit
fread
:
int length;
fread(&length, sizeof(int), 1, file);
- Über Pointer, indem wir den Speicherinhalt neu »interpretieren« lassen:
// buffer is the char array containing the file
int length = *((int*)buffer);
- Mit
memcpy
in einen Integer kopieren:
// buffer is the char array containing the file
int length;
memcpy(&length, buffer, sizeof(int));
HW6 - Dateigröße ermitteln
- Keine C Funktion um die Dateigröße zu ermitteln
- Folgende Vorgehensweise:
- Dateizeiger an das Ende der Datei setzen
- Abfragen, wo der Dateizeiger steht
- Dateizeiger wieder auf den Anfang der Datei setzen
- Der Code dazu:
long size;
fseek(file, 0, SEEK_END);
size = ftell(file);
fseek(file, 0, SEEK_SET);
Abgabe
- bis Mittwoch, 20.11.
- Deadline 19:00
Bis zum nächsten Mal!