C Probleme bei Übergabe von dynamischen Arrays (NOOB)

quaaack

Newbie
Registriert
Juni 2016
Beiträge
6
Ich versuche momentan den Boyermoore Algorithmus auf beliebig große Textdateien anzuwenden. Dabei bin ich auf das Problem gestoßen, dass ich zwar das dynamische Array beschreiben kann, aber leider bei der Übergabe und der Weiterverarbeitung etwas schief läuft. Führe ich das Programm aus, stürz es direkt ab. (Wird mit Sicherheit an einem Pointer-Fehler liegen, allerdings kann ich ihn einfach nicht finden.
Vielen danke schonmal für die Hilfe! Hier einmal der Code.
Habt mitleid... Ich bin noch ein Frischling!
Im Anhang eine Beispieldatei. (kleinste vorhandene)

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void boyermoore();

int main(int argc, char *argv[])
{
    FILE *f;
    long long anzg, anzb;
    char *gesucht, *block;

    if (argc <= 1)
    {
        fprintf(stdout,"Parameter Dateiname fehlt\n");
        return 1;
    }
    else
    {
        FILE* dateizeiger = fopen (argv[1], "r");

        if (dateizeiger == NULL)
        {
           fprintf(stdout,"Fehler beim Oeffnen\n");
        }
        else
        {
        	fscanf(dateizeiger, "%d", &anzg); //Anzahl Zeichen des gesuchten Wortes

        	gesucht = malloc(sizeof(char)*anzg + 1);
        	if(gesucht==NULL)
                    printf("Nicht genügend Speicher!\n");
        	fscanf(dateizeiger, "%s", gesucht);//einlesen: gesuchtes Wort

		fscanf(dateizeiger, "%d", &anzb);//Anzahl Zeichen des Textes

		block = malloc(sizeof(char)*anzb + 1);        
                if(block==NULL)
                    printf("Nicht genügend Speicher!\n");
		fscanf(dateizeiger, "%s", block);//einlesen: Text

              //printf("%s\n", block);

    		fclose(dateizeiger);

                boyermoore(block, gesucht, anzb, anzg);

                free(gesucht);
                free(block);
    	}
    system("PAUSE");
    return 0;
	}
}

void boyermoore(char block[], char gesucht[], int anzb, int anzg)
{
    int i = 0, j, counter;
    i=anzg-1;
    j=anzg-1;
    do
    {
        counter = 0;
        if(gesucht[j] == block[i])
        {
            i--;
            j--;
        }else
        {
            while(gesucht[j] != block[i] && counter<=anzg)
            {
                counter++;
                j--;
            }
            j = anzg-1;
            i += counter;
        }

        if(j==0)
        {
            printf("%d\n", i);
            i+=anzg;
            j=anzg-1;
        }
    }while(i<=anzb-1);
}
 

Anhänge

  • t.txt
    t.txt
    9,8 KB · Aufrufe: 408
Zuletzt bearbeitet:
compilier das programm mit -g in der gcc zeile

debugge das programm mit gdb ./programmname
tippe "run"

dann siehst du in welcher zeile es abbricht
 
in Zeile 59/60 nutzt du beides mal anzg. Ich vermute das eine soll anzb sein ;-) Dadurch nimmt er an, dass beide Arrays gleich groß sind und du hast einen Speicherzugriffsfehler
 
DarthSpot schrieb:
in Zeile 59/60 nutzt du beides mal anzg. Ich vermute das eine soll anzb sein ;-) Dadurch nimmt er an, dass beide Arrays gleich groß sind und du hast einen Speicherzugriffsfehler

Dachte ich auch zuerst, aber das ist der Algorithmus. Man vergleicht zuerst ob das letzte Zeichen im Suchstring mit dem Zeichen im Text an dieser Position übereinstimmt. Wenn der Suchstring kürzer ist als der Text, sollte es keine Probleme mit Zugriffsverletzungen geben.
 
Erst einmal VIELEN dank für die zahlreichen und schnellen Antworten!
Ich werde mal mit euren Tipps ein wenig rumprobieren und gucken, ob ich damit auf die Lösung komme.
Ich halte euch auf dem laufenden :D

@Shadow127
Wofür muss ich es initialisieren? Ich überschreibe die Variable doch mit fscanf, oder verstehe ich was falsch?
 
Zuletzt bearbeitet:
Stimmt, mein Visual Studio hat da den Wert einfach immer falsch angezeigt, hat mich schon gewundert das es nicht geht.

Du hast btw bei der Funktionsdeklaration "void boyermoore();" vergessen die Datentypen einzutragen. Das hab ich übersehn, dadurch werden die Variablen nicht richtig übergeben.
 
Moin, ich habe es jetzt FAST gelöst. Ich habe long long durch long ausgetauscht und die Funktionsübergabeparameter dementsprechend geändert.
Ich habe 3 Testdateien: 1-Die im Anhang beigefügte kleine Datei
2-10MB 10.000.000 Zeichen
3-50MB 50.000.000 Zeichen
Für die ersten beiden funktioniert es jetzt anstandslos, die andere (50MB) bleibt offensichtlich in der do while-schleife der Boyermoore Funktion stecken. Ich erkenne aber keinen sichtlichen unterschied zu der 10 MB Datei. *Am Kopf kratz*

Ideen? :)
 
kann nur wieder auf die Deklaration der Funktion ganz oben hinweißen, bei mir läuft das ganze nämlich auch bei 51.200.000 Zeichen. Vergesse ich selber immer bei C/C++.
 
So sieht mein jetziger code aus, aber es funktioniert einfach nicht mit der 50MB Datei. Ich habe alles umgesetzt (glaube ich) :(


Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void boyermoore(char block[], char gesucht[], long anzb, long anzg);

int main(int argc, char *argv[])
{
    FILE *f;
    long anzg, anzb;
    char *gesucht, *block;

    if (argc <= 1)
    {
        fprintf(stdout,"Parameter Dateiname fehlt\n");
        return 1;
    }
    else
    {
        FILE* dateizeiger = fopen (argv[1], "r");

        if (dateizeiger == NULL)
        {
           fprintf(stdout,"Fehler beim Oeffnen\n");
        }
        else
        {
        	fscanf(dateizeiger, "%ld", &anzg);

        	gesucht = malloc(sizeof(char)*anzg + 1);
        	if(gesucht==NULL)
                    printf("Nicht genügend Speicher!\n");
        	fscanf(dateizeiger, "%s", gesucht);

		fscanf(dateizeiger, "%ld", &anzb);

	        block = malloc(sizeof(char)*anzb + 1);
                if(block==NULL)
                    printf("Nicht genügend Speicher!\n");
		fscanf(dateizeiger, "%s", block);

    		fclose(dateizeiger);

               boyermoore(block, gesucht, anzb, anzg);

              free(gesucht);
              free(block);
    	}
    system("PAUSE");
    return 0;
	}
}

void boyermoore(char block[], char gesucht[], long anzb, long anzg)
{
    long i = 0, j, counter;
    i=anzg-1;
    j=anzg-1;
    do
    {
        counter = 0;
        if(gesucht[j] == block[i])
        {
            i--;
            j--;
        }else
        {
            while(gesucht[j] != block[i] && counter<=anzg)
            {
                counter++;
                j--;
            }
            j = anzg-1;
            i += counter;
        }

        if(j==0)
        {
            printf("%ld\n", i);
            i+=anzg;
            j=anzg-1;
        }
    }while(i<=anzb-1);
}
 
Mal so eine Frage, dein Code tut ja nichts. Er läuft durch aber gibt nie ein Ergebnis o.ä. zurück.

Bist du fest an C als Sprache gebunden oder kannst du auch C++ dafür benutzen? Damit ginge das 100 mal schneller und eleganter. ;)

Was clang mir als Fehler anzeigt ist, dass malloc einen void* zurück gibt und du den casten solltest bevor du ihn auf die char* zuweist, also

Code:
block = (char*)malloc( sizeof( char ) * anzb + 1 );
gesucht = (char*)malloc( sizeof( char ) * anzg + 1 );
 
Es geht mir letztendlich nur um die Ausgabe und die ist in der Boyermoore Funktion.
Ich habe den Code jetzt abgeändert und den cast dazugeschrieben, allerdings hat sich nichts geändert, aber danke trotzdem, damit hast du absolut recht. :)

PS. C++ wäre mir auch deutlich lieber, aber leider bin ich an C gebunden :x
Ergänzung ()

Keiner mehr eine Idee, woran es liegen könnte? - Ich kann die 50MB Datei leider nicht hochladen (weiß der Geier wieso).

Nochmal danke für die Bemühungen!
 
GregoryH schrieb:
Was clang mir als Fehler anzeigt ist, dass malloc einen void* zurück gibt und du den casten solltest bevor du ihn auf die char* zuweist
Ein void* zu casten ist in C nicht notwendig und auch keine gute Idee, weil es Fehler maskiert und void* absichtlich als generischer Zeigertyp eingeführt wurde.
In C++ allerdings ist der cast zwingend notwendig. Weil frag nicht, ist halt so.
 
Zuletzt bearbeitet:
Poste doch mal die ersten 3 Zeilen und einen kleinen (!) Teil des langen Strings (z.B. auf http://pastebin.com) damit man sich das anschauen kann.
 
1.Zeile: 10
2.Zeile: inbzeuylhj
3.Zeile: 50000000
4.Zeile:
gnzdmyhjreotdlbmarrazebziwxudgwkuvnhuvqmzefdqhqryhryltyupwotdkdxgrfbmvnmatpqagiznzyztwtisibvtftzwybjuovuhllirthftfemcyvugxqacjzyibhcpdxxojfgdnlwsqjvoepvbgveqvcywkbmozkciqjldviwlrrawh (usw.)

Ich weiß, dass es am "i" in der Boyer-Moore Funktion liegt. es hängt bei 5440-5442 (immer vor und zurückspringend).
Somit wird nie die Abbruchbedingung erfüllt. Allerdings, weiß ich nicht, wo mein Logikfehler liegt. Vor allem, weil es mit den anderen Dateien problemlos funktioniert.
 
Zurück
Oben