Umgang mit Pointern
-
Ich habe den Teil eines großen Projektes und dachte zu viel Code und geschreibe schreckt eher ab.
Im Grunde möchte ich üben einen Kommunikationsweg Daten austauschen(zur Zeit noch seriell oder ssh). Da die Datenmengen abundzu recht groß sein können(~4000Bytes), wollte ich dynamischen Speicher verwenden.
char *p_buffer=NULL; if((p_buffer=malloc(1024+1))==NULL) return 0; wr_cmd2("commando", &p_buffer); wr_cmd2("commando", &p_buffer); free(p_buffer);
ich möchte also ich unterschiedlichen Funktionen write read Kommandos absetzen können.
int wr_cmd2(char *cmd, char **recv_buffer){ switch(COMM_METHOD) { case CM_RS232: WriteReadComFixSize(cmd, *recv_buffer); break; case CM_SSH: GetAndSendInput(cmd); GetAndSendInput("\n"); ReadAndHandleOutput_untilprompt(*recv_buffer); break; default: printf("Unknown communicationway!"); } return 0; }
ReadAndHandleOutput_untilprompt() ließt mit readfile aus einer pipe
do { printf("available: %i\n",i_BytesAvailable); if((i_BytesAvailable-i_BytesCount)<READ_BUF_SIZE+1) // have always enough memory for a readfile with full READ_BUF_SIZE(512) { printf("alloc! %i - %i < 512+1 = %i\n", i_BytesAvailable, i_BytesCount, i_BytesAvailable-i_BytesCount); p_test=realloc(*lpBuffer, DEFAULT_BUF_SIZE+(READ_BUF_SIZE * ++i)+1);// +1 for stringnull at the end if(p_test==NULL) { printf("can't allocate memory, abort reading!"); return -1; } printf("i=<%i> allocate memory= %i\n", i, DEFAULT_BUF_SIZE+(READ_BUF_SIZE * i)+1); *lpBuffer=p_test; i_BytesAvailable=DEFAULT_BUF_SIZE+(READ_BUF_SIZE * i)+1; } if (!ReadFile(Redirect_Info.hOutputRead, *lpBuffer+i_BytesCount, READ_BUF_SIZE, &nBytesRead, NULL)) { if (GetLastError() == ERROR_BROKEN_PIPE) { printf("ERROR_BROKEN_PIPE"); return -2; } else { printf("error at ReadFile",); break; } } //counting i_BytesCount+=nBytesRead; printf("Bytescount: %i += nBytesRead %i\n", i_BytesCount, nBytesRead); *(*lpBuffer+i_BytesCount)=0; printf("strlen: %i\n",strlen(*lpBuffer)); }while(find_prompt(&(*lpBuffer), nBytesRead));
Der Auszug ist sicherlich nicht ansatzweise korrekt, dem bin ich mir bewusst, es soll nur meine Herangehensweise darstellen.
@swordfish: bei dem fail habe ich einen Breakpoint gesetzt, d.h. ich wäre nicht weiter gegangen im Fehlerfall.
-
Vielleicht möchtest Du einen Datentyp für Strings implementieren?
typedef struct string_tag { char *data; size_t length; size_t size; } string_t; string_t string_create(void) { string_t string = { calloc(1, 1), 0, 1 }; // Leerer String, '\0' terminiert. length = 0, size = 1 return string; } bool string_is_valid(string_t *string) { return string->data; } bool string_assign(string_t *dst, char const *src) { size_t new_length = strlen(src); if (new_length + 1 > dst->size) { char new_data = realloc(dst->data, new_length + 1); if(!new_data) return false; dst->data = new_data; } dst->size = new_length + 1; dst->length = new_length; strcpy(dst->data, src); return true; } // ...
@_Neuling sagte in Umgang mit Pointern:
@swordfish: bei dem fail habe ich einen Breakpoint gesetzt, d.h. ich wäre nicht weiter gegangen im Fehlerfall.
Ja, ne, das Komische ist das Initialisieren mit
NULL
und die umständliche Zuweisung in der condition vomif
.
-
Danke fürs Beispiel @swordfish, aber muss ich die Datenstruktur dann nicht genauso durchreichen mit Pointern, wie ich es im ersten Beitrag vor hatte?
-
Ja, weil du willst ja das Original verändern und nicht eine Kopie. Aber was ist das Problem dabei? Wenigstens hast Du so keine hässlichen "Doppelzeiger" mehr. Die Zauberworte heißen OOP und Kapselung.
// edit: Ich hab' dir
string_assign()
oben als Bleistift implementiert.string_append()
usw. ist dein Bier.string_destroy()
nicht vergessen.
-
Ich vermute ich verstehe was du mir sagen möchtest, aber wenn ich die Datenstruktur in die 3.Unterfunktion befördern muss, um den prompt zu suchen, brauch ich doch genauso wieder Doppelzeiger, ich sehe noch nicht ganz den Vorteil? Vllt brauch ich ein Beispiel um es korrekt zu verstehen?
-
@_Neuling sagte in Umgang mit Pointern:
[...] 3.Unterfunktion befördern muss, um den prompt zu suchen, [...]
Ne, du, ich hab' keine Lust zu suchen. Code?
-
Letztes codebeispiel, letzte Zeile, find_prompt() gibt 0 zurück, wenn der prompt gefunden werden konnte.
Edit: gut, in der letzten Funktion ist es nicht nötig by reference zu übergeben, da nicht verändert wird, dann sind in diesem Bsp zwei UnterfunktionenWie gesagt, ich versuche mir eine gute Programmierstruktur anzueignen, benötige aber dabei etwas Unterstützung
-
@_Neuling sagte in Umgang mit Pointern:
Letztes codebeispiel, letzte Zeile, find_prompt() gibt 0 zurück, wenn der prompt gefunden werden konnte.
Ja, dann wirst Du wohl eine
bool string_find(string_t const *haystack, char const *needle)
schreiben müssen.strstr()
ist dein Freund.@_Neuling sagte in Umgang mit Pointern:
in der letzten Funktion ist es nicht nötig by reference zu übergeben, da nicht verändert wird, dann sind in diesem Bsp zwei Unterfunktionen
Jein. Nötig nicht. Aber einen Pointer zu kopieren ist trotzdem billiger als die gesamte struct. Übergib per
string_t const *
.
-
@Swordfish sagte in Umgang mit Pointern:
Vielleicht möchtest Du einen Datentyp für Strings implementieren?
typedef struct string_tag { char *data; size_t length; size_t size; } string_t;
Length und Size, WTF?
Einer davon ist doch bestimmt überflüssig.
-
@RBS2 sagte in Umgang mit Pointern:
Length und Size, WTF?
Einer davon ist doch bestimmt überflüssig.Nur wenn der String immer nur soviel wächst wie absolut nötig. Ziemlich ineffizient.
Selber grund warum ein
std::vector<>
eine size und eine capacity hat.
-
@Swordfish Okay, reservierter Speicher vs. tatsächliche Stringlänge. Alles klar.
-
@RBS2 sagte in Umgang mit Pointern:
@Swordfish Okay, reservierter Speicher vs. tatsächliche Stringlänge. Alles klar.
Schlauer/Braver Junge!