Inhalt eines char Pointers konvertieren



  • Ahoi!

    Voraussetzung: Ansi-C
    Aus der main():
    int NamAnz = 5;
    char *TstNamPtrArr[MAXNAMA] = {"hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE"};

    ConvertNamen(TstNamPtrArr, NamAnz);

    So weit so klar.

    void ConvertNamen(char *PtrNamPtrArr[], int NamAnz){					//Namen korrigieren
    	char Name[51];			                    //Hilfsvariable f. String
    
    	clrscr();
    	printf("Ausgabe 2: Namen in Original-Reihenfolge und korrigierter Schreibweise\n\n");
    
    	for(int i = 0; i < NamAnz; i++){                            //Strings in Hilfsvariable kopieren
    		strcpy(Name, PtrNamPtrArr[i]);
    
    		for(int j = 0; j < strlen(Name); j++){
    		  Name[j] = tolower(Name[j]);                            
    		  if(Name[j] == ' ' || Name[j] == '-'){
    				j++;
    				Name[j] = toupper(Name[j]);
    		  }
    		  Name[0] = toupper(Name[0]);
    		}
    
    		PtrNamPtrArr[i] = Name;
    
    		printf("Name %2d: %s\n", i+1, Name);
    		//printf("NamPtr: %s\n", PtrNamPtrArr[i]);
    	}
    	ClrStdIn();
    }
    

    Damit konvertiere ich die Strings, auf die der Pointer zeigt, in normale Schreibweise.
    **
    Das Problem:**
    Es sollen die konvertierten Namen wieder an die Adressen des Pointers zurückgespeichert werden, damit ich sie -über die main-Funktion- in einer Funktion *void SortNamen(char PtrNamPtrArr[], int NamAnz) lexikographisch sortieren kann. Das tut er so aber nicht. Er überschreibt ALLES im Array mit dem aktuellen String, sodass am ende im ganzen Array "Lisa Marie" steht.

    Und in der Sort-Funktion macht er bisher nur Mist und bricht das Programm mit 'System.AccessViolationException' ab.Kann gut sein, dass es daran liegt das in ConvertNamen() irgendwas kaputt gemacht wird.

    Würd mich über eine Erklärung freuen. 🙂
    Schönen Gruß



  • Zeile 19:

    //PtrNamPtrArr[i] = Name; //Name ist nach verlassen der Funktion ungültig
    strcpy(PtrNamPtrArr[i], Name);
    


  • eigentlich kannst du das auch in-place also ohne kopierung machen
    denke dafür mußt du die folgenden zeilen tauschen

    char Name[51];
    in
    char *Name;
    
    strcpy(Name, PtrNamPtrArr[i]);
    in
    Name = PtrNamPtrArr[i];
    
    und das kommt dann raus
    PtrNamPtrArr[i] = Name;
    
    und das am besten unter Name = PtrNamPtrArr[i];
    Name[0] = toupper(Name[0]);
    

    lg lolo



  • Ich glaube in Zeile 19 liegt dein Fehler:

    PtrNamPtrArr[i] = Name;
    

    hier kopierst du nicht den char*, sondern übergibst nur die Adresse von Name, und da Name zuletzte Lisa Marie war, ...

    wieso benutzt du nicht strcpy wie du es schon in Zeile 8 gemacht hast?



  • was macht eigentlich toupper(0)? das kommt vor wenn das letzte zeichen ' ' oder '-' ist...

    if(Name[j]!=0)
        Name[j] = toupper(Name[j]);
    


  • toupper(0) gibt 0 zurück also kannst dir meinen letzten post schenken...



  • noobLolo schrieb:

    eigentlich kannst du das auch in-place also ohne kopierung machen
    denke dafür mußt du die folgenden zeilen tauschen

    char Name[51];
    in
    char *Name;
    
    strcpy(Name, PtrNamPtrArr[i]);
    in
    Name = PtrNamPtrArr[i];
    
    und das kommt dann raus
    PtrNamPtrArr[i] = Name;
    
    und das am besten unter Name = PtrNamPtrArr[i];
    Name[0] = toupper(Name[0]);
    

    lg lolo

    void ConvertNamen(char *NamPtrArr[], int NamAnz) {
      char *Name;
      printf("%d ", NamPtrArr[0]);
    
      for (int i = 0; i < NamAnz; i++) {
        Name = NamPtrArr[i]; 
        Name[0] = toupper(Name[0]);
    
        for (int j = 0; j < strlen(Name); j++) {
          if(Name[j] == ' ' || Name[j] == '-') {         // Nicht-Buchstaben überspringen
            j++;
            Name[j] = toupper(Name[j]);                  // Erster Buchstabe danach groß
          } else {
            Name[j] = tolower(Name[j]);                  // Alles klein machen
          }
        }
      }
    }
    

    Das war jetzt der Versuch. Es kompiliert, bricht dann aber mit folgender Fehlermeldung das Programm ab:

    An unhandled exception of type 'System.AccessViolationException' occurred in pa4.exe

    Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.



  • zeig doch mal den code mit dem du das string array anlegst



  • btw. du solltest jetzt bei j=1 anfangen da du Name[0] ja schon bearbeitet hast



  • Was genau meinst du?

    char *TstNamPtrArr[10] = { "hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE" };
    

    steht ja schon oben.

    Ganz genau:

    Main():

    int main(void) {
      //char **PtrNamPtrArr = NULL;
      //int NamAnz = 0;
      char *TstNamPtrArr[10] = { "hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE" };
      int NamAnz = 5;
    
      //GetNamen(PtrNamPtrArr, NamAnz);
    
      OutNamen("Ausgabe 1: Namen in Original-Reihenfolge und Original-Schreibweise", TstNamPtrArr, NamAnz);  
      ConvertNamen(TstNamPtrArr, NamAnz);
      OutNamen("Ausgabe 2: Namen in Original-Reihenfolge und korrigierter Schreibweise", TstNamPtrArr, NamAnz);
      SortNamen(TstNamPtrArr, NamAnz);
    }
    

    ConvertNamen:

    void ConvertNamen(char *NamPtrArr[], int NamAnz) {
      char *Name;
      printf("%d ", NamPtrArr[0]);
    
      for (int i = 0; i < NamAnz; i++) {
        Name = NamPtrArr[i]; 
        Name[0] = toupper(Name[0]);
    
        for (int j = 0; j < strlen(Name); j++) {
          if(Name[j] == ' ' || Name[j] == '-') {         // Nicht-Buchstaben überspringen
            j++;
            Name[j] = toupper(Name[j]);                  // Erster Buchstabe danach groß
          } else {
            Name[j] = tolower(Name[j]);                  // Alles klein machen
          }
        }
      }
    }
    


  • "lisa-marie" und "LISA MARIE" passen nicht in dein Array.



  • "lisa-marie" und "LISA MARIE" passen nicht in dein Array.

    😕

    versuch mal

    char TstNamPtrArr[][256] = { "hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE" };
    statt
    char *TstNamPtrArr[10] = { "hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE" };
    

    so sollts auf jeden fall auf die schnelle klappen, das problem ist das ein string der mit

    char *xxx = "asdasdasd";
    

    angelegt wird schreibgeschützt ist
    und

    char xxx[] = "asdasdasd";
    

    nicht.



  • Doch das passt rein, das ist erstens in der Aufgabenstellung so vorgegeben und zweitens haben beide Namen 10 "Buchstaben". Da der Array bei 0 beginnt und bis 10 geht passt es rein.

    Sobald ich beim aktuellen Code versuche einen einzelnen Char per Name[0] o.Ä. anzusprechen bricht er mit der Access Violation-Message ab.



  • noobLolo schrieb:

    versuch mal

    char TstNamPtrArr[][256] = { "hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE" };
    statt
    char *TstNamPtrArr[10] = { "hans", "FRANZ", "oTTo", "lisa-marie", "LISA MARIE" };
    

    so sollts auf jeden fall auf die schnelle klappen, das problem ist das ein string der mit

    char *xxx = "asdasdasd";
    

    angelegt wird schreibgeschützt ist
    und

    char xxx[] = "asdasdasd";
    

    nicht.

    Dürfen wir leider nicht, die Struktur diesbezüglich ist fest vorgegeben, wir dürfen selbst in den Unterprogrammen nur eingeschränkt arbeiten, wie wir wollen. 😕



  • ⚠ Da der Array bei 0 beginnt und bis 10 geht passt es rein. ⚠
    richtig ist
    Da der Array bei 0 beginnt und bis 9 geht passt es rein.
    int arr[10];

    erstes ist arr[0];
    letztes ist arr[9];

    Dürfen wir leider nicht, die Struktur diesbezüglich ist fest vorgegeben, wir dürfen selbst in den Unterprogrammen nur eingeschränkt arbeiten, wie wir wollen. :/
    

    also von sowas hab ich ja noch nie gehört... aber man lernt ja nie aus, du kannst auch eine kopie von deinem string array anlegen, alerdings würd ich das nicht in "ConvertNamen" mit ein bauen denn das gehört da nicht rein

    zum kopieren

    char *from[10] = {"asd","asd","asd"};
    char *to[10] = {};
    int l = 0;
    while( l<10 && from[l] ){
        to = strdup(from[l]);
        l++;
    }
    

    hoffe das klappt so...

    darüber hinaus ist es ja so das dein programm in zukunft sowieso die namen woanders hernehmen soll also entweder von der tastatur, einer datei, datenbank o.ä. und dann sind die strings idr. nicht schreibgeschützt.



  • "LISA MARIE" ist ein '\0'-terminierter String, deshalb brauchst du 11 chars, 10 für LISA MARIE und 1 fürs '\0'-Zeichen. Wahrscheinlich wird deshalb das '\0'-Zeichen geschluckt und dein Array sieht tatsächlich so aus:

    hans\0     FRANZ\0     oTTo\0     lisa-marieLISA MARIE
    

    Das würde auch erklären warum das nicht richtig läuft.
    strlen versagt hier weil es bei lisa-marie bis zum '\0'-Zeichen zählt, was aber garnicht da ist.
    Du kannst aber statt strlen(Name) einfach 10 hinschreiben, dann sollte es funktionieren.



  • @nwp2
    char *from[10] erstellt bei mir ein array für 10 char* zeiger ist doch bei dir auch so oder?



  • Ups, ich nehme alles zurück und behaupte das Gegenteil.



  • Ja, später sollen bis zu 10 Namen per fgets eingelesen werden. Vorerst sollen wir aber mit dem Test-Array die Unterprogramme zum Laufen kriegen. Hab jetzt zwar noch etwas weiter rumprobiert, aber finde einfach keine Lösung, wie das Programm nicht abstürzt, wenn ich versuche einzelne Buchstaben von "Name" anzusprechen (Name[0] z.B. was in dem Fall "h" von "hans" sein sollte).

    Sobald die Unterprogramme funktionieren, soll ein Feld mit char-Zeigern dynamisch per calloc erzeugt werden und ein Zeiger PtrNamPtrArr auf die Startaddresse zeigen. Das Feld soll dann genau NamAnz (1 bis max 10) Elemente vom Datentyp char* enthalten. Und in die Feldelemente kommen die Addressen der dynamischen Strings, die die Namen enthalten. Bin mir da zwar auch noch nicht 100% sicher wie das implementiert werden soll, aber erstmal will ich einfach nur dass es mit dem Test-Ding klappt.

    Also das hauptsächliche Problem gerade ist, dass ich aus der Unterfunktion nicht wirklich in den Ram speichern kann, weil er mir sofort 'ne AccessViolation andreht. Muss ich vielleicht doch vorher schon etwas mit calloc oder so machen?

    Und nochmal zum Verständnis: Wenn ich einen Zeiger (char *Name) erstelle und den mit NamPtrArr[0] gleichsetze (Name = NamPtrArr[0]), habe ich in "Name" den ersten Eintrag von NamPtrArr, also "hans" (gerade per fprint getestet). Wieso kann ich dann diesen String charakterweise nicht per Name[0] Schritt für Schritt durcharbeiten? Sobald ich einen Index anhänge kriege ich eine Access-Violation. Gibt es da noch eine andre Methode?



  • Kuh-Couch schrieb:

    Wieso kann ich dann diesen String charakterweise nicht per Name[0] Schritt für Schritt durcharbeiten?

    also lesen kannst du schon nur nicht schreiben weil das in einem schreibgeschützten bereich drin steht...


Anmelden zum Antworten