Char-Array definieren
-
Hallo Zusammen!
Eines vorweg: Ich bin kein C++ Kenner! Ich habe in meinem Studium mal zwei Semester "Programmieren in C" gehabt und muss mich nun zwangsweise wieder mit der Thematik beschäftigen. Ich möchte über TCP/IP Parameterwerte einer Maschine auslesen. Der Maschine muss ich dafür Befehle, wie z.B. "002R:SCRW1_H_BAR_Z01.ACT.VAL" übergeben. Das habe ich auch mit den entsprechenden Tutorials hinbekommen, allerdings definiere ich mir diese Befehle z.Zt. noch so:
buf[0] = 0; buf[1] = 0; buf[2] = 2; 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] = '1'; buf[20] = '.'; buf[21] = 'A'; buf[22] = 'C'; buf[23] = 'T'; buf[24] = '.'; buf[25] = 'V'; buf[26] = 'A'; buf[27] = 'L';Und das finde ich nicht so wirklich toll

Ich hab es auch schon folgendermaßen versucht, leider ohne Erfolg:
strcpy(buf, "SCRW1_H_BAR_Z01.ACT.MAX"); char buf[50]="SCRW1_H_BAR_Z01.ACT.MAX";Daher bin ich für Eure Hinweise, wie ich das ganze "kompakter" ausführen kann sehr dankbar!
Viele Grüße
Tobsen
-
Probier's mal mit
#include <string> ... std::string instr("SCRW1_H_BAR_Z01.ACT.MAX"); //da du WinAPI verwendest: deineFunktion(/*...*/, instr.c_str() /*...*/); ...
-
struct struktur{ char befehl1[10] = {'b','y','a',.....'x'}; char befehl2[5] = {'b','y','a','x','t'}; } befehle;dann kannst du über befehle.befehl1 drauf zugreifen..
-
tobsenmh schrieb:
strcpy(buf, "SCRW1_H_BAR_Z01.ACT.MAX"); char buf[50]="SCRW1_H_BAR_Z01.ACT.MAX";Bei Variante 1 kommt es drauf an, wie buf deklariert wurde.
Variante 2 sieht eigentlich gut aus, abgesehen davon, dass du nicht unbedingt 50 Zeichen reservieren musst. Das ginge auch so:
char buf[]="SCRW1_H_BAR_Z01.ACT.MAX";Trotzdem ist deine Zeile nicht falsch. Was heißt denn "leider ohne Erfolg"? Compiler-Fehler? Laufzeit-Fehler? Unerwünschtes Verhalten?
-
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