char array durchsuchen



  • hi!
    ich lese in meinem programm die daten aus einem txt file in ein char array ein und möchte dieses dann nach einem begriff durchsuchen. Einlesen und speichern funktionniert, nur mit meiner suchfunktion scheint was nicht zu stimmen ... durchsuch den code schon ständig nach bugs, find aber den feheler nicht .. vielleicht hätt ja jemand von euch die güte mal einen blick drauf zu werfen:

    globale variablen:

    char textfeld[17000][1000]; // (ja ich weiss ziemlich gross) <== hier wird das txt file reingespeichert ...
    int wieviel; // <== soll zaehlen wie oft der suchbegriff gefunden wurde ...
    

    und hier die funktion:

    void compare(char x[100], int i, int j, int k){  
    
    //     cout << i << " " << j << " " << k << endl;
    
         if(x[i]==textfeld[j][k]){
           if(x[i+1]=='\0'){               
             wieviel++; 
             cout << "found in line " << j << endl;
             cin.get();              
             if(j+1<17000){               
               compare(x,0,j+1,0);
             }
             else{
               cout << endl << endl << "Search complete!" << endl << endl << endl;
             }   
           }
           else {   
             if(textfeld[j][k+1]!='\0'){
               compare(x,i+1,j,k+1);
             }
             else{
               cout << "not found in line " << j << endl;
               if(j+1<17000){
                 compare(x,0,j+1,0);
               }
               else{
                 cout << endl << endl << "Search complete!" << endl << endl << endl;                
               }                  
             }
           }
         }
         else{
           if(textfeld[j][k+1]!='\0'){                         
             compare(x,0,j,k+1);
           }
           else{
             if(j+1<17000){
               cout << "not found in line " << j << endl;   
               compare(x,0,j+1,0);
             }
             else{
               cout << endl << endl << "Search complete!" << endl << endl << endl;  
             }
           }
         }
    }
    

    char x wird das such array aus der main() zugewiesen, int i ist der index von x, und j und k die indizes für das textfeld[j][k] ... zu beginn alle drei auf 0 .. (such array, sowie das textfeld wurden zu beginn mit '\0' initialisiert (vor der einelese der txt file selbsverständlich ...
    wär cool wenn mir wer weiterhelfen könnte ... die suche bricht nämlich ca bei line 1950 ab (obwohl es in dieser zeile kein sonderzeichen oder ähnliche problemmacher gibt ...)
    lg, pete



  • bricht ab? Wie?
    Mit fehlermeldung?Ohne?

    Ist dein array aus main auch gleich groß wie das übergebene?

    Nimm std::string und std::vector



  • fehlermeldung gibts keine, weder beim compilieren noch beim ausführen (zumindest nicht im dos emu) ... gibt noch eine leerzeile aus und beendet dann das programm, obwohl noch eine ausgabe etc folgen sollten ... hängt sich auch nicht auf oder so, also kein ctr-c ... gar nichts ... so als wäre das programm fehlerfrei ausgeführt worden ...
    array ist auch gleich lang
    aufruf:

    char suche[100];
    cin.get(suche,100);
    compare(suche,0,0,0);
    

    seltsam ist, dass es mit manchen txts funktioniert mit anderen (insbesonder laengeren) nicht, die einlese der txt ist aber genauso wie sie sein sollte ... das array wird korrekt gefuellt ...



  • Da du sowiso C++ verwendest, tu dir doch einen Gefallen und nutz C++ Mittel. Um genau zu sein std::vector< std::string >, da bekommst du den ganzen Aufwand abgenommen!

    grüße



  • tja, würd ich ja gerne, aber is für die uni und wir sollen das ohne zuhilfenahme der stringklasse programmieren ... und das hab ich auch ... nur funktionierts leider nicht *g*
    dachte, vielleicht wirft jemand einen blick drauf und sagt: DA ist der fehler! 😃 naja, vielleicht passiert das ja noch :xmas1:



  • Dann würd ich an deiner Stelle mal den Code ein wenig aufteilen. So wie ich das verstanden habe hast du eine Liste mit lauter Begriffen aus welcher du die Anzahl des Vorkommens eines bestimmten Suchbegriffs haben willst?!

    grüße



  • pete t. schrieb:

    char textfeld[17000][1000]; // (ja ich weiss ziemlich gross) <== hier wird das

    Ja, und zu groß um es auf dem Stack zu allokieren, das sind 16,2MB und definitiv zu viel. Nimm einfach new und hol dir Speicher vom Heap (löschen nicht vergessen 🙂



  • HIRSCH_H schrieb:

    pete t. schrieb:

    Ja, und zu groß um es auf dem Stack zu allokieren, das sind 16,2MB und definitiv zu viel. Nimm einfach new und hol dir Speicher vom Heap (löschen nicht vergessen 🙂

    Wie kommst Du auf Stack ? 😕 - er schrieb "globale Variable"



  • emmax schrieb:

    HIRSCH_H schrieb:

    pete t. schrieb:

    Ja, und zu groß um es auf dem Stack zu allokieren, das sind 16,2MB und definitiv zu viel. Nimm einfach new und hol dir Speicher vom Heap (löschen nicht vergessen 🙂

    Wie kommst Du auf Stack ? 😕 - er schrieb "globale Variable"

    Und weiter? Liegt doch trotzdem auf dem Stack.



  • David_pb schrieb:

    emmax schrieb:

    HIRSCH_H schrieb:

    pete t. schrieb:

    Ja, und zu groß um es auf dem Stack zu allokieren, das sind 16,2MB und definitiv zu viel. Nimm einfach new und hol dir Speicher vom Heap (löschen nicht vergessen 🙂

    Wie kommst Du auf Stack ? 😕 - er schrieb "globale Variable"

    Und weiter? Liegt doch trotzdem auf dem Stack.

    Globale Variable sind "static" liegen im Datensegment - nicht auf dem Stack!



  • Ich glaub eher er meinte "global" nicht in Form von "extern".



  • Das ist leider aus dem Quellcodefragment des OP nicht ersichtlich, falls die Daten global sind hat emmax natürlich recht und die Daten liegen im BSS Bereich.



  • HIRSCH_H schrieb:

    Das ist leider aus dem Quellcodefragment des OP nicht ersichtlich, falls die Daten global sind hat emmax natürlich recht und die Daten liegen im BSS Bereich.

    Es war ersichtlich - der OP arbeitet mit den globalen Daten innerhalb seiner Funktion. 🙂



  • emmax schrieb:

    HIRSCH_H schrieb:

    Das ist leider aus dem Quellcodefragment des OP nicht ersichtlich, falls die Daten global sind hat emmax natürlich recht und die Daten liegen im BSS Bereich.

    Es war ersichtlich - der OP arbeitet mit den globalen Daten innerhalb seiner Funktion. 🙂

    Richtig, du hast gewonnen 😉

    The problem was NOT the size of the array as they are global variables which do not use stack space.



  • Ich finde du machst es dir etwas kompliziert... Wenn ich das richtig verstanden habe, sollst du in einer Textdatei das Vorkommen einer bestimmten Zeichenkette zählen?
    Wenn ja, dann kann man es wirklich kürzer machen:

    bool Equals( const char* Str1, const char* Str2, size_t LenToCmp )
    {
    	for ( size_t i=0; i<LenToCmp; i++ )
    		if ( Str1[i] != Str2[i] )
    			return false;
    	return true;
    }
    
    int Count( const char* Orig, const char* ToSearch )
    {
    	int Result = 0;
    	size_t len = strlen(Orig);
    	size_t searchlen = strlen(ToSearch);
    	for ( size_t i=0; i<len-searchlen+1; i++ )
    		if ( Orig[i] == ToSearch[0] )
    			if ( Equals( Orig+i+1, ToSearch+1, searchlen-1 ) )
    				Result++;
    	return Result;
    }
    

    Vorher musst du die Datei noch einlesen, aber kA wie das C++-ISO-Konform geht, nehme immer die WinAPI... Jedenfalls, die ganze Datei sollte in nem Buffer drin sein, hinten am Buffer sollte eine 0 dran sein und dann rufst du damit die Funktion Count auf:

    printf( "Count = %i\n", Count(myBuf,"MySearchString") );
    

    Wenn ichs verpeilt habe und es um was anderes geht, dann bitte meinen Post schnell wieder vergessen 😃



  • ok, also meine variablen sind global, also vor dem mainprogramm (und den anderen funktionen) aber in derselben file definiert, nicht extern ...
    wenn ich das jetzt richtig verstanden hab sollte es also keine probleme mit der groesse des arrays geben, oder?
    werds vielleicht trotzdem mal mit dem heap probieren, schon allein, weil im endgültigen programm mehrere txt files nacheinander eingelesen werden sollen und die meisten wesentlich kleiner sind als dieses 17000 zeilen teil. ich hab nur mal so ein grosses array angelegt, um auch ohne dynamik keine fehler mit dem einlesen zu bekommen ... denkste ... (Nebenfrage: ist es prinzipiell auch möglich die zweite dimension des Arrays dynamisch zu aendern? kaum eine zeile ist 1000 zeichen lang, hab ich nur so hoch gesetzt, damit zumindest kein ueberlauf produziert werden kann, würde aber schon mal wesentlich platz sparen, wenn ich das von fall zu fall aendern könnte? also wenn die erste zeile 10 zeichen lang ist das array auf [17000][10] festlegen, wenn die zweite zeile 20 lang ist das array auf [17000][20] ausweiten, etc.)
    @Badestrand: eigentlich will ich nicht nur eine variable hochzählen, sondern immer wenn der suchbegriff gefunden wurde, soll die zeilen nr, die gesamte zeile, sowie die ueberschrift des gesamten textfiles, etc. in ein result_array geschrieben werden, das dann am ende aufgerufen wird ... hab meinen code aber für die fragestellung auf das noetigste gekuerzt, der rest funktioniert nämlich. es liegt wirklich nur an dieser funktion und ich würde wirklich gerne wissen wo der fehler liegt ... werd mir trotzdem eure vorschläge zu herzen nehmen ...
    lg, pete



  • pete t. schrieb:

    ...wir sollen das ohne zuhilfenahme der stringklasse programmieren ...

    🙄
    Hat der Dozent auch gesagt, warum ? Ist das eine "reine C"-Vorlesung oder geht's da um Programmierung selbst ?

    Sieht ein wenig so aus, als ob der Dozent keine Lust hat, seine alten Aufgabenskripte nochmal zu überarbeiten...

    Gruß,

    Simon2-.



  • pete t. schrieb:

    Nebenfrage: ist es prinzipiell auch möglich die zweite dimension des Arrays dynamisch zu aendern? kaum eine zeile ist 1000 zeichen lang, hab ich nur so hoch gesetzt, damit zumindest kein ueberlauf produziert werden kann, würde aber schon mal wesentlich platz sparen, wenn ich das von fall zu fall aendern könnte? also wenn die erste zeile 10 zeichen lang ist das array auf [17000][10] festlegen, wenn die zweite zeile 20 lang ist das array auf [17000][20] ausweiten, etc.)

    Die zweite Dimension des Arrays dynamisch? - eine reale Textdatei representiert diese Dynamik! - da sind die verschieden langen Zeilen! Du kannst die Textdatei auf einen
    Hieb in den Speicher lesen, dann setzt du eine scann()-funktion ein, die dir ermittelt wieviele Zeilen enthalten sind und du legst dir dynamisch ein Array für Zeilenadressen
    an. Mit Hilfe von scann() füllst du dann dieses Array mit den Adressen der Zeilen - du wirst sie zum Ermitteln der Zeilennummern brauchen. Gleichzeitig kannst du schon
    alle Zeilen nullterminieren.

    #include <fstream>
    #include <iostream>
    using namespace std;
    
    char* scann(const char* suchstr, char* buf, const char* maxadr)
    {
            for (size_t i = strlen(suchstr); buf < maxadr; buf++) 
                    if (!memcmp(suchstr, buf, i))
                            break;
            return (buf != maxadr)?buf:0;
    }
    
    int main()
    {
        ifstream ein("c:\\bbb.txt", ios::binary | ios::ate);
        int len = ein.tellg();
        char* buf = new char[len+1];
            buf[len] = 0;
            ein.seekg(0, ios::beg);
            ein.read(buf, len);
        const char* maxadr = buf+len; 
        const char a[] = {10, 0};    
        int zeilen = 0;
        //  ermitteln wieviele Zeilen vorhanden
            for (char* y = buf; y < maxadr; zeilen++, y++)
                    y = scann(a, y, maxadr);
        char** my =  new char*[zeilen]; 
            my[0] = buf;
        //  die Adressen der Zeilen ins Array eintragen
            for (int x = 1; x < zeilen; x++){
                    my[x] = scann(a, my[x-1], maxadr)+1;
                    *(my[x]-2) = 0; //  alle Zeilen mit 0 abschliessen
            }
        //  Text suchen
        const char* test = "alle Jahre wieder kommt der W";
        char* result = scann(test, buf, maxadr);
        int i;
        //  Zeilennummer ermitteln    
            for (i = 0; result >= my[i]; i++);
            cout << test << " - wurde in Zeile "<< i << " gefunden." << endl;
            delete[] buf, delete[] my;
            return 0;
    }
    

    ist erweiterungsfähig - am besten als Klasse - wäre mein Vorschlag!
    :xmas1:


Anmelden zum Antworten