Variablen an Funktionen übergeben scheitert!?



  • Hallochen,

    ich bin noch nicht lange mit C++ unterwegs und ecke ständig an, aber konnte es bisher immer lösen.
    Ich muss C++ nehmen und nitze die ArduinoIDE zum programmieren eines Arduino.

    Das Problem:
    Ich möchte eine Zeichenkette, die ich zerlegen will, an eine Funktion übergeben, jedoch kommt, statt der Zeichenkette, nur Unfug in der Funktion an.

    Derzeit zum testen so:

    
    void setup()
    {
        test('S,W,I,T,C.H');
    }
    
    void test(const char *befehlszeile)
    {
        Serial.print(" befehlszeile:"); // Testausgabe
        Serial.print(befehlszeile); // Testausgabe 
    
    }
    

    Das Ergebnis:
    befehlszeile:����o�����>�e���+���|����8�......

    Ich habe schon dutzende Schreibweisen und Formulierungen versucht, aber ich bekomme es nicht durch. 😞
    Wenn ich jedoch von einer PS2-TAstatur den Output durchschieße, funktioniert das einwandfrei.
    Es ist, als wenn hinterlegte Texte im Code chinesisch codiert wären!? ... uff!

    Hoffentlich weiß jemand, was hier los ist...


    Anmelden zum Antworten
     

  • Mod

    'dies ist keine Zeichenkette, sondern eine Art und Weise, wie man ein einzelnes exotisches Zeichen schreiben kann'

    "dies ist eine Zeichenkette"

    Schalte auch unbedingt Warnungen an. Der Compiler kann erkennen, dass das wahrscheinlich Blödsinn ist, ein Zeichen in einen Zeiger auf eine Zeichenkette umzuwandeln, auch wenn es technisch gesehen gültiges C ist.



  • Ja, ich habe schon alles mögliche versucht... auch Hochkommas und "... ich bin völlig ratlos.
    Ich probiers nochmal...



  • Habs generell so drin jetzt im Programm:

    char *command_1[] = {"S","W","I","T","C","H"," ","2"," ","0"," ","enter","pause"};
      for(i=0;i<=12;i++){ key_char(command_1[i]); }
    
    
    void key_char(char c)		
    {
        Serial.print(c);  // Testausgabe  
        uint8_t y = keycode(c);
      ...
    }
    
    uint8_t keycode(char c)		
    {
         Serial.print(c);  // Testausgabe
    }
    
    

    Aber ich bekomme in den folgenden Funktionen nur Entengrütze raus.


  • Mod

    Hier hast du das gegenteilige Problem, command_1 ist ein Array von (Zeigern auf) Zeichenketten, das ist nicht kompatibel zu char.

    C ist ziemlich frickelig was Zeichenketten angeht. Der Unterschied zwischen einem char und einem (Zeiger auf ein) Array von char ist extrem bedeutsam. Du musst ganz genau verstehen wie das funktioniert, denn das explodiert beim kleinsten Fehler. Vielleicht lieber erst einmal als Trockenübung auf der Konsole mit printf.



  • @SeppJ Ja, also mit Arrays in C++ ist die Hölle, aber ich weiß wirklich nicht, wie ich das umgehen könnte.
    Trocken Übungen mache ich schon 2 Tage und ich komme einfach nicht dahinter. Ich muss quasi aus dem Zeiger erstmal ein CHAR machen und hoffen, dass der mir dann keinen INT Code auswirft... wenn ich das korrekt verstanden habe?



  • Derzeit zum testen so:

    
    void setup()
    {
        test('S,W,I,T,C.H');
    }
    
    
    void setup()
    {
        test("S,W,I,T,C.H");
    }
    


  • int i;
    char x;
    // Zeile 1
    char *command_1[] = {"S","W","I","T","C","H"," ","2"," ","0"," ","enter","pause"};
    for(i=0;i<=12;i++){ x = command_1[i]; key_char(x); }
    

    das in ein CHAR zu schieben wars leider nicht...

    In PHP hat man sowas in sekundenschnelle umgesetzt, aber mangels assoc Arrays wird sowas kleines in C++ leider zur Wissenschaft. Oje... wem ist nur eingefallen, gerade diese Sprache für Arduino zu nutzen? 😃


  • Mod

    @j-foe sagte in Variablen an Funktionen übergeben scheitert!?:

    @SeppJ Ja, also mit Arrays in C++ ist die Hölle, aber ich weiß wirklich nicht, wie ich das umgehen könnte.

    Also in C++ wäre es eigentlich viel einfacher. Das Problem ist, dass du hier auf eine C-artige Untermenge eingeschränkt bist, damit das auf dem Arduino läuft (Ich nehme mal an, der mag weder vector noch string).

    Trocken Übungen mache ich schon 2 Tage und ich komme einfach nicht dahinter. Ich muss quasi aus dem Zeiger erstmal ein CHAR machen und hoffen, dass der mir dann keinen INT Code auswirft... wenn ich das korrekt verstanden habe?

    Nein, das geht ja rein logisch gesehen nicht. Du musst in deinen Kopf bekommen, dass ein Zeichen und eine Folge von Zeichen ganz unterschiedliche Dinge sind. Selbst wenn die Folge von Zeichen nur aus einem einzigen Zeichen besteht. Da kann man nichts so einfach umwandeln. Du kannst einzelne Zeichen in eine Zeichenkette packen, aber man kann kein Zeichen in eine Zeichenkette verwandeln. Du kannst aus einer Zeichenkette ein einzelnes Zeichen herauspicken, aber man kann aus einer Zeichenkette kein einzelnes Zeichen machen.

    Im Alltag unterscheidet man leider nicht zwischen Zeichen und Zeichenketten. Denk vielleicht eher an Gummibärchen und Tüten von Gummibärchen. Da ist vielleicht klarer, dass eine Tüte Gummibärchen kein Gummibärchen ist, selbst wenn nur eines drin ist (und dass auch 0 drin sein können!), oder dass man ein Gummibärchen nicht in eine Tüte Gummibärchen verwandeln kann, sondern höchstens das Bärchen in eine Tüte hineintun kann. Auch dass es nicht gut funktioniert, die Tüte selbst zu essen, wenn man ein Gummibärchen essen will.



  • Was für eine Lösung wäre denn stattdessen möglich?
    Ich will das so gestalten, dass jeder, der in den Code schaut, dann auch eigene Zeilen nachbauen und zufügen kann.

    Ich hatte das auch mit strtok() umgesetzt, aus einem String, aber als ich die extrahierten Zeichen dann weitergegeben habe, waren die dann auch chinesisch. ratlosguck

    Ja, das ist sicher alles sehr abgespeckt auf dem Arduino.


  • Mod

    Kommt halt drauf an, was du erreichen möchtest, ich weiß nicht, was deine Funktionen key_char und keycode tun sollen, aber sie sollen ja sicher was anderes können als nur eine Testausgabe zu machen.



  • Ja, sollen sie natürlich. 😉

    Das wird ein Modul für einen KC85 (DDR Rechner) und der wird über einen seriellen Output in die Tastaturbuchse gefüttert.
    Das ganze muss also zerlegt, in spezielle Codes verwandelt und dann gesendet werden.

    Generell funktioniert grob alles und ich kann von einer PS2 Tastatur wunderbar alles durchgeben, was an Anschlägen kommt.

    • keycode() wandelt Zeichen in Codes um
    • key_char() reicht das Ergebnis an die Outputroutine weiter (könnte man weglassen, aber wird für anderes auch benötigt und ich will nicht doppeln)

    Ich kann natürlich jeden Buschstaben auch einzeln als CHAR anlegen und absenden, aber das ist sehr viel Code und für Abänderungen quasi untauglich.


  • Mod

    "wandelt Zeichen in Codes um"

    Meinst du damit nun eine Folge von Zeichen, oder wiederholte Aufrufe mit einem Zeichen?

    Da es immer noch C++ ist, könntest du sogar eine Funktion (mit einem Namen) für beides machen, genauso wie Serial.print ja auch damit zurecht kommt, egal ob du ihm ein einzelnes oder eine Folge von Zeichen gibst. Aber ich weiß nicht, wie fit du in C++ bist und ob Überladung von Funktionen nicht ein bisschen fortgeschritten ist. Jedenfalls könntest du da dann eine Funktion bauen, die ein einzelnes Zeichen erwartet, und die andere Funktion schickt dann einzeln die Zeichen aus einer Zeichenkette in die erste Funktion.

    PS: Weiter oben schreibst du auch "enter" und "pause". Dir ist schon klar, dass das für den Computer nur die Zeichenfolge 'e', 'n', 't', 'e', 'r' ist, und keine tiefere Sonderbedeutung hat, außer du gibst ihm eine?


  • Mod

    Hier, so meine ich: https://ideone.com/HkbYaO
    Ich habe keine Arduino, und ideone erst recht nicht, daher habe ich mal nur Ausgaben gemacht, um das Prinzip zu zeigen.

    #include <iostream>
    using namespace std;
    
    void key_char(char c)
    {
    	cout << "Sende Zeichen an Output: " << c << '\n';
    }
    
    void keycode(char c)
    {
    	cout << "Codiere einzelnes Zeichen: " << c << '\n';
    	key_char(c);
    }
    
    void keycode(const char* str)
    {
    	cout << "Verarbeite ganze Zeichenkette: " << str << '\n';
    	for(const char *pos = str; *pos != '\0'; ++pos )
    	    keycode(*pos);
    }
    
    int main() {
    	keycode("blah");
    	keycode('x');
    	keycode("y");
    	return 0;
    }
    

    Verstehst du, was da passiert? Passt das zu deinem Vorhaben? Guck dir die Ausgabe genau an, kannst du nachvollziehen, wann warum welche Funktion aufgerufen wird? Verstehst du von jedem einzelnen Zeichen (besonders die *!) in meinem Programm, wo und warum ich sie setze? Ich fürchte, das ist das Mindestmaß an Können, um in C mit Zeichenketten zu hantieren. Ist nun einmal so. Wäre in anderen Sprachen wahrscheinlich sogar ekeliger, wenn man sich auf mikrokontrollerkompatible Datenstrukturen herablassen muss. C ist wenigstens gemacht für diesen Zweck.

    So allgemein vom Programmaufbau finde ich es aber unpassend, wenn eine Codierungsfunktion eine Ausgabefunktion aufruft. Wenn dann eher umgekehrt, dass man eine Ausgabe vorher passend codiert. Eine Funktion soll immer exakt eine einzige Aufgabe haben. Aber dies ist gerade nicht das Thema, daher habe ich es so gemacht, wie du beschrieben hast.



  • Ja, dafür gibt es ja die Routine zum umformen, denn wie willst du ein "Enter" als Zeichen hinterlegen und ein \n ist zum auswerten die Hölle. 😃

    Es soll eine leicht verständliche Eingabe von Zeichen/Befehlsfolgen geben und eben bei Bedarf deren Abarbeitung automatisch erfolgen können (quasi als virtueller Mensch an einer virtuellen Tastatur).
    Ich habe eine andere Vorlage auch und da wurde gleich mit Codes in Arrays gearbeitet, ... wie ich jetzt bemerke, wohl nicht grundlos. Aber das ist dann nur echt unschön zu ändern und man ist dann dran, Codes einzutippen.
    Zur Not baue ich ne Webseite, die das als Service macht... 😃

    Also ich bin eigentlich PHP Programmierer, daher ist mir zumindest Programmieren nicht fremd.
    Aber ich merke, dass das Niveau von C recht nah am Assembler zu sein scheint, was viele Dinge angeht und ich bin da quasi schon als Anfänger einzustufen.
    Ich hatte schon überlegt, eine Klasse und Objekte zu machen, aber da sind die Probleme gleichfalls noch da und nichts wird besser.


  • Mod

    @j-foe sagte in Variablen an Funktionen übergeben scheitert!?:

    Ja, dafür gibt es ja die Routine zum umformen, denn wie willst du ein "Enter" als Zeichen hinterlegen und ein \n ist zum auswerten die Hölle. 😃

    Du darfst durchaus '\n' schreiben, und ich würde auch von allen halbwegs computernahen Menschen erwarten, dass sie das direkt verstehen. In meinem Beispiel habe ich das ja auch kommentarlos benutzt.

    PS: Ich habe oben einen doppelten Beitrag. Will dich nur darauf aufmerksam machen, weil du den zweiten, wichtigeren Beitrag eventuell übersehen hast, weil du schon geantwortet hast, während ich ihn schrieb.



  • Naja, ich meine das eher in der Handhabung und Auswertung von Strings, aber generell finde ich ein "Enter" schon schöner. 🙂
    So extrem computernah sind die auch oft nicht.

    Oh... wo wie .... mal schauen, was ich übersehen habe...
    Ups, wirklich noch nicht gesehen. 😃



  • Ah, ok, so ganz geheuer ist mir dieses Konstrukt nicht:

    for(const char *pos = str; *pos != '\0'; ++pos )
    	    keycode(*pos);
    

    Der zerteilt quasi den String und sortiert jedes Zeichen auf ein Feld(Zeiger?) in Char.
    Das Sternchen ist doch ein Platzhalter für variable Anzahl von Elementen, wenn ich das richtig kapiert habe.
    So langsam wird mir manches klar. 😃 Ich hatte Char als eine Art String wahrgenommen, was so gar nicht hinhaut.

    Nein, die Codierfunktion macht keinen Output. Das war nur im Beispiel so.
    Die liefert mit Return einen int-Code zurück.

    Dank dir. Das hilft mir beim weiterdenken ... 🙂


  • Gesperrt

    @j-foe sagte in Variablen an Funktionen übergeben scheitert!?:

    Ah, ok, so ganz geheuer ist mir dieses Konstrukt nicht:
    for(const char *pos = str; *pos != '\0'; ++pos )
    keycode(*pos);

    Der zerteilt quasi den String und sortiert jedes Zeichen auf ein Feld(Zeiger?) in Char.

    Das Konstrukt ist völlig korrekt, und liest eine Zeichenkette bis zum nächsten newline char.

    Vielleicht solltest du mal C lernen? Obwohl... mich stören solche Rückfragen nicht...

    Edit: Pardon, bis zum Zeichenkettenende.


  • Mod

    @j-foe sagte in Variablen an Funktionen übergeben scheitert!?:

    Das Sternchen ist doch ein Platzhalter für variable Anzahl von Elementen, wenn ich das richtig kapiert habe.

    Nein, nein, überhaupt nicht! Da muss ich leider omggg zustimmen, du musst noch viel über die grundlegende Syntax von C und C++ lernen, sonst wird das nichts mit den Zeichenketten. Und auch grundlegende Konzepte, wie was ein Array ist. Leider kann ich kein php, daher kann ich dir die C-Konzepte nicht mit php-Begriffen erklären.

    So langsam wird mir manches klar. 😃 Ich hatte Char als eine Art String wahrgenommen, was so gar nicht hinhaut.

    Genau, deswegen schrieb ich ja so oft darüber, dass Zeichen und Zeichenfolgen ganz was anderes sind.


Anmelden zum Antworten