ein Kapitel zurück                                           ein Kapitel weiter

Für die Praxis habe ich mir als Beispiel schon vor längerer Zeit ein Videoverwaltungsprogramm zusammengebastelt, welches als Anschauungsbeispiel ganz gut geeignet sein dürfte.


So siehts aus:





Ich habe den Quellcode in 2 Teile aufgeteilt. In dem einen Teil findet die Datenverarbeitung des Programms statt und in dem anderen Teil die Ausgabe mit curses auf dem Bildschirm.

Zuerst aber noch die Headerdatei struc.h mit einer kurzen Erklärung zu den einzelnen Funktionen.......

/*Download:struc.h*/
#ifndef _STRUC #define _STRUC #include <unistd.h> #include <curses.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define DAT "video.dat" typedef struct film{ char genere[75]; char titel[75]; char regie[75]; char darsteller[75]; char fsk[3]; char jahr[5]; struct film *next; struct film *previous; }ARCHIV; ARCHIV *anfang,*next,*ende; enum{ERROR=0, SUCCESS}; void start(); /*anfang,ende und next den NULL-Zeiger &uuml;bergeben*/ /*Sortieren nach Filmtitel */ void sortieren(char *, char *, char *, char *, char *, char *); /*Element sortiert eingeben*/ void einhaengen(char *, char *, char *, char *, char *, char *); int comp(ARCHIV*, ARCHIV *); /*Vergleichsfunktion*/ void loesche(char *); /*Funktion zum l&ouml;schen eines Filmes "titel" aus dem ARCHIV*/ ARCHIV *searching(char *); /*Funktion zum suchen eines Filmes im Archiv*/ int loading(FILE *); /*Laden des Archives beim Programmstart*/ int open_for_read(FILE **); /*Datei video.dat zum lesen &ouml;ffnen*/ int create_new_file(FILE **); /*Falls video.dat nicht existiert wird sie neu erstellt*/ void save_file(FILE *); /*Archiv speichern in "video.dat"*/ int file_open_for_write(FILE **); /*Archiv zum Beschreiben &ouml;ffnen*/ void show_archiv(void); /*Zeigt das Men&uuml; f&uuml;r Archiv*/ void show_work_archiv(void); /*zeigt Men&uuml; zum Bearbeiten des Archives an*/ void show_search_scroll(void); /*Zeigt das Suchmen&uuml; zum scrollen an*/ /*Suchmaske mit Flag womit wir die Funktion zum &Auml;ndern(1) und suchen(0) benutzen*/ void search_mask(int ); void new_title(void); /*Eingabemaske eines neuen Filmtitels*/ void fehler_curses(char *); /*Popup-Fenster zur Fehlerausgabe*/ void output(ARCHIV *); /*Ausgabe eines bestimmten Filmes*/ void delete_title(void); /*Funktion zum l&ouml;schen eines Filmes aus der Liste*/ #endif

Als nächstes nun der Code für die Darstellung des Programms mittels curses und Gleichzeitig unser Hauptprogramm....

