Kopie von Variabel verwenden



  • Hi zusammen

    Ich hab ne Frage:

    Ich habe eine Funktion, die mir "\x0d" und "\x0a" Zeichen aus einem "char* rxBuffer" ersetzt, um die Ausgabe auf einer Zeile zu behalten.
    Nun habe ich jedoch gemerkt, dass ich eine zweite Funktion habe, die die 2. Zeile von diesem "char* rxBuffer" benötigt.

    Ich würde mein Programm gerne so umschreiben, dass ich statt die Originaldaten verändere zuerst eine Kopie von diesem "char* rxBuffer" mache und erst dies verändere. Jedoch auch wenn ich eine Kopie erstelle(char *copyRxBuffer) werden die Originaldaten (char *rxBuffer) verändert

    Hier die Funktionen:

    In dieser Funktion soll die Kopie erstellt werden und alles ersetzt werden.

    BOOL CSerialPort::ReceiveData (int bytesToReceive, char *rxBuffer, unsigned long* bytesReceived)
    {
    	BOOL readState;
    
    	if (hComm == INVALID_HANDLE_VALUE)
    	{
    		return (FALSE);
    	}
    
    	readState = ReadFile(hComm,rxBuffer , bytesToReceive, bytesReceived, NULL);
    
    	if (m_isDebugModeEnabled == 1)
    	{	char *copyRxBuffer = rxBuffer;                          //Hier versuche ich eine Kopie zu erstellen.
    
    		  replace(&copyRxBuffer, '\x0a', ' ');
    		  replace(&copyRxBuffer, '\x0d', ' ');
    
    		  cout << m_dateTime->DateTime() <<  "   Fluke --> PC : "<< copyRxBuffer  << endl; // Diese Ausgabe soll auf 1ner Zeile bleiben
    	}
    
    	/*<<timeStamp */
    	return (readState);
    }
    

    Replace Funktion:

    void CSerialPort::replace(char** buffer, char search, char replacement)
    {
    	if(buffer == NULL || *buffer == NULL) return;
    	char* str = *buffer;
    	while(*str++ != '\0')
    	{
    		if(*str == search) *str = replacement;
    	}
    }
    

    Ich glaube ich habe einen kleinen überlegungsfehler gemacht, komme aber nicht dahinter 😞

    Hoffe ihr könnt mir helfen.

    Danke & Gruss TTS



  • char *copyRxBuffer = rxBuffer;
    

    Du zeigst damit auf den selben Speicher! Somit änderst du das Original. Richtig wäre hier aber:

    EDIT: Hier stand mist!



  • Schau dir strcpy an. Dann schau dir std::string an.



  • char *p = "Hello, world!";
    	char a[14];
    	strcpy(a, p);
    
    	cout << a;
    

    Andere Möglichkeit wäre mit new/del dir neuen speicher für deinen zeiger zu reservieren und diesem dann den Wert *newpointer = *oldpointer zu übergeben.

    std::string würde aber deutlich leichter gehen. Siehe Vorredner.



  • Ich habe es so versucht:

    HighLigerBiMBam schrieb:

    Andere Möglichkeit wäre mit new/del dir neuen speicher für deinen zeiger zu reservieren und diesem dann den Wert *newpointer = *oldpointer zu übergeben.

    char* copyRxBuffer = new char;
    *copyRxBuffer = *rxBuffer;
    replace(&copyRxBuffer, '\x0a', ' ');
    replace(&copyRxBuffer, '\x0d', ' ');
    
    cout << m_dateTime->DateTime() <<  "   Fluke --> PC : "<< copyRxBuffer  <<  endl;
    

    aber im rxBuffer steht folgendes:
    *IDN?
    FLUKE, 45, 4851253, 1.6 D1.0
    =>

    Und nach der Zuweisung

    *copyRxBuffer = *rxBuffer;
    

    steht im copyRxBuffer :

    "*ýýýýð­º
    ð­º
    𭺫«««««««"

    Das macht doch kein Sinn oder? 😃



  • TTS schrieb:

    char* copyRxBuffer = new char;
    

    Hier forderst du nur Speicher für ein einziges Zeichen an, du müsstest eigentlich mindestens soviel Platz anfordern, wie rxBuffer lang ist.

    Ums nochmal hervorzuheben: Schau dir std::string an, wenn du mit C-Strings nicht so sattelfest bist. Da gehts nämlich ganz einfach:

    string rxBuffer;
    ...
    string copyRxBuffer = rxBuffer;
    


  • Ja das mit den strings wurde mir schon einige male gesagt, das die leichter zu verwenden sind. Jedoch erfordert meine Funktion einen "**char copyRxBuffer", wenn ich einen String verwenden würde, könnte die Funktion dann immernoch damit umgehen?



  • Meinst du deine eigene Funktion? Aber da kannst du doch die Signatur beliebig ändern.



  • Es funktioniert schon mal einigermassen. Es verwendet den richtigen buffer und schreibt mir alles schön in ein File.

    Jedoch beim

    delete copyRxBuffer
    

    kackt alles ab:

    Debug Error!

    Programm: ..\FlukeReader\AktuelleVersion\Debug\Fluke_45_Reader.exe

    DAMAGE: after Normal block(#112) at 0x003c24..

    (Press Retry to debug the application)

    Abort Retry Ignore

    Hat schon mal jemand von euch so eine Fehlermeldung erhalten?



  • Schau dir folgendes Beispiel an und verstehe es:

    #include <string>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	string rxBuffer = "Hallo Welt";
    	replace(rxBuffer.begin(), rxBuffer.end(), 'l', 'm');
    	cout << rxBuffer;
    }
    

    Damit kannst du dein Problem sehr einfach lösen.

    Edit: Schau dir dazu noch das Konzept der Iteratoren an. Alles, was ich genannt habe, steht in jedem Anfängerbuch.



  • TTS schrieb:

    Ja ich meine meine eigene Funktion.
    Natürlich kann ich meine Funktion verändern. Jedoch habe ich keine Ahnung wie ich die umschreiben soll, das sie noch funktioniert 😃

    Ächz
    Da kommt langsam die Frage auf, ob du der Aufgabenstellung überhaupt gewachsen bist... Ich habe den Eindruck, dass Codeschnipsel solange umsortiert werden, bis das Ergebnis halbwegs passt, ohne dass verstanden wird, was da überhaupt passiert.

    Am elegantesten lässt sich das Problem mit einem Funktor erschlagen, denke ich, obwohl der TE nicht verstehen wird, was da passiert.

    #include <functional>
    #include <algorithm>
    
    struct RemoveNewLine : public std::unary_function<char,bool>
    {
       bool operator()( const char& c ) const
       {
          return c == '\r || c == '\n';
       }
    };
    
    struct ReplaceNewLine : public std::unary_function<char,char>
    {
       char operator()( const char& c ) const
       {
          if( c == '\r' || c == 'n' ) return ' ';
          else return c;
       }
    };
    
    int main()
    {
       std::string data = "Hello\r\nWorld";
    
       // alle \r und \n löschen
       data.erase( std::remove_if( data.begin(), data.end(), RemoveNewLine() ), data.end() );
    
       // alle \r und \n durch Leerzeichen ersetzen
       std::transform( data.begin(), data.end(), data.begin(), ReplaceNewLine() );
    }
    

    Der erste Ansatz löscht alle Vorkommen von \n und \r indem er die Vorkommen durch die nachfolgenden Elemente überschreibt. remove_if überprüft für jedes Zeichen im Eingabestring, ob es ein \n oder \n ist, wenn ja, wird es zum Löschen markiert (ohne jetzt auf Interna einzugehen). Die Kombination von erase/remove_if entfernt jedenfalls alle Elemente, auf die das Prädikat von remove_if zutrifft.
    Ähnlich arbeitet transform, es ruft für jedes Element eine Funktion auf, die das Ergebnis der Operation bestimmt. Für \n und \r ist das Ergebnis ein Leerzeichen, für alle anderen Zeichen wird das Eingabezeichen zurückgegeben.



  • Michael E. schrieb:

    Schau dir folgendes Beispiel an und verstehe es:

    #include <string>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	string rxBuffer = "Hallo Welt";
    	replace(rxBuffer.begin(), rxBuffer.end(), 'l', 'm');
    	cout << rxBuffer;
    }
    

    Damit kannst du dein Problem sehr einfach lösen.

    Edit: Schau dir dazu noch das Konzept der Iteratoren an. Alles, was ich genannt habe, steht in jedem Anfängerbuch.

    Vielen Dank.. mit dem wurde mir alles klar 😃



  • @TTS

    BOOL CSerialPort::ReceiveData (int bytesToReceive, char *rxBuffer, unsigned long* bytesReceived)
    

    Ich versteh trotzdem nicht, warum Du einer Memberfunktion( Klasse - definitiv c++) unbedingt eine typische C-Signatur verpassen musst.
    Wer schreibt dir das vor? Ist die Memberfunktion statisch (Das die als FktPtr verwenden kannst) ?

    C++ like und um Welten unkomplizierter waer :

    BOOL CSerialPort::ReceiveData(std::string & Buffer)
    

    (statt std::string sollt man std::vector<char> verwenden, wenn die Daten Null-Zeichen enthalten koennen)

    Ciao ...


  • Mod

    RHBaum schrieb:

    (statt std::string sollt man std::vector<char> verwenden, wenn die Daten Null-Zeichen enthalten koennen)

    Das juckt den String aber auch nicht im geringsten. Die Unterschiede sind bloß die zusätzlichen Zeichenkettenmanipulierungsmethoden von String, sowie die Überladung des Streamausgabeoperators. Theoretisch gibt es noch den Unterschied, dass bei vector<char> garantiert ist, dass die Elemente sequentiell im Speicher liegen, String darf theoretisch egal wie aufgebaut sein - in der Praxis irrelevant, da alle Implementierungen den String sequentiell speichern. Mit den gleichen theoretischen Überlegungen könnte man auch argumentieren, dass die garantierte sequentielle Anordnung der Vectorelemente nicht zwangsläufig heißt, dass diese von vorne nach hinten geordnet sind.


Log in to reply