Hilfe bei strcat error



  • Hallo C++ Community,
    Ich habe ein Problem mit meinem Programm!
    Dieses soll 3 Zahlen erstellen, diese in Strings umwandeln und danach vergleich.
    Kurz: Eine Art Übung für Linux-Rechte für mich selbst.
    Das Problem beginnt beim Debuggen bei Zeile 70. Funktioniert strcat nicht mit char* ? 😕
    Bitte habt Nachsicht mit mir da es das erste mal ist das ich mit char* arbeite da ich keinen anderen weg kannte eine String zu "returnen"... 😞

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <time.h>
    #include <string.h>
    
    char *vis3;
    char getrecht(int zahl) {
    	//wandelt zahlen in visuelle zeichen
    	if (zahl == 7) {
    		vis3 = "rwx";
    	}
    	if (zahl == 6) {
    		vis3 = "rw-";		
    	}
    	if (zahl == 5) {
    		vis3 = "r-x";		
    	}
    	if (zahl == 4) {
    		vis3 = "r--";	
    	}
    	if (zahl == 3) {
    		vis3 = "-wx";		
    	}
    	if (zahl == 2) {
    		vis3 = "-w-";		
    	}
    	if (zahl == 1) {
    		vis3 = "--x";		
    	}
    	if (zahl == 0) {
    		vis3 = "---";		
    	}
    	return *vis3;
    }
    int randrecht(void){
    	int rnum;
    	srand(time(NULL));
    	rnum = rand()%7;
    
    	return rnum;
    }
    void main(){
    	char *visuel = "";
    	char *vergleich;
    
    	int eingabe;
    	int rnum;
    	int i,e;
    
    	printf("Linux-Rechte Test\n");
    	do{
    		printf("Wählen sie zwischen folgenden Möglichkeiten:\n");
    		printf("1.Test Starten\n");
    		printf("2.Beenden\n");
    		scanf("%d", &eingabe);
    
    		//generiert eine 3 stellige zufalls-zahl
    		printf("Gib die rechte für die Zahl: ");
    		for (i = 0;i < 4;i++) {
    			rnum = randrecht();
    			printf("%d", rnum);
    			getrecht(rnum);
    			strcat(visuel,vis3);
    		}
    		printf(" ein!\nBsp: r-xrw----\n");
    		//vergleicht antwort mit lösung
    		do {
    			scanf("%s",&vergleich);
    			e = strcmp(vergleich, visuel);
    
    		} while (e != 0);
    		//ausgabe
    		printf("Eingabe korrekt");
    		system("pause");
    		system("cls");
    	}while(eingabe == 1);
    }
    


  • Du hast so ziemlich alles falsch gemacht, was man falsch machen kann:
    1. Dein Programm ist C, nicht C++
    2. conio.h
    3. Zeilen 11-34 lassen sich durch ein switch-case ersetzen.
    4. Der Funktion getrecht (5. Englisch und Deutsch vermischt) übergibst du am besten einen Zeiger auf ein Array, indem der String gespeichert wird.
    6. srand nur einmal im Programm aufrufen
    7. void main statt int main(void)
    8. printf statt puts
    9. Du reservierst keinen Speicher mit malloc und riskierst einen Overflow.
    10.

    scanf("%s",&vergleich);
    

    hier kein &
    11. system("cls") unter Linux
    12. Globale Variablen
    ...



  • Cambaru schrieb:

    Bitte habt Nachsicht mit mir da es das erste mal ist das ich mit char* arbeite da ich keinen anderen weg kannte eine String zu "returnen"... 😞

    std::string



  • wechlol.vb schrieb:

    Du hast so ziemlich alles falsch gemacht, was man falsch machen kann:
    1. Dein Programm ist C, nicht C++
    2. conio.h
    3. Zeilen 11-34 lassen sich durch ein switch-case ersetzen.
    4. Der Funktion getrecht (5. Englisch und Deutsch vermischt) übergibst du am besten einen Zeiger auf ein Array, indem der String gespeichert wird.
    6. srand nur einmal im Programm aufrufen
    7. void main statt int main(void)
    8. printf statt puts
    9. Du reservierst keinen Speicher mit malloc und riskierst einen Overflow.
    10.

    scanf("%s",&vergleich);
    

    hier kein &
    11. system("cls") unter Linux
    12. Globale Variablen
    ...

    Da hab ich einiges nicht verstanden:
    1. Oh gut zu wissen, mir wird in der Schule gesagt das wir C++ lernen...

    2. Was ist an conio.h falsch?

    6. Warum nur einmal? Ich brauche ja immerhin 3 zufallszahlen.

    7. Nirgendwo steht int main(void)

    8. Ich habe überall printf genutzt 😕



  • Cambaru schrieb:

    2. Was ist an conio.h falsch?

    Gehört nicht zum Standard und ist Compilerabhängig.

    Cambaru schrieb:

    6. Warum nur einmal? Ich brauche ja immerhin 3 zufallszahlen.

    Die Zufallszahlen bekommst du mit rand(), srand initialisiert den Zufallszahlengenerator.
    Wenn du srand schnell mehrfach hintereinander aufrufst bekommst du die selben Zufallszahlen, da du mit der Zeit initialisierst, die sich nur jede Sekunde ändert.

    Cambaru schrieb:

    7. Nirgendwo steht int main(void)

    Ich meinte es andersrum, void main ist falsch.

    Cambaru schrieb:

    8. Ich habe überall printf genutzt 😕

    Hier auch, printf ist zwar nicht falsch, aber puts ist besser wenn du nur konstante Strings ausgeben willst.

    Cambaru schrieb:

    1. Oh gut zu wissen, mir wird in der Schule gesagt das wir C++ lernen...

    Das ist schlecht, noch ein Lehrer der sich nicht auskennt.
    Dann nimm das auf keinen Fall ernst was dein Lehrer sagt, wenn du C++ anständig lernen willst.



  • Ahh alles klar!

    Aber bitte nochmal zurück zum eigentlichen Problem, denn das Programm läuft und es hakt nur an dieser einen Stelle ( Zeile 70 )warum geht das strcat nicht ?
    und ich bitte nochmals um Entschuldigung, da ich in der Materie sehr neu bin.

    Aber danke trotzdem schonmal für die Hilfe! 👍



  • Cambaru schrieb:

    Ahh alles klar!

    Aber bitte nochmal zurück zum eigentlichen Problem, denn das Programm läuft und es hakt nur an dieser einen Stelle ( Zeile 70 )warum geht das strcat nicht ?
    und ich bitte nochmals um Entschuldigung, da ich in der Materie sehr neu bin.

    Aber danke trotzdem schonmal für die Hilfe! 👍

    1. Du musst das & im scanf weglassen.
    2. Du initialisierst visuel mit "", d.h. an erster stelle steht ein abschließendes '\0'.
    Alles was danach kommt wird von Stringverarbeitungsfunktionen nicht beachtet.



  • Ok ich hab den Code überarbeitet, jetzt hab ich Probleme bei getrecht
    erstmal wird nur eins von 3 Zeichen zurück an das Hauptprogramm gegeben
    un dazwischen stehen viele andere Zeichen z.B.:

    visuel 0x010a9750 "ÍÍÍÍÍÍÍÍÍÍýýýý\n\x1,ž\x13yÒ<rÍÍÍÍÍÍÍÍÍýýýýrÍÍÍÍÍÍÍÍÍýýýý-ÍÍÍÍÍÍÍÍÍýýýý"

    Ich habe keine Ahnung woher das kommt.
    Ausserdem hier nochmal der überarbeitete Code...
    Ich hoffe es ist besser bis auf "puts" müsste ich auch alle deine Vorschläge berücksichtigt haben.

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    
    char getrecht(int zahl) {
    	char *vis3;
    	vis3 = (char *)malloc(sizeof(*vis3) * 10);
    
    	//wandelt zahlen in visuelle zeichen
    	switch (zahl) {
    	case 7:
    		vis3 = "rwx";
    		break;
    	case 6:
    		vis3 = "rw-";
    	case 5:
    		vis3 = "r-x";
    		break;
    	case 4:
    		vis3 = "r--";
    		break;
    	case 3:
    		vis3 = "-wx";
    		break;
    	case 2:
    		vis3 = "-w-";
    		break;
    	case 1:
    		vis3 = "--x";
    		break;
    	case 0:
    		vis3 = "---";
    		break;
    	}
    	return vis3;
    }
    int randrecht(){
    	int rnum;
    	rnum = rand()%7;
    	return rnum;
    }
    int main(void){
    	srand(time(NULL));
    	char *zeichen;
    	char *visuel;
    	char *vergleich;
    
    	zeichen = (char *)malloc(sizeof(*zeichen) * 10);
    	visuel = (char *)malloc(sizeof(*visuel) * 10);
    	vergleich = (char *)malloc(sizeof(*vergleich) * 10);
    
    	int eingabe;
    	int rnum;
    	int i,e;
    
    	printf("Linux-Rechte Test\n");
    	do{
    		printf("Wählen sie zwischen folgenden Möglichkeiten:\n");
    		printf("1.Test Starten\n");
    		printf("2.Beenden\n");
    		scanf("%d", &eingabe);
    
    		//generiert eine 3 stellige zufalls-zahl
    		printf("Gib die rechte für die Zahl: ");
    		for (i = 0;i < 3;i++) {
    			rnum = randrecht();
    			printf("%d", rnum);
    			*zeichen=getrecht(rnum);
    			strcat(visuel,zeichen);
    		}
    		printf(" ein!\nBsp: r-xrw----\n");
    		//vergleicht antwort mit lösung
    		do {
    			scanf("%s",vergleich);
    			e = strcmp(vergleich, visuel);
    
    		} while (e != 0);
    		//ausgabe
    		printf("Eingabe korrekt");
    		system("pause");
    		system("cls");
    	}while(eingabe == 1);
    
    	free(vergleich);
    	free(zeichen);
    	free(visuel);
    }
    


  • *zeichen=getrecht(rnum);
    

    Durch den * Operator greifst du auf das erste Element zu auf das zeichen zeigt, dem wird dann getrecht zugewiesen nicht zeichen.



  • Aber sobald ich das * entferne wird das = als Fehler markiert und er sagt mir:

    Ein Wert vom Typ ""char"" kann keiner Entität vom Typ ""char *"" zugewiesen werden.

    Tut mir ja echt leid aber ich weiß beim besten Willen nicht was das bedeuten soll.



  • Warum liefert getrecht ein char und kein char*?

    Benutze std::string.



  • manni66 schrieb:

    Warum liefert getrecht ein char und kein char*?

    Benutze std::string.

    Das nützt aber nur etwas wenn er den Rest auch nach C++ umschreibt und so wie es aussieht lehrt der Lehrer C.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum C (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • wechlol.vb schrieb:

    2. Du initialisierst visuel mit "", d.h. an erster stelle steht ein abschließendes '\0'.
    Alles was danach kommt wird von Stringverarbeitungsfunktionen nicht beachtet.

    Das ist natürlich Quatsch.
    Ein Naivling mit Helfersyndrom aber ohne Ahnung plappert irgendwas nach, was er irgendwo aufgeschnappt aber nicht verstanden hat um es anwenden zu können.

    Insbesondere ist es genau strcat, wo der Speicher nach dem String manipuliert wird.
    Die Wurzel allen Übels ist aber das Ändern von Elementen eines Stringliterals mit strcat auf visuel, das nennt man auch UB, um hier mal Ordnung in deine weitschweifigen und nicht den Kern treffenden Laien-Erklärungsversuche zu bringen.



  • Dein getrecht ist Mist.

    Als Rückgabewert hast du ein char (kann genau ein Zeichen aufnehmen).
    Bei return hast du aber ein char*. Das ist ein anderer Typ.

    Durch das fehlende free zu dem malloc produzierst du Speicherlecks ohne Ende.

    Du kannst dich an strcpy orientieren. Dort übergibst du auch den Zielstring.

    Oder du machst gleich ein Array of char*

    static char *dateirechte[] = {"---", "--x", "-w-", "-wx", .... , "rwx"};
    
    char *getrecht(int zahl) {
    
       hier Fehlerbehandlung machen;
    
       return dateirechte[zahl];
    }
    

    Für 10 Werte lohnt kein malloc .
    Du kannst auch mit Zeigern auf Arrays arbeiten.



  • DirkB schrieb:

    Dein getrecht ist Mist.

    Dazu muss ich sagen das ich noch einen Algorithmus schreiben will der diese Zeichen selbst zusammensetzt... Das sollte wesentlich kürzer und effizienter als ein switch case sein!



  • Cambaru schrieb:

    DirkB schrieb:

    Dein getrecht ist Mist.

    Dazu muss ich sagen das ich noch einen Algorithmus schreiben will der diese Zeichen selbst zusammensetzt...

    Wenn du das switch durch einen Algorithmus ersetzt, wird es nicht besser, da der switch -Teil der richtig ist (bis auf ein fehlendes break).
    Das drumherum ist Mist:

    char getrecht(int zahl) {                      // char als Rückgabetyp  
        char *vis3;
        vis3 = (char *)malloc(sizeof(*vis3) * 10); // Wo ist das free?
        ....
        return vis3;                               // Rückgabe von char*
    }
    

    Cambaru schrieb:

    Das sollte wesentlich kürzer und effizienter als ein switch case sein!

    Nicht unbedingt.
    Das switch arbeitet (intern) mit einer Sprungtabelle und muss nicht rechnen.

    Aber als Übung ist es OK.



  • Wenn du das switch durch einen Algorithmus ersetzt, wird es nicht besser, da der switch -Teil der richtig ist (bis auf ein fehlendes break).
    Das drumherum ist Mist

    Das ist inzwischen das letzte Problem welches ich habe.
    Ich habe keine Ahnung wie ich eine Funktion zu einer char* Funktion mache,falls dies überhaupt möglich ist... Beim recherchieren bin ich dabei nur auf Funktionsarten gestoßen die ich bereits kannte. 😕

    Und natürlich geht es mir nicht um Effizienz sonder nur um mir das Programmieren näher zu bringen und etwas mehr Praxis zu bekommen.

    Außerdem nochmal danke für die Antworten die ihr mir bisher gegeben habt! 👍


  • Mod

    Cambaru schrieb:

    Ich habe keine Ahnung wie ich eine Funktion zu einer char* Funktion mache,falls dies überhaupt möglich ist... Beim recherchieren bin ich dabei nur auf Funktionsarten gestoßen die ich bereits kannte. 😕

    Und natürlich geht es mir nicht um Effizienz sonder nur um mir das Programmieren näher zu bringen und etwas mehr Praxis zu bekommen.

    Das ist doch eine wunderbare Gelegenheit, richtig Programmieren zu lernen. Du scheinst gelernt zu haben, irgendwo abzuschreiben und dann zu verändern, wie man an deinem Kommentar zu "Funktionsarten" erkennen kann. Besser wäre es gewesen, wenn du gelernt hättest, wie man selber Funktionen schreibt. Und hier noch viel wichtiger, wie Zeichenketten funktionieren, so dass du weißt, wie man damit umgehen muss. Dein Lehrer scheint in dieser Hinsicht vollkommen versagt zu haben 😞

    Wir können dir hier natürlich nicht C beibringen (und merke: C hat mit C++ praktisch nichts zu tun; außer der Bedeutung verschiedener Sonderzeichen und allgemeiner Programmiererfahrung wirst du in C++ nichts von deinem C-Wissen verwenden können), aber wir können dich zumindest auf brauchbare Bücher verweisen:
    http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list



  • Cambaru schrieb:

    Dazu muss ich sagen das ich noch einen Algorithmus schreiben will der diese Zeichen selbst zusammensetzt... Das sollte wesentlich kürzer und effizienter als ein switch case sein!

    Bitteschön:

    #include <stdio.h>
    
    static const char perm[4] = "rwx";
    
    // Doppelt gemoppelt:
    char *getperm( char *vis, int num )
    {
    //	printf( "num: %d\n", num );
    
    	for( int i = 0; i < 3; ++i )
    		vis[i] = (num & (4 >> i)) == 4 >> i ? perm[i] : '-';
    
    	return vis;
    }
    
    int main( void )
    {
    	char vis[4] = "eop";
    	puts( getperm( vis, 3 ) ); // puts( vis );
    	puts( getperm( vis, 6 ) ); // puts( vis );
    	puts( getperm( vis, 5 ) ); // puts( vis );
    	puts( getperm( vis, 7 ) ); // puts( vis );
    	return 0;
    }
    

Log in to reply