/*Download:video.c*/
#include "struc.h" void show_archiv(void) { int press; do{ clear(); attrset(A_BOLD|COLOR_PAIR(1)); mvprintw(11,21," -1- Nach Film suchen mit Suchbegriff \n"); mvprintw(12,21," -2- Liste durchscrollen \n"); mvprintw(13,21," -3- Zurück \n"); refresh(); switch(press=mvgetch(0,0)) { case '1': attrset(COLOR_PAIR(3)); mvprintw(11,21," -1- Nach Film suchen mit Suchbegriff \n"); refresh(); usleep(400000); search_mask(0); break; case '2': attrset(COLOR_PAIR(3)); mvprintw(12,21," -2- Liste durchscrollen \n"); refresh(); usleep(400000); show_search_scroll(); break; case '3': attrset(COLOR_PAIR(3)); mvprintw(13,21," -3- Zurück \n"); refresh(); usleep(400000); return; default : break; } }while(press!=3); } void show_work_archiv(void) { int press; do{ clear(); attrset(A_BOLD|COLOR_PAIR(1)); mvprintw(11,28," -1- Ändern \n"); mvprintw(12,28," -2- Neuen Titel hinzufügen \n"); mvprintw(13,28," -3- Titel löschen \n"); mvprintw(14,28," -4- Zurück \n"); refresh(); switch(press=mvgetch(0,0)) { case '1': attrset(COLOR_PAIR(3)); mvprintw(11,28," -1- Ändern \n"); refresh(); usleep(400000); search_mask(1); break; case '2': attrset(COLOR_PAIR(3)); mvprintw(12,28," -2- Neuen Titel hinzufügen \n"); refresh(); usleep(400000); new_title(); break; case '3': attrset(COLOR_PAIR(3)); mvprintw(13,28," -3- Titel löschen \n"); refresh(); usleep(400000); delete_title(); break; case '4': attrset(COLOR_PAIR(3)); mvprintw(14,28," -4- Zurück \n"); refresh(); usleep(400000); return; default : break; } }while(press!=4); } void show_search_scroll(void) { WINDOW *neu,*neu2; ARCHIV *archiv; int i=1, j, press; attrset(COLOR_PAIR(4)); neu=newwin(7, 72, 0, 0); //Neues Fenster mit 5 Zeilen 70 Spalten neu2=newwin(5, 70, 0,0); keypad(neu2, TRUE); mvwprintw(stdscr, 1, 14, "Scrollen mit 'Pfeil nach oben' und 'Pfeil nach unten'"); mvwprintw(stdscr, 2, 10, "Auswählen mit 'Pfeil nach rechts' und Abbrechen mit 'Escape'"); wrefresh(stdscr); wattrset(neu, COLOR_PAIR(2)); box(neu, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster mvwin(neu, 3,5); //Fenster an die richtige Position mvwin(neu2,4,6); wrefresh(neu); //Fenster zeichnen wrefresh(neu2); if(anfang == NULL) { fehler_curses(" Es sind keine Filme in der Liste vorhanden!!!!!!!!! "); return; } archiv=anfang; noecho(); do{ wclear(neu2); box(neu, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster wrefresh(neu); wattrset(neu2, COLOR_PAIR(3)); mvwprintw(neu2, 1,1, "%s",archiv->titel); wattrset(neu2, COLOR_PAIR(0)); if(archiv->next != NULL) { wmove(neu2, 2, 1); insertln(); mvwprintw(neu2, 2, 1, "%s",archiv->next->titel); if(archiv->next->next != NULL) { wmove(neu2, 3,1); insertln(); mvwprintw(neu2, 3,1, "%s",archiv->next->next->titel); } } wrefresh(neu2); switch(press=wgetch(neu2) ) { case KEY_DOWN : if(archiv->next != NULL) archiv=archiv->next; break; case KEY_UP : if(archiv->previous != NULL) archiv=archiv->previous; break; case KEY_RIGHT : output(archiv); break; default : break; } }while(press != 27); } void search_mask(int flag) { WINDOW *neu; char film[75],input[75]; ARCHIV *found; int i=1,press; neu=newwin(8,76,0,0); keypad(neu, TRUE); wattrset(neu, COLOR_PAIR(2)); box(neu, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster mvwin(neu, 2,2); //Fenster an die richtige Position wattrset(neu, COLOR_PAIR(4)); mvwprintw(neu, 3,3,"Filmtitel : "); wrefresh(neu); echo(); wgetnstr(neu, film, 75); noecho(); if((found=searching(film)) == NULL) { fehler_curses(" Suche erfolglos!!! "); return; } else { wclear(neu); wattrset(neu, COLOR_PAIR(5)); box(neu, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster wattrset(neu, COLOR_PAIR(0)); mvwprintw(neu, 1,3,"Genere : %s",found->genere); mvwprintw(neu, 2,3,"Titel : %s",found->titel); mvwprintw(neu, 3,3,"Regie : %s",found->regie); mvwprintw(neu, 4,3,"Schauspieler : %s",found->darsteller); mvwprintw(neu, 5,3,"FSK : %s",found->fsk); mvwprintw(neu, 6,3,"Jahr : %s",found->jahr); wrefresh(neu); if(flag==0) wgetch(neu); } if(flag==1) { do{ if(i==0) i=6; else if(i==7) i=1; mvwprintw(stdscr, 0, 14, "Scrollen mit 'Pfeil nach oben' und 'Pfeil nach unten'"); mvwprintw(stdscr, 1, 10, "Ändern mit 'Pfeil nach rechts' und Abbrechen mit 'Escape'"); wrefresh(stdscr); wattrset(neu, COLOR_PAIR(5)); box(neu, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster wattrset(neu, COLOR_PAIR(0)); wmove(neu ,i,19); wrefresh(neu); switch(press=wgetch(neu)) { case KEY_DOWN : i++; break; case KEY_UP : i--; break; case KEY_RIGHT : wclrtoeol(neu); wrefresh(neu); echo(); wgetnstr(neu, input, 75); noecho(); if(i==1) strcpy(found->genere, input); if(i==2) strcpy(found->titel, input); if(i==3) strcpy(found->regie, input); if(i==4) strcpy(found->darsteller, input); if(i==5) strcpy(found->fsk, input); if(i==6) strcpy(found->jahr, input); input[0]='\0'; break; default : break; } }while(press != 27); } } void new_title(void) { WINDOW *neu; char genere[75],titel[75],regie[75],darsteller[75],fsk[3],jahr[5]; neu=newwin(8,76,0,0); keypad(neu, TRUE); wattrset(neu,COLOR_PAIR(5)); box(neu, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster wattrset(neu,COLOR_PAIR(0)); mvwin(neu, 1,2); //Fenster an die richtige Position mvwprintw(neu, 1,3,"Genere : "); mvwprintw(neu, 2,3,"Titel : "); mvwprintw(neu, 3,3,"Regie : "); mvwprintw(neu, 4,3,"Schauspieler : "); mvwprintw(neu, 5,3,"FSK : "); mvwprintw(neu, 6,3,"Jahr : "); wrefresh(neu); echo(); mvwgetnstr(neu, 1,18, genere, 75); mvwgetnstr(neu, 2,18, titel, 75); mvwgetnstr(neu, 3,18, regie, 75); mvwgetnstr(neu, 4,18, darsteller, 75); mvwgetnstr(neu, 5,18, fsk, 3); mvwgetnstr(neu, 6,18, jahr, 5); noecho(); sortieren(genere,titel,regie,darsteller,fsk,jahr); } void fehler_curses(char *message) { WINDOW *pop; pop=newwin(3,75,0,0); wattrset(pop, COLOR_PAIR(1)); box(pop, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster mvwin(pop, 20,2); //Fenster an die richtige Position mvwprintw(pop, 1,1," %s ",message); wrefresh(pop) ; wgetch(pop); wclear(pop); wrefresh(pop); } void output(ARCHIV *movie) { WINDOW *output; output=newwin(8,76,0,0); wattrset(output, COLOR_PAIR(5)); box(output, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster keypad(output,TRUE); if(movie == NULL) { fehler_curses(" Es sind keine Filme in der Liste vorhanden!!!!!!!!! "); return; } mvwin(output, 15,2); //Fenster an die richtige Position wattrset(output, COLOR_PAIR(0)); mvwprintw(output, 1,3,"Genere : "); mvwprintw(output, 2,3,"Titel : "); mvwprintw(output, 3,3,"Regie : "); mvwprintw(output, 4,3,"Schauspieler : "); mvwprintw(output, 5,3,"FSK : "); mvwprintw(output, 6,3,"Jahr : "); mvwprintw(output, 1,18,"%s",movie->genere); mvwprintw(output, 2,18, "%s",movie->titel); mvwprintw(output, 3,18, "%s",movie->regie); mvwprintw(output, 4,18, "%s",movie->darsteller); mvwprintw(output, 5,18,"%s",movie->fsk); mvwprintw(output, 6,18, "%s",movie->jahr); wrefresh(output); wgetch(output); wclear(output); wrefresh(output); } void delete_title() { WINDOW *delete; char search[75]; delete=newwin(5, 76, 0, 0); wattrset(delete, COLOR_PAIR(5)); box(delete, ACS_VLINE, ACS_HLINE); //Linien um das neue Fenster wattrset(delete, COLOR_PAIR(0)); mvwin(delete, 2, 3); mvwprintw(delete, 2,2, "Welchen Film wollen sie entfernen : "); wrefresh(delete); echo(); wgetnstr(delete, search, 75); noecho(); loesche(search); } int main(int argc, char **argv) { int press; FILE *file; initscr(); //Curses initialisieren start_color(); //Farben initialisieren if(has_colors () == TRUE) //Können wir Farben benutzen { init_pair(1, COLOR_WHITE, COLOR_RED); //Weiss-Rot init_pair(2, COLOR_RED, COLOR_RED); //Schwarz-Rot init_pair(3, COLOR_RED, COLOR_WHITE); //Rot-Weiss init_pair(4, COLOR_RED,COLOR_BLACK); init_pair(5, COLOR_BLUE, COLOR_BLUE); } cbreak(); //nur noch STRG + S, ...+Q, ...+C werden beachtet noecho(); //keine Ausgabe auf dem Bildschirm keypad(stdscr,TRUE); //Funk.-u.-Cursortasten als Taste behandeln if((loading(file)) == SUCCESS); else if((create_new_file(&file)) == SUCCESS) { start(); fehler_curses(" \"video.dat\" neu erstellt!!! "); fclose(file); } do{ clear(); attrset(A_BOLD|COLOR_PAIR(1)); mvprintw(11,30," -1- Zum Filmarchiv \n"); mvprintw(12,30," -2- Filme verwalten \n"); mvprintw(13,30," -3- Programm beenden \n"); refresh(); switch(press=mvgetch(0,0)) { case '1': attrset(COLOR_PAIR(3)); mvprintw(11,30," -1- Zum Filmarchiv \n"); refresh(); usleep(400000); show_archiv(); break; case '2': attrset(COLOR_PAIR(3)); mvprintw(12,30," -2- Filme verwalten \n"); refresh(); usleep(400000); show_work_archiv(); break; case '3': attrset(COLOR_PAIR(3)); mvprintw(13,30," -3- Programm beenden \n"); refresh(); sleep(1); save_file(file); echo();endwin();exit(0); default: break; } fflush(stdin); refresh(); }while(press!=3); endwin(); //Curses beenden return 0; }

