Char-Array definieren



  • Ich bin mir aber nicht sicher, ob strcpy eine Null-Terminierung benötigt.

    Sind es feste Befehle? Oder ändern die sich von Zeit zu Zeit?



  • zuckerlie schrieb:

    Ich bin mir aber nicht sicher, ob strcpy eine Null-Terminierung benötigt.

    Ein Stringliteral ist nullterminiert.



  • _matze schrieb:

    zuckerlie schrieb:

    Ich bin mir aber nicht sicher, ob strcpy eine Null-Terminierung benötigt.

    Ein Stringliteral ist nullterminiert.

    Stimmt, du hast recht, "blabla" - da wird automatisch eine Null-Terminierung dran gehangen, 'b' ist ein einzelnes char ohne Null-Terminierung 🙂



  • Ersteinmal vielen Dank für Eure schnelle Hilfe.
    Leider bin ich noch nicht am Ziel.
    Ich habe folgende Varianten ausprobiert:

    //std::string instr("0025R:SCRW1_H_BAR_Z01.ACT.MAX");
    //strcpy(buf,"0025R:SCRW1_H_BAR_Z01.ACT.MAX");
    //char buf[]={'0','0','25','R:SCRW1_H_BAR_Z01.ACT.MAX'};
    //char buf[]={'0','0','25','R',':','S','R','C','W','1','_','H','_','B','A','R','_','Z','0','1','.','A','C','T','.','M','A','X'};
    
    buf[0] = 0;			
    buf[1] = 0;			
    buf[2] = 25;	
    buf[3] = 'R';
    buf[4] = ':';
    buf[5] = 'S';		
    buf[6] = 'C';
    buf[7] = 'R';
    buf[8] = 'W';
    buf[9] = '1';
    buf[10] = '_';
    buf[11] = 'H';
    buf[12] = '_';
    buf[13] = 'B';
    buf[14] = 'A';
    buf[15] = 'R';
    buf[16] = '_';
    buf[17] = 'Z';
    buf[18] = '0';
    buf[19] = '2';
    buf[20] = '.';
    buf[21] = 'S';
    buf[22] = 'E';
    buf[23] = 'T';
    buf[24] = '.';
    buf[25] = 'V';
    buf[26] = 'A';
    buf[27] = 'L';
    
    //    if (send(s, instr.c_str(), 28, 0) < 0)
          if (send(s, buf, sizeof(buf), 0) < 0)
    

    Nur die nicht auskommentierte Variante funktioniert.

    Bei den anderen Varianten friert das Programm an der Stelle, an der eigentlich die Antwort empfangen werden soll ein (="leider ohne Erfolg" @ _matze):

    if (recv(s, buf, sizeof(buf), 0) < 0)
    

    @zuckerlie: Es sind feste Befehle, die ich nur einmal programmieren muss. D.h. zur Not könnte ich mich auch über die o.g. "Mammutzeilen-Lösung" retten, aber zumindest ein klein wenig schön soll das Programm dann doch schon sein... 😉

    @_matze:
    buf habe ich so deklariert (Vorlage des Maschinenherstellers):

    char buf[1024];
    

    Viele Grüße
    Tobsen



  • '25' gibt's nicht, was genau hast du getestet?
    Ansonsten:

    char buf[] = "\0\0\x19R:SCRW1_H_BAR_Z01.ACT.MAX";
    


  • if (send(s, instr.c_str(), 29, 0) < 0)
    

    Probier das mal und achte darauf, dass ein char nur ein Zeichen ist und nicht '25'.



  • zuckerlie schrieb:

    if (send(s, instr.c_str(), 29, 0) < 0)
    

    Probier das mal und achte darauf, dass ein char nur ein Zeichen ist und nicht '25'.

    Wie soll das denn gehen? '0' != 0



  • char buf[]={'0','0','25','R',':','S','R','C','W','1','_','H','_','B','A','R','_','Z','0','1','.','A','C','T','.','M','A','X'};
    
    buf[0] = 0;			
    buf[1] = 0;			
    buf[2] = 25;
    ...
    

    Du erzeugst hier mit den beiden Methoden nicht den gleichen String! 0 ist was ganz anderes als '0'. Du musst scheinbar am Anfang ein paar Steuerzeichen schicken, bevor der eigentliche Datenstring erwartet wird. Wenn dein Programmm mit den alternativen Methoden einfriert, dann vermutlich nur, weil du auf eine Antwort vom Gerät wartest, die einfach nicht kommt, weil du nie einen validen Befehl gesendet hast. Du kannst nicht druckbare Zeichen per Escape-Sequenz in einen String packen. Probier mal so:

    char buf[]="\x00\x00\x19\R:SCRW1_H_BAR_Z01.ACT.MAX";  //die ersten Zeichen sind 0,0,25 (dezimal)
    


  • 1. Verwende nicht Konstante, sondern die tatsächliche Länge des Strings, damit da kein Mist eingelesen bzw. nichts abgeschnitten wird.
    2. Verwende Konstante zur Überprüfung des Funktionsrückgabewertes. Ein beim Senden aufgetretene Fehler wird mit SOCKET_ERROR signalisiert und, wie du siehst, ist das nicht 0.

    WinSock2.h schrieb:

    #define SOCKET_ERROR (-1)

    Also:

    std::string instr("0025R:SCRW1_H_BAR_Z01.ACT.MAX");
    ...
    int sendResult = send(s, instr.c_str(), instr.size(), 0);
    if (sendResult != SOCKET_ERROR)
        ...
    else
        //Fehler in sendResult auswerten!!!
    

    Ansonsten weiß ich nicht, warum es bei dir schiefläuft.

    Edit: Jetzt ist halt die Frage, was bei dir nach dem if im Code kam: das auszuführende Programm oder eine Fehlerbehandlung. Ich hoffe das Letztere.



  • zuckerlie schrieb:

    if (send(s, instr.c_str(), 29, 0) < 0)
    

    Probier das mal und achte darauf, dass ein char nur ein Zeichen ist und nicht '25'.

    Wenn überhaupt, sollte man std::string::size() verwenden und nicht selber zählen. size() verzählt sich nicht. Aber eine 0 in std::string unterzubringen bzw. danach noch was zu verwertendes, ist gar nicht so einfach. Ich denke, std::string ist hier nicht angebracht. Eher ein old-style Array oder std::vector<char>.



  • [Rewind] schrieb:

    Ansonsten weiß ich nicht, warum es bei dir schiefläuft.

    Lies doch mal die anderen Beiträge. Es liegt an 0!='0'. Er braucht 0, schreibt bei seinem Versuchen in die Stringliterale aber '0' rein.



  • Der Vorschlag mit std::string kam am Anfang als er noch keine Zahlen verschicken wollte. Da er aber die Zahlen und die Stringliterale wahrscheinlich separat auswerten wird, kann man überlegen, ob man nicht zwei Datenpakete schickt. Wenn der Befehl als Ganzes ausgewertet wird, dann ist string bestens geeignet.



  • [Rewind] schrieb:

    Der Vorschlag mit std::string kam am Anfang als er noch keine Zahlen verschicken wollte. Da er aber die Zahlen und die Strinliterale separat auswerten wird, kann man überlegen, ob man nicht zwei Datenpakete schickt. Wenn der Befehl als Ganzes ausgewertet wird, dann ist string bestens geeignet.

    Er wollte schon im ersten Post Zahlen schicken.



  • _matze schrieb:

    zuckerlie schrieb:

    if (send(s, instr.c_str(), 29, 0) < 0)
    

    Probier das mal und achte darauf, dass ein char nur ein Zeichen ist und nicht '25'.

    Wenn überhaupt, sollte man std::string::size() verwenden und nicht selber zählen. size() verzählt sich nicht. Aber eine 0 in std::string unterzubringen bzw. danach noch was zu verwertendes, ist gar nicht so einfach. Ich denke, std::string ist hier nicht angebracht. Eher ein old-style Array oder std::vector<char>.

    ist aber kein problem.

    std::string asd = "\0\0\0\0asd";
    std::cout.write(asd.c_str(), asd.size());
    

    steht auch im standard irgendwo, dass string '\0' beinhalten darf ohne kaputt zu gehen.

    bb



  • unskilled schrieb:

    steht auch im standard irgendwo, dass string '\0' beinhalten darf ohne kaputt zu gehen.

    Echt? Cool. Wie funktioniert denn das? Wird nicht nur ein const char* an den Konstruktor gegeben? Bin tatsächlich etwas überrascht gerade. 🙂



  • cooky451 schrieb:

    unskilled schrieb:

    steht auch im standard irgendwo, dass string '\0' beinhalten darf ohne kaputt zu gehen.

    Echt? Cool. Wie funktioniert denn das? Wird nicht nur ein const char* an den Konstruktor gegeben? Bin tatsächlich etwas überrascht gerade. 🙂

    stimmt, ist natürlich der falsche ctor und somit hab ich doch müll geschrieben - sry.
    beinhalten darf der string '\0' zwar natürlich aber wenn man die zeichen nicht einzeln per push_back hinzufügt, muss man natürlich den ctor aufrufen:
    string(const char* str, size_type length)
    (oder die iterator variante)

    gehen würde z.bsp. folgendes:

    #include <iostream>
    #include <string>
    
    int main()
    {
    	char buf[] = {'\0', '\0', 'A' };
    	std::string str(buf, sizeof(buf)/sizeof(buf[0]));
    
    	std::cout << str << std::endl; //geht, weiß aber nicht, ob das vom standard garantiert ist - spielt hier aber auch keine rolle
    	std::cout.write(str.c_str(), str.size()); //geht auf jeden fall
    
    	std::cin >> buf[0];
    }
    

    ja, diesmal hab ichs extra getestet, bevor ich wieder was falsches erzähl^^

    bb



  • Jo, stimmt, so einfach kann das sein. 🙂



  • Moin und besten Dank für Eure Hilfen!

    char buf[] = "\x00\x00\x19R:SCRW1_H_BAR_Z02.ACT.VAL";
    

    ...ist letzen Endes zielführen. (Das "\" vor dem "R" hat dem Compiler nicht gefallen, deswegen habe ich es noch entfernt.)

    Allerdings habe ich nun zwei neue Probleme:

    1.) Was bei dem langen Befehl funktioniert hat, funktioniert bei dem kurzen Befehl hier leider nicht:

    //char buf[] = "\x00\x00\x02V:";
    
    buf[0] = 0;			
    buf[1] = 0;			
    buf[2] = 2;			
    buf[3] = 'V';		
    buf[4] = ':';
    

    Sind die beiden Varianten denn vom Inhalt her gleich, oder habe ich etwas falsch gemacht?

    2.) Ich müsste buf[] in meinem Programm mehrfach mit anderem Inhalt füllen. Wenn ich es einmal verwendet habe und dann später im Programm noch "umdefinieren" möchte, sagt mir der Compiler, dass das nicht geht. Geht´s aber vielleicht doch? 😉 Oder muss ich mir für jeden Befehl eine neue Variable definieren?

    Besten Dank und viele Grüße
    Tobsen



  • tobsenmh schrieb:

    2.) Ich müsste buf[] in meinem Programm mehrfach mit anderem Inhalt füllen. Wenn ich es einmal verwendet habe und dann später im Programm noch "umdefinieren" möchte, sagt mir der Compiler, dass das nicht geht. Geht´s aber vielleicht doch? 😉 Oder muss ich mir für jeden Befehl eine neue Variable definieren?

    geht nicht.
    was aber geht:

    std::string gimme_x()
    {
      const char[] value = { '\0', 'A', 'S', 'D' };
    
      return std::string(value, sizeof(value)/sizeof(*value));
    }
    
    std::string gimme_y()
    {
      const char[] value = { '\0', 'Q', 'W', 'E' };
    
      return std::string(value, sizeof(value)/sizeof(*value));
    }
    
    int main()
    {
      winapi_fct_1(gimme_x().c_str(), gimme_x().size());
      winapi_fct_1(gimme_y().c_str(), gimme_y().size());
    }
    

    bb



  • tobsenmh schrieb:

    Sind die beiden Varianten denn vom Inhalt her gleich, oder habe ich etwas falsch gemacht?

    Du musst schon "\x02" statt "\x19" schreiben.

    tobsenmh schrieb:

    2.) Ich müsste buf[] in meinem Programm mehrfach mit anderem Inhalt füllen. Wenn ich es einmal verwendet habe und dann später im Programm noch "umdefinieren" möchte, sagt mir der Compiler, dass das nicht geht. Geht´s aber vielleicht doch? 😉 Oder muss ich mir für jeden Befehl eine neue Variable definieren?

    Du kannst buf mehrfach füllen, z.B. mit strcpy/memcpy, aber das lohnt nicht, da du dann auf die Größe etc. achten musst. Nimm einfach neue Variablen.

    Edit: @unskilled
    Na ja, ich finde hier liefert std::string irgendwie überhaupt keinen Vorteil.. es wird eher komplizierter, unsicherer und langsamer. Warum nicht gleich:

    int main()
    {
      const char msg1[] = "...";
      send(sock, msg1, sizeof(msg1), buf);
      const char msg1[] = ",,,";
      send(sock, msg2, sizeof(msg2), buf);
    }
    

Anmelden zum Antworten