Arrays überschreiben ohne Bibliotheken



  • Also das Problem wurde sicher schon gepostet und kommt auch von einem sicherlich schon hier bekannte Beispiel. Da ich aber keinen Bock habe mir irgendwo eine fertige Lösung zu kopieren (die ich zugegebenermaßen auch nicht finden konnte) und selbst versucht habe es zu programmieren, stoße ich auch leider auf ganz eigene Probleme.

    Ich wäre jedem sehr dankbar über ein bisschen Hilfe, da das Prog bereits Morgen fertig sein muss.

    Hier noch einmal die Angabe:

    *"Schreiben Sie eine Funktion replace, die als Parameter zwei Zeichenketten erhält, in einer globalen Zeichenkette jedes Auftreten des ersten Parameterwerts sucht und durch den zweiten Parameterwert ersetzt. (verwenden Sie dazu keine Funktionen aus externen Bibliotheken z.B. strlen) Beispiel:

    globale Zeichenkette: Noch Ein Einzeller

    Parameter 1: Ein

    Parameter 2: Mehr

    globale Zeichenkette nach Funktionsende: Noch Mehr Mehrzeller"*

    Hier ist einmal das was ich bisher habe und ich glaube die Vorgehensweise ist schon die richtige Richtung (wenn auch etwas umständlich) nur passen die Pointer und neu (dynamisch) erstellten Arrays noch überhaupt nicht und würde euch bitten mir vielleicht die ein oder andere Zeile zu nennen, wo nachgebessert gehört und wie ich das am besten lösen könnte.

    #include <iostream>
    
    using namespace std;
    
    char azeichenkette[]={'noch ein einzeller'};
    
    char replace(char *ppara1, char *ppara2){
        int counterpara1=0, anfang=0, ende=0;
        char anewarray[]={};
        for(int i=0; ppara1[i]!='\0'; i++)
            counterpara1++;
        for(int i=0; ::azeichenkette[i]!='\0'; i++){
            if(ppara1[0]==::azeichenkette[i]){
                for(int j=1; ppara1[j]!='\0'; j++){
                    if(ppara1[j]==::azeichenkette[i+j]){
                        if(j==counterpara1){//Ich weiß nun, dass Parameter1, an der Stelle i beginnt und bis zur Stelle i+j geht
                            ende=j+i;
                            anfang=i;
                        }
                    }
                }
            }
        }
        if(ende>0 && anfang>0){
            for(int i=ende; ::azeichenkette[i]!='\0'; i++){//Teil ab Ende des gefundenen Wortes aus globalem Array in neues kopieren
                int j=0;
                ::azeichenkette[i]=anewarray[j]; //Weiss nicht ob das so geht, glaube ich muss hier eigentlich mit dynamischen Speicher arbeiten
                j++;
            }
            for(int i=0; i<=ende-i; i++){//Wort aus globalem Array ersetzen
                char *pakette=::&azeichenkette; //Muss die Adresse ändern, aber er will die Notation nicht
                pakette[anfang+i]=ppara1[i];
            }
            for(int i=0; anewarray[i]!='\0'; i++){//Am Ende des ersetzten Wortes, Teil aus neuem Array dranstückeln
                ::azeichenkette[ende+1+i]=anewarray[i];
            }
        }
    }
    int main(){
        char para1[]={'ein'}, para2[]={'mehr'};
        replace(para1, para2);
        for(int i=0; ::azeichenkette[i]!='\0'; i++)
            cout << ::azeichenkette[i];
        system("PAUSE");
        return 0;
    }
    

    Also das wo ich versuche das alte Array zu überschreiben kann nicht funktionieren im nachhinein gesehen, da müsste ich es erst zerstören und neu (dynamisch) erstellen, die frage ist nur wie 😕

    ich danke euch schon im voraus für eure hilfe!!



  • Ich sehe hier nur C Code (kein C++), falsches Unterforum.

    mfg, René~



  • Floeee schrieb:

    Also das wo ich versuche das alte Array zu überschreiben kann nicht funktionieren im nachhinein gesehen, da müsste ich es erst zerstören und neu (dynamisch) erstellen, die frage ist nur wie 😕

    Du musst in deinem globalen char[] "noch ein einzeller" und nicht 'noch ein einzeller' schreiben.

    Zu deiner Frage:
    Dynamischen Speicher allozieren geht mit

    char *new_string = calloc(NeueStringGröße, sizeof(char));
    

    Dadurch, dass du calloc verwendest, wird der allozierte Speicher gleich mit Nullen vollgeschrieben.
    Du kannst auch malloc(NeueStringGröße) verwenden, dann musst du das terminierende '\0' allerdings selbst setzen.



  • NewSoftzzz schrieb:

    Ich sehe hier nur C Code (kein C++), falsches Unterforum.

    #include <iostream> , using namespace std; und der Scope-Operator sind eindeutig C++.

    wxSkip schrieb:

    Zu deiner Frage:
    Dynamischen Speicher allozieren geht mit

    char *new_string = calloc(NeueStringGröße, sizeof(char));
    

    Nein. Nimm in C++ new[] , falls du überhaupt dynamischen Speicher brauchst. Versuche diesen aber soweit möglich zu vermeiden.

    char* new_string = new char[size];
    // ...
    delete[] new_string;
    


  • Nexus schrieb:

    Nein. Nimm in C++ new[] , falls du überhaupt dynamischen Speicher brauchst.

    Klar, dann kann er aber auch gleich std::string benutzen 😉
    Das muss er selbst aussuchen, ob er C-Funktionen verwenden soll oder ob er auch eine Prise C++ (außer dem Scope-Operator und std::cout) in seine Funktion einbauen will.



  • wxSkip schrieb:

    Nexus schrieb:

    Nein. Nimm in C++ new[] , falls du überhaupt dynamischen Speicher brauchst.

    Klar, dann kann er aber auch gleich std::string benutzen 😉

    Nicht, wenn die Anforderung "verwenden Sie dazu keine Funktionen aus externen Bibliotheken z.B. strlen" lautet.

    wxSkip schrieb:

    Das muss er selbst aussuchen, ob er C-Funktionen verwenden soll oder ob er auch eine Prise C++ (außer dem Scope-Operator und std::cout) in seine Funktion einbauen will.

    Wieso sollte man hier calloc() verwenden, wenn man new[] hat? Das ist nur fehleranfälliger und weniger komfortabel. Du hast zum Beispiel schon in deinem Minimalbeispiel einen Fehler gemacht (Cast nach char* vergessen).



  • Nexus schrieb:

    wxSkip schrieb:

    Nexus schrieb:

    Nein. Nimm in C++ new[] , falls du überhaupt dynamischen Speicher brauchst.

    Klar, dann kann er aber auch gleich std::string benutzen 😉

    Nicht, wenn die Anforderung "verwenden Sie dazu keine Funktionen aus externen Bibliotheken z.B. strlen" lautet.

    Gut, da fallen natürlich auch malloc()/calloc() drunter. Wenn new[] da nicht dazuzählt, ist das natürlich die beste Lösung. Ansonsten muss man halt ein relativ langes Ersatzarray auf den Stack legen.

    Wobei mir gerade einfällt, dass realloc() in so einem Fall vielleicht geschickt wäre (str = realloc(str, Länge_des_bisherigen_strings + Länge_des_Replacestrings - Länge_des_Suchstrings)).

    Nexus schrieb:

    wxSkip schrieb:

    Das muss er selbst aussuchen, ob er C-Funktionen verwenden soll oder ob er auch eine Prise C++ (außer dem Scope-Operator und std::cout) in seine Funktion einbauen will.

    Wieso sollte man hier calloc() verwenden, wenn man new[] hat? Das ist nur fehleranfälliger und weniger komfortabel. Du hast zum Beispiel schon in deinem Minimalbeispiel einen Fehler gemacht (Cast nach char* vergessen).

    Stimmt, ich hab gedacht, er will das mit nem C-Compiler kompilieren und hab deshalb extra den Ratschlag in der FAQ berücksichtigt 🙄 . Dabei habe ich die C++-Sachen natürlich glatt übersehen...



  • also das überrascht mich doch sehr, dass ich hier so viele schnelle antworten erhalten habe

    vielen dank an alle!

    also dynamischen speicher kann ich nun anscheinend auslassen. ich initialisiere einfach das globale array mit ein paar mehr stellen und gut ist die sache

    nun gehts aber dann um den code selbst, der passt ja noch nciht ganz, aber wo könnten da überall fehler versteckt sein? bin heut leider schon etwas gaga und seh gar nichts mehr 😕

    ausbessern kann ich sie dann eh selbst, aber einfach mal das prinzip das ich hier verwende sollte zumindest passen, weil ich wüsste nicht warum es nicht passen sollte

    muss ich nun bei stringketten hochkomma ' oder anführungszeiten " machen, ist das nicht egal?



  • Es passt einiges nicht, das Ganze wird ja nicht einmal kompiliert.

    Ich sehe aber, du versuchst, alles in einer Funktion unterzubringen. Sinnvoller wäre es aber, Funktionen für die Teilprobleme zu schreiben.
    Ein paar mögliche Prototypen:

    size_t mystrlen(const char* in); // liefert die Länge
    // find liefert einen Index, wenn what gefunden wurde, sonst SIZE_MAX
    // die Schleife sollte bis inlen-whatlen durchlaufen werden
    size_t find(const char* in, const char* what, size_t off = 0);
    // copy kopiert in[off] bis if[off+len] nach out, die aufrufende Funktion muss out freigeben
    void copy(const char* in, char*& out, size_t off, size_t len);
    // searchandreplace ist die in main aufzurufende Funktion.
    bool searchandreplace(const char* what, const char* rep);
    

    Ein Aufteilen in Teilprobleme macht es normalerweise einfacher.



  • ja dass es noch fehler hat ist mir klar, deswegen frag ich ja hier

    und es geht nur darum ob meine grundüberlegungen richtig sind, dass es einfacher geht nehm ich mal sehr stark an, bin ja auch noch ein noob in c++



  • Also ich hab das ganze nun etwas umgeschrieben und einige fehler gefunden

    meine 2 großen probleme sind nun, dass er mir immer "r" ausgibt und dass er ja nur das erste wort das er findet austauscht und dann nix mehr

    #include <iostream>
    
    using namespace std;
    
    char azeichenkette[50]={'noch ein einzeller'};
    
    char replace(char *ppara1, char *ppara2){
        int counterpara1=0, anfang=0, ende=0, abbruch=0;
        for(int i=0; ppara1[i]!='\0'; i++) //Zählt wieviele Stellen im auszutauschenden Paramter sind
            counterpara1++;
        for(int i=0; ::azeichenkette[i]!='\0' || abbruch==1; i++){
            if(ppara1[0]==::azeichenkette[i]){
                for(int j=1; ppara1[j]!='\0'; j++){
                    if(ppara1[j]==::azeichenkette[i+j]){
                        if(j==counterpara1){//Ich weiß nun, dass Parameter1, an der Stelle i beginnt und bis zur Stelle i+j geht
                            ende=j+i;
                            anfang=i;
                            abbruch=1;
                        }
                    }
                }
            }
        }
        if(ende>0 && anfang>0){
            int restcounter=0;
            for(int i=0; ::azeichenkette[ende+i]!='\0'; i++)
                restcounter++;
            char anewarray[restcounter]={};
            int j=0;
            for(int i=ende+1; ::azeichenkette[i]!='\0'; i++){//Teil ab Ende des gefundenen Wortes aus globalem Array in neues kopieren
                anewarray[j]=::azeichenkette[i]; //Weiss nicht ob das so geht, glaube ich muss hier eigentlich mit dynamischen Speicher arbeiten
                j++;
            }
            for(int i=0; ppara2[i]!='\0'; i++){//Wort aus globalem Array ersetzen
                ::azeichenkette[anfang+i]=ppara2[i];
            }
            for(int i=0; anewarray[i]!='\0'; i++){//Am Ende des ersetzten Wortes, Teil aus neuem Array dranstückeln
                ::azeichenkette[ende+1+i]=anewarray[i];
            }
        }
    }
    int main(){
        char para1[]={'ein'}, para2[]={'mehr'};
        replace(para1, para2);
        for(int i=0; ::azeichenkette[i]!='\0'; i++)
            cout << ::azeichenkette[i];
        system("PAUSE");
        return 0;
    }
    


  • wxSkip schrieb:

    Du musst in deinem globalen char[] "noch ein einzeller" und nicht 'noch ein einzeller' schreiben.

    (gilt natürlich auch für die anderen Strings)



  • ok danke
    das war einer meiner hauptfehler, nach dem einbau vieler couts bin ich dann draufgekommen und natürlich noch auf viele andre fehler

    bin nun fertig und hier der endgültige code, falls es noch wen interessiert:
    (es ist eine bedingung bei uns, die programme beliebig oft ausführen zu können, aber nicht eine cin eingabe zu vollziehen - glaub ich zumindest)

    #include <iostream>
    
    using namespace std;
    
    char azeichenkette[50]={"noch ein einzeller"};
    
    char replace(char *ppara1, char *ppara2){
        int counterpara1=0, counterpara2=0, anfang=0, ende=0, abbruch=0;
        for(int i=0; ppara1[i]!='\0'; i++) //Zählt wieviele Stellen im auszutauschenden Paramter sind
            counterpara1++;
        for(int i=0; ppara2[i]!='\0'; i++)
            counterpara2++;
        counterpara1--;
        for(int i=0; ::azeichenkette[i]!='\0' && abbruch==0; i++){
            if(ppara1[0]==::azeichenkette[i]){
                for(int j=1; ppara1[j]!='\0' && abbruch==0; j++){
                    if(ppara1[j]==::azeichenkette[i+j]){
                        if(j==counterpara1){//Ich weiß nun, dass Parameter1, an der Stelle i beginnt und bis zur Stelle i+j geht
                            ende=j+i;
                            anfang=i;
                            abbruch=1;
                        }
                    }
                }
            }
        }
        if(abbruch==0)
            return 1;
        if(ende>0 && anfang>0){
            char anewarray[50]={};
            int j=0;
            for(int i=ende+1; ::azeichenkette[i]!='\0'; i++){//Teil ab Ende des gefundenen Wortes aus globalem Array in neues kopieren
                anewarray[j]=::azeichenkette[i];
                j++;
            }
            for(int i=0; ppara2[i]!='\0'; i++){//Wort aus globalem Array ersetzen
                ::azeichenkette[anfang+i]=ppara2[i];
            }
            for(int i=0; anewarray[i]!='\0'; i++){//Am Ende des ersetzten Wortes, Teil aus neuem Array dranstückeln
                ::azeichenkette[anfang+counterpara2+i]=anewarray[i];
            }
        }
    return replace(ppara1, ppara2);
    }
    int main(){
        char bedingung='n', start='n';
        do{
            char para1[]={"ein"}, para2[]={"mehr"}; 
            cout << "Dieses Programm soll aus der globalen Variable: noch ein einzeller, den Parameter ein finden und durch den Paramter mehr ersetzen." << endl;
            cout << "Wollen sie das Programm starten? j/n ";
            cin >> start;
            if(start='j')
                replace(para1, para2);//Uns wurde in den Übungsstunden erklärt, dass beim Schreiben einer Funktion, nur eine Übergabe von Werten in egal welcher Form reicht, deswegen keine cin Eingabe
            //Sollte in Zukunft dennoch eine Eingabe erwünscht sein, bitte im Kommentar vermerken
            for(int i=0; ::azeichenkette[i]!='\0'; i++)
                cout << ::azeichenkette[i];
            cout << endl << "Wollen sie das Programm noch einmal ausfuehren? j/n ";
            cin >> bedingung;
        }while(bedingung=='j');
        return 0; 
    }
    

    danke nochmal an alle die hier ihr bestes gegeben haben 🙂



  • Ich finde so nervige Aufgaben ja teilweise kontraproduktiv. Aber ich kann dir versichern das REALE Programmierung im Berufsleben WESENTLICH weniger ätzend ist als dein Beispiel, macht wesentlich mehr Spaß.

    PS: Außer man muss Code von inkompetenten Vorgängern debuggen 😃

    mfg, René~



  • wenn nicht so ein zeitdruck wäre, fänd ichs ja lustig ^^ ist einfach so viel zu tun atm



  • *nuked*



  • Falls es tatsächlich ein Problem gibt, dass zwei den selben Account benutzen, könnt ihr es in der Forentechnik posten.

    (Da stand vorher was)


Anmelden zum Antworten