Jetzt noch der Quellcode zur Verarbeitung der Daten des Programms.....

/*Download:structur.c*/
#include "struc.h" /*Startadressen für die Zeiger next,anfang und ende*/ void start(void) { next=anfang=ende=NULL; } void sortieren(char gen[],char tit[],char reg[],char dar[],char f[],char j[]) { ARCHIV *zeiger1, *zeiger2, *zeiger3; if((zeiger2=(ARCHIV *)malloc(sizeof(ARCHIV))) == NULL) { fehler_curses("Ich konnte keinen Speicher reservieren....versuchen sie es erneut!"); return; } strcpy(zeiger2->genere, gen); strcpy(zeiger2->titel, tit); strcpy(zeiger2->regie, reg); strcpy(zeiger2->darsteller, dar); strcpy(zeiger2->fsk, f); strcpy(zeiger2->jahr, j); /*1.Element ? */ if(anfang==NULL) { if((anfang=(ARCHIV *)malloc(sizeof(ARCHIV))) == NULL) { fehler_curses("Ich konnte keinen Speicher reservieren....versuchen sie es erneut!"); return; } strcpy(anfang->genere, gen); strcpy(anfang->titel, tit); strcpy(anfang->regie, reg); strcpy(anfang->darsteller, dar); strcpy(anfang->fsk, f); strcpy(anfang->jahr, j); anfang->next=NULL; ende=anfang; ende->previous=NULL; } else { zeiger1=anfang; while((zeiger1->next != NULL ) && (comp(zeiger1, zeiger2) <0)) zeiger1=zeiger1->next; if(zeiger1->next == NULL) //hinten anhängen { if((zeiger1->next=(ARCHIV *) malloc(sizeof(ARCHIV))) == NULL) { fehler_curses("Ich konnte keinen Speicher reservieren....versuchen sie es erneut!"); return; } zeiger3=zeiger1; zeiger1=zeiger1->next; strcpy(zeiger1->genere, gen); strcpy(zeiger1->titel, tit); strcpy(zeiger1->regie, reg); strcpy(zeiger1->darsteller, dar); strcpy(zeiger1->fsk, f); strcpy(zeiger1->jahr, j); zeiger1->next=NULL; ende=zeiger1; zeiger1->previous=zeiger3; } else if(zeiger1==anfang && (comp(zeiger1, zeiger2)>=0)) //vorne anhängen { if((anfang=(ARCHIV *)malloc(sizeof(ARCHIV))) == NULL) { fehler_curses("Ich konnte keinen Speicher reservieren....versuchen sie es erneut!"); return; } strcpy(anfang->genere, gen); strcpy(anfang->titel, tit); strcpy(anfang->regie, reg); strcpy(anfang->darsteller, dar); strcpy(anfang->fsk, f); strcpy(anfang->jahr, j); anfang->next=zeiger1; anfang->previous=NULL; zeiger1->previous=anfang; } else if(comp(zeiger1, zeiger2) >=0) //mittendrin { zeiger3=anfang; while(zeiger3->next != zeiger1) zeiger3=zeiger3->next; zeiger2->previous=zeiger3; zeiger2->next=zeiger1; zeiger1->previous=zeiger2; zeiger3->next=zeiger2; } else //Fehler-Routine für curses schreiben exit(0); } } /*Vergleichsfunktion*/ int comp(ARCHIV *arch, ARCHIV *neu) { int ret=strcmp(arch->titel,neu->titel); return ret; } /*Löschen eines Filmes aus der Liste*/ void loesche(char wen[]) { ARCHIV *zeiger ,*zeiger1, *zeiger2; int found=0; /*Ist überhaupt ein Element vorhanden?*/ if(anfang != NULL) { /*Ist unser 1.Element das von uns gesuchte (wen[]) ?*/ if(strcmp(anfang->titel,wen) == 0) { zeiger=anfang->next; if(zeiger == NULL) { free(anfang); anfang=NULL; ende=NULL; return; } zeiger->previous=NULL; free(anfang); anfang=zeiger; return; } /*Ist das letzte Element das von uns gesuchte ? */ else if(strcmp(ende->titel,wen) == 0) { zeiger=ende->previous; zeiger->next=NULL; zeiger1=ende; ende=zeiger; free(zeiger1); return; } else { /*Es ist nicht das 1.Element zu löschen. Wir suchen in der weiteren Kette ob das zu löschende Element vor- handen ist*/ zeiger=anfang; while(zeiger->next != NULL) { zeiger1=zeiger->next; /*Ist die Adresse von zeiger1 der gesuchte Namen?*/ if(strcmp(zeiger1->titel,wen) == 0) { /*Falls ja dann.....*/ zeiger->next=zeiger1->next; zeiger2=zeiger1->next; zeiger2->previous=zeiger; free(zeiger1); return; } zeiger=zeiger1; }//Ende while }//Ende else }//Ende if(anfang != NULL) fehler_curses(" Ich kann den Film nicht im Archiv finden ?!?!?! "); } ARCHIV *searching(char film[]) { ARCHIV *zeiger; if(anfang == NULL) { fehler_curses(" Es befinden sich keine Filme in der Liste "); return NULL; } zeiger=anfang; while((zeiger != NULL) && (strcmp(zeiger->titel, film) != 0)) zeiger=zeiger->next; return zeiger; //Entweder NULL oder den gefundenen Film } int loading(FILE *file) { ARCHIV zeiger; if(open_for_read(&file)) { while(fread(&zeiger,sizeof(ARCHIV),1,file)) sortieren(zeiger.genere, zeiger.titel, zeiger.regie, zeiger.darsteller, zeiger.fsk, zeiger.jahr); return SUCCESS; } return ERROR; } int open_for_read(FILE **file) { if((*file = fopen(DAT ,"r")) == NULL) { fehler_curses(" Konnte \"video.dat\" nicht zum lesen oeffnen! "); return ERROR; } return SUCCESS; } int create_new_file(FILE **file) { if((*file = fopen(DAT ,"w+")) == NULL) { fehler_curses(" Konnte \"video.dat\" nicht zum nicht erzeugen ! "); return ERROR; } return SUCCESS; } void save_file(FILE *file) { ARCHIV *zeiger; /*Im "w+" - Modus oeffnen*/ if(file_open_for_write(&file)) { zeiger=anfang; while(zeiger != NULL) { fwrite(zeiger,sizeof(ARCHIV),1,file); zeiger=zeiger->next; } } fclose(file); } int file_open_for_write(FILE **file) { if((*file = fopen(DAT, "w+")) == NULL) { fehler_curses(" Konnte \"video.dat\" nicht zum schreiben oeffnen! "); return ERROR; } return SUCCESS; }

Übersetzten müssen sie diese 3 Codeteile mit......

gcc -o video video.c structur.c -lncurses  

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf