Sequenzielle Suche
-
Hallo,
Es wird eine Fehler.txt eingelesen, der Benutzer soll dann nach einem Datum suchen können (seqentielle Suche) und die entsprechenden Einträge der Fehlerdatei sollen angezeigt werden. Vorerst macht mir aber überhaupt die Rückgabe des Index zu schaffen.
Hier der Header:
//Funktionen zur Handhabung von Fehlerprotokollen //*********************************************** //Datenstruktur für einen Fehlerprotokolleintrag //********************************************** //Untertyp Kalenderdatum typedef struct { int tag; int monat; int jahr; } KDatum; //Untertyp Uhrzeit typedef struct { int std; int min; } Uhrzeit; //Länge einer Kurzbeschreibung #define KLEN 51 //Struktur für Fehlerprotokolleintrag typedef struct { KDatum kdat; //Kalenderdatum Uhrzeit zeit; //Uhrzeit int errnr; //Fehlernummer char ftext[KLEN]; //Kurzbeschreibung } Fehler; //Fehlerprotokolleintrag im Konsolenfenster anzeigen //************************************************** void showFDat(const Fehler *fdatP); //fdatP: Zeiger auf den anzuzeigenden Fehlerdatensatz //Fehlerprotokolldatei in Speicher einlesen //***************************************** int readFDat(const char *pfad, Fehler *fdata, int nmax); //pfad: Pfadname der Fehlerdatei //fdata: Zeiger auf Array der einzulesenden Fehlerdaten im Speicher //nmax: Max.Anzahl der einzulesenden Fehlerdaten //Rückgabe: Anzahl der erfolgreich gelesenen Datensätze im Bereich 0..nmax, //-1, falls Fehler beim Öffnen der Datei //Funktion zum Überprüfen der Gültigkeit eines Kalenderdatums //*********************************************************************** //datP: Zeiger auf das zu überprüfende Kalenderdatum //Rückgabe: 1, falls Kalenderdatum ok, 0 sonst int checkKDatum(const KDatum *datP); //Funktion zum Überprüfen der Gleichheit zweier Kalenderdaten static int equalKDatum(const KDatum *kd1P, const KDatum *kd2P) { if(kd1P->jahr==kd2P->jahr && kd1P->monat==kd2P->monat && kd1P->tag==kd2P->tag) { return 1; } else return 0; } //sequenzielle Suche int seqSearchKDat(const Fehler fdata[], const KDatum *kdP, int n1, int n2);
1. c-File (hier ist die sequenzielle Suche implementiert)
#include <stdio.h> #include "FehlerProtokoll.h" //Fehlerprotokolleintrag im Konsolefenster anzeigen //************************************************* void showFDat(const Fehler *fdatP) { printf("%02d.%02d.%4d-%02d:%02d %d %s\n", fdatP->kdat.tag, fdatP->kdat.monat, fdatP->kdat.jahr, fdatP->zeit.std, fdatP->zeit.min, fdatP->errnr, fdatP->ftext); } //Funktion zum Überprüfen der Gültigkeit eines Kalenderdatums //*********************************************************************** int checkKDatum(const KDatum *datP) { //Tabelle der Monatslängen static int MonatsLaenge[] = {31,29,31,30,31,30,31,31,30,31,30,31}; //Monatszahl prüfen if(datP->monat < 1 || datP->monat > 12) return 0; //Tageszahl prüfen mit rudimentärer Schaltjahrberücksichtigung if(datP->tag < 1 || datP->tag > MonatsLaenge[datP->monat-1] || (datP->monat == 2 && datP->tag == 29 && datP->jahr % 4 != 0)) return 0; return 1; } //Lokale Hilfsfunktion zum Überprüfen der Gültigkeit einer Uhrzeit //**************************************************************** //Rückgabe: 1, falls Uhrzeit ok, 0 sonst static int checkUhrzeit(const Uhrzeit *zeitP) { if(zeitP->min < 0 || zeitP->min >= 60 || zeitP->std < 0 || zeitP->std >= 24) return 0; return 1; } //Fehlerprotokolldatei in Speicher einlesen //***************************************** int readFDat(const char *pfad, Fehler *fdata, int nmax) { int ret; int n = 0; FILE *file = fopen(pfad, "rt"); if(file == NULL) return -1; while(n < nmax ) { ret = fscanf(file, "%d.%d.%d-%d:%d %d %s", &fdata[n].kdat.tag, &fdata[n].kdat.monat, &fdata[n].kdat.jahr, &fdata[n].zeit.std, &fdata[n].zeit.min, &fdata[n].errnr, fdata[n].ftext); if(!(ret == 7 && fdata[n].errnr >= 1 && checkKDatum(&fdata[n].kdat) && checkUhrzeit(&fdata[n].zeit))) break; n++; } fclose(file); return n; } int seqSearchKDat(const Fehler data[], const KDatum *kdP, int n1, int n2) { int k; for (k=n1-1; k<=n2-1; k++) if(equalKDatum(&data[k].kdat, kdP)) return k+1; else return -1; }
2. c-File für Kontrollausgabe der Fehlerdatei, sowie Eingabe nach dem zu suchenden Datum.
Ab Zeile 67 wird die Funktion für die sequenzielle Suche aufgerufen. Mehrmalig in einer for-Schleife im Falle mehrmalig vorkommender Daten.#include <stdlib.h> #include <stdio.h> #include <ctype.h> #include "FehlerProtokoll.h" #define NMAX 10000 int main(void) { int k, nread, n1, n2, m, w; char pfadname[_MAX_PATH]; Fehler err[NMAX]; KDatum *dat=NULL; //speicher freigeben dat=(KDatum *) malloc(sizeof(KDatum)); if(dat==NULL) { printf("Speicher konnte nicht allokiert werden!"); system("pause"); return; } //Fehlerdatei öffnen printf("Pfadname der Fehlerprotokolldatei: "); scanf("%s", pfadname); nread = readFDat(pfadname, err, NMAX); if(nread < 0) { printf("Datei kann nicht geoeffnet werden\n"); system("pause"); return 1; } //Kontrollausgabe printf("Kontrollausgabe:\n"); for(k = 0; k < nread; k++) { printf("%3d: ", k+1); showFDat(&err[k]); } printf("Bitte geben Sie ein Datum TTMMJJJJ ein: \n"); do { scanf("%d", &(dat->tag)); scanf("%d", &(dat->monat)); scanf("%d", &(dat->jahr)); } while(!checkKDatum(dat)); if(checkKDatum(dat)) { printf("Geben sie das Suchintervall ein: \n"); scanf("%d bis %d", &n1, &n2); for(k=n1-1;k<=n2-1;k++) { w=seqSearchKDat(&err[k], dat, n1, n2); printf("%d", w); } } system("pause"); return 0; }
Die for-Schleife im letzten c.File gibt aber überhaupt nichts zurück, was übersehe ich? Vielen Dank fürs Drüberschauen.
-
Die for-Schleife in seqSearchKDat wird nur 1-mal durchlaufen, denn entweder gibt es den if-Zweig oder else.
Und in Beiden steht return.Warum hast du in seqSearchKDat eine for-Schleife und drum herum noch einmal mit den selben Parametern?
Die Funktion equalKDatum hat in dem Header nichts zu suchen. Sie wird für jedes .c das den Header einbindet angelegt.
Steck sie in ein .c und mach das static davor weg.
-
Habe mir schon gedacht, dass das so nicht funktioniert...
Aber wie komme ich dann an alle Rückgabewerte von seqSearch?Steh grad auf der Leitung.
Danke für den Hinweis mit equalKDat, war vermutlich ein Versehen.
-
TrappedUnderIce schrieb:
Aber wie komme ich dann an alle Rückgabewerte von seqSearch?
Lass doch einfach das else weg (nur das Wort). Dann gibt es das
return -1
nur wenn die Schleife ganz durchgelaufen ist.
-
Und die äußere for-Schleife um seqSearch lassen?!
-
So genau habe ich mir das jetzt auch nicht angesehen.
Es ist dein Programm. Du musst wissen was es machen soll.
Bau in den Schleifen ein paar printf ein in denen du die Werte ausgibst (Datum, k ,n1,n2,...).
Dann siehst du doch ob das doppelt vorkommt.Es gibt übrigens auch noch den Debugger
Damit kannst du das Problem auch finden.
-
Was ich nicht ganz verstehe ist folgendes...
int seqSearchKDat(const Fehler fdata[], const KDatum *kdP, int n1, int n2) { int k; for (k=n1-1; k<=n2-1; k++) { if(equalKDatum(&fdata[k].kdat, kdP)) return k+1; } return -1; }
Wenn ich diese Funktion folgendermaßen aufrufe, müsste doch k+1 als Ausgabe erscheinen, falls denn k+1 dieses Datum beeinhaltet.
printf("%d", seqSearchKDat(&err[k], dat, n1, n2));
Die gibt aber jetzt immer -1 zurück. Wieso?
-
1. Wirf einen Debugger an
2. step durch die Funktion und die Unterfunktion
3. Sobald etwas von dir unerwartetes geschieht guckst du dir an, warum (z.B. mal die Werte der Variablen an der Stelle angucken)
4. ???
5. Profit!
-
Dann nimm doch mal den Debugger.
Oderprintf("equalKDatum : %3d: %02d.%02d.%4d <-> %02d.%02d.%4d\n", k, kd1P->jahr, kd1P->monat, kd1P->tag , kd2P->jahr, kd2P->monat, kd2P->tag);
und
printf("seqSearchKDat: %3d: %02d.%02d.%4d <-> %02d.%02d.%4d\n", k, fdata[k].kdat.jahr, fdata[k].kdat.monat, fdata[k].kdat.tag , kdP->jahr, kdP->monat, kdP->tag);
Und schau nach ob es wirklich gleiche Daten sind.
-
Die Daten sind definitiv gleich, wie ich mit diesem Code überprüft habe:
for(k=n1-1; k<=n2-1; k++){ printf("%d", equalKDatum(&err[k].kdat, dat)); }
Hier erhalte ich als Ausgabe 0 und im Falle der Gleichheit eine 1.
Ich will aber die Indices also bei welchem k sich die gesuchten Fehlerdaten befinden, deshalb die Funktion seqSearchKDat, die mir k+1 ( +1 wg. Initialisierung von 0 beginnend). @seppj: 4. und 5. ?
-
Das ist aber trotzdem etwas anderes.
Du interpretierst/übergibst die Daten in seqSearchKDat anders als in equalKDatum
Genauer: beim ersten Paramter.An seqSearchKDat wird die Anfangsadresse von Feld übergeben. Dann stimmen auch die Indizes.
An equalKDatum übergibst du aber die Adresse von einem Element. Behandelst es aber wie die Anfangsadresse. Dann stimmen die Indizes nicht mehr.
Das Problem mit den zwei for-Schleifen.
-
Deshalb wohl auch dieses hier im Debugger:
&fdata[k].kdat 0x00076b50 {tag=-858993460 monat=-858993460 jahr=-858993460 }Wie biege ich das gerade?
-
Indem du seqSearchKDat mit dem gesamten Feld aufrufst oder in seqSearchKDat nur das übergebene Element vergleichst.
w=seqSearchKDat(&err[0], dat, n1, n2);
oder
if(equalKDatum(&(fdata->kdat), kdP))
Was du dadurch noch ändern solltest, musst du mal selber schauen.
-
Das verstehe ich nicht.
Hast du Stichworte für diese Thematik, dann informiere ich mich dadrüber lieber nochmal.
-
Arrays und Zeiger.
-
Bisschen genauer vllt?
-
Indizes fangen immer bei 0 an.
Eine Funktion kann nicht feststellen wie groß das Array ist.
Da ich dein Buch nicht kenne, kann ich dir leider nicht die Seite nennen.