Hallo zusammen, ich bin gerade dabei, ein Programm zu schreiben, in dem eine Adresse in Hexadezimal von einem PC gesendet und weiter verarbeitet werden soll. Die Adresse lese ich mit fgets ein. Das Problem ist, dass der Wert 0x00 auch in der Mitte der Adressen vorkommt und nicht nur am Ende z.B. D3 88 00 FF FF 01 00. Die Adresse wird nur bis zu 88 eingelesen, schätzungsweise da die erste 00 als Ende angesehen wird. Gibt es eine Möglichkeit die komplette Adresse einzulesen? Programmiert wird in der Sprache C. #include <stdio.h> #include <string.h> int main(){ char adresse[8]; fgets(adresse, 8, stdin); printf("%s", adresse); fflush(stdin); } Danke schonmal für die Antworten.
:
Bearbeitet durch User
fgets() dient zum Einlesen von Zeichenketten. Du willst aber binäre Daten lesen, wo jedes byte einen beliebigen Wert haben kann. Dazu ist die Funktion fread() gedacht. https://www.tutorialspoint.com/c_standard_library/c_function_fread.htm > printf("%s", adresse); %s dient zur Ausgabe von Zeichenketten. Deine Adresse ist aber keine Zeichenkette, sondern eine Folge von Bytes. Gebe die 8 Bytes so aus:
1 | for (int i=0; i<8 i++) { |
2 | printf("%02x", adresse[i]); |
3 | }
|
An den String ein CR anhängen und darauf testen. Bei fread muss die Länge der Zeichenkette vorher bekannt sein.
Isi S. schrieb: > in dem eine Adresse in Hexadezimal von einem PC gesendet und weiter > verarbeitet werden soll. Mein Tipp: nimm ASCII-Zeichenketten, dann kannst du auch die üblichen ASCII-Steuerzeichen für Textanfang (STX) und Textende (ETX) oder Zeilenende (wie z.B. 0x0a und 0x0d für CR/LF) verwenden. - https://www.itwissen.info/Textende-end-of-text-control-character-ETX.html Und zusätzlicher Bonus: du kannst die Kommunikation mit jedem x-beliebigen Terminal mitlesen.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Mein Tipp: nimm ASCII-Zeichenketten Geht leider nicht. Die Adressen sind schon so vorgegeben, die kann ich nicht ändern.
Isi S. schrieb: > Die Adressen sind schon so vorgegeben, die kann ich > nicht ändern. Dann soll derjenige das lösen, der sich dieses krude Format ausgedacht hat. Ein Datenformat muß so definiert sein, daß sich Daten und Steuerinformationen eindeutig zuordnen lassen. Ansonsten hat der Entwickler gepennt oder er ist unfähig.
Beitrag #7509693 wurde vom Autor gelöscht.
Isi S. schrieb: > Geht leider nicht. Die Adressen sind schon so vorgegeben, die kann ich > nicht ändern. Wie sichert der, der dieses Format vorgegeben hat, die Übertragung ab, wenn in den Daten selber kein eindeutiges Ende erkennbar ist? Was passiert im EMV-Labor? Oder wenn ich da mal mit meinem "Bursttest für Anfänger"(**) aka. Viehtreiber draufhalte und ein fehlerhaftes Start- oder Datenbit erzeugt wird? (**) siehe dort im Beitrag "Re: Tiefentladungsschutz mit Attiny und P-Kanal Fet" Das ist ein nettes entwicklungsbegleitendes Tool... ;-)
:
Bearbeitet durch Moderator
Isi S. schrieb: > D3 88 00 FF FF 01 00 Werden diese Werte gelesen, dann liegt kein Hex-Format vor. Zahlen im Hexformat werden immer als lesbare ASCII-Zeichen (0=0x30, 1=0x31, 2=0x32 ...) übertragen. Die Daten liegen im **Binär-Format** vor! Zeichenweise lesen:
1 | #include <stdio.h> |
2 | |
3 | int main() { |
4 | char c; |
5 | |
6 | printf("Bitte geben Sie ein Zeichen ein: "); |
7 | |
8 | // Verwende getchar, um ein Zeichen einzulesen
|
9 | c = getchar(); |
10 | |
11 | printf("Sie haben das Zeichen '%c' eingegeben.\n", c); |
12 | |
13 | return 0; |
14 | }
|
Oder Blockweise: #include <stdio.h>
1 | int main() { |
2 | FILE *file; |
3 | char buffer[100]; // Ein Puffer, um Daten zu speichern |
4 | |
5 | // Datei im binären Modus öffnen
|
6 | file = fopen("dateiname.txt", "rb"); |
7 | |
8 | if (file == NULL) { |
9 | perror("Fehler beim Öffnen der Datei"); |
10 | return 1; |
11 | }
|
12 | |
13 | // 10 Zeichen aus der Datei lesen
|
14 | size_t elements_read = fread(buffer, sizeof(char), 10, file); |
15 | |
16 | if (elements_read != 10) { |
17 | if (feof(file)) { |
18 | printf("Ende der Datei erreicht.\n"); |
19 | } else { |
20 | printf("Fehler beim Lesen der Datei.\n"); |
21 | }
|
22 | } else { |
23 | printf("Gelesene Daten: %s\n", buffer); |
24 | }
|
25 | |
26 | // Datei schließen
|
27 | fclose(file); |
28 | |
29 | return 0; |
30 | }
|
ähhhm, das Lesen mit fgets dürfte funktioniert haben. Stop Character ist „end of line“ und nicht Null. Und bei EOF stoppt fgets ebenfalls. Die Ausgabe als String funktioniert natürlich nicht. Also einfach mal mit der schon vorgeschlagenen for-Schleife probieren. Als Ausgabeformat würde ich %.2hhx nehmen.
Zugegeben: das war für’s Einlesen jetzt nicht hilfreich, denn er erste Wert, in dem ein Bytewert 0x0a vorkommt, wird nicht vollständig gelesen.
Harald K. schrieb: > Isi S. schrieb: >> char adresse[8]; >> >> fgets(adresse, 8, stdin); > > Entdecke den Fehler. Es fehlt der Speicherplatz für den 0-char (Stringende), also char adresse[9]
Als Funktion würde ich fread() verwenden. Siehe Beispiel. fgets() ist ungeignet weil es für c-Strings ausgelegt ist. Bei binären Daten ist fread() besser geeignet.
:
Bearbeitet durch User
Isi S. schrieb: > Gibt es eine Möglichkeit die komplette Adresse einzulesen? Wie ist die Adresse formatiert? Gib mal drei Bespiele. Die zwei Ziffern 00 sollten das Lesen nicht stoppen ... LG, Sebastian
Sebastian W. schrieb: > Isi S. schrieb: >> Gibt es eine Möglichkeit die komplette Adresse einzulesen? > > Wie ist die Adresse formatiert? Gib mal drei Bespiele. Die zwei Ziffern > 00 sollten das Lesen nicht stoppen ... > LG, Sebastian Wenn man die Daten, dazu zählt auch die Adresse, mit String-Funktionen liest, dann wird es nicht gelingen Adressen in **allen** Kombinationsmöglichkeiten zu empfangen. Die Stringfunktionen erlauben keinen transparenten Empfang aller Bytekombinationen. Üblicherweise verwendet man für ein transparentes Lesen die Funktion fread(). Die Variable **buffer** kann die Struktur sein, welche die Daten in ihrer Reihenfolge im Telegramm abbildet. Z.B.
1 | struct TELEGR { |
2 | unsigned long adresse; |
3 | ínt datum1 |
4 | ínt datum2 |
5 | }buffer; |
size_t elements_read = fread(buffer, sizeof(TELEGR), 1, file); Wichtig ist zu beachten ist, dass die Order (MSB ...LSB), abhängig vom μP, passt
Isi S. schrieb: > Einlesen einer Hex Zahl von stdin Was sind HEX-Zahlen? Bekommst du jetzt einen Zeichenkette (String, ASCII Zeichen) oder Bytes gesendet? Bei einer Zeichenkette ist das 8. Zeichen schon bei der ersten 00. D3 88 00 FF FF 01 00 12345678901234567890
:
Bearbeitet durch User
Übrigens ist auch das Betriebssystem hier wichtig, denn stdin arbeitet defaultmäßig im Textmodus. Falls das Betriebssystem z.B. Windows sein sollte, führt der Stream in diesem Modus beim Lesen auch schon Änderungen durch, noch bevor die Daten im Programm ankommen. Dann muss man stdin erst mit freopen() auf den Binary-Modus umschalten. Isi S. schrieb: > fflush(stdin); Das hat nach C-Standard undefiniertes Verhalten. Lothar M. schrieb: > Wie sichert der, der dieses Format vorgegeben hat, die Übertragung ab, > wenn in den Daten selber kein eindeutiges Ende erkennbar ist? Ich würde jetzt bei so einem Format erwarten, dass Adressen keine beliebige Länge haben, sondern immer gleich lang sind und sich daraus ziemlich eindeutig das Ende ergibt.
Obelix X. schrieb: > Was sind HEX-Zahlen? Hexzahlen sind ASCII codierte Binärwerte. Wobei Hexzahlen ASCII '0' bx0000 bis '9' bx1001 und 'A' bx1010 bis 'F' bx1111 Ein Byte besteht aus zwei Hexzahlen Ein Word besteht aus vier Hexzahlen Ein DWord besteht aus acht Hexzahlen Hexzahlen können wiederum Binär dargestellt werden: 1. 8 Bit Binärwert 2. 8 Bit Binärwert z.B. "30" Hex => bx0011_0000 bx0011_0000 z.B. "A5" Hex => bx0100_0001 bx0011_0101 Nicht zu vergessen der Hex-String wird mit bx0000_0000 abgeschlossen!
:
Bearbeitet durch User
Gerald K. schrieb: > Obelix X. schrieb: >> Was sind HEX-Zahlen? > > Hexzahlen sind ASCII codierte Binärwerte. Das ist deine Definition von Hexzahlen :) Für die Hexadezimaldarstellung einer Zahl ist lediglich festgelegt, dass ein ein Stellenwertsystem verwendet wird, in dem jede Stelle einen Wert von 0 bis 15 hat, wobei die Werte 10 bis 15 in der für Menschen lesbaren Schreibweise üblicherweise mit den Buchstaben A bis F notiert werden. Für die Art und Weise, wie in der Computertechnik die einzelnen Ziffern jeweils in Gruppen von mehreren Bits codiert werden, gibt es viele Möglichkeiten und IMHO keine Norm, die einer dieser Möglichkeiten den Vorzug gibt. Die Codierung jeder Ziffer als ASCII-Symbol ist nur eine davon. Im Fall des TE (der sich ja nicht mehr meldet) sind die Hexziffern vermutlich als gepackte 4-Bit-Gruppen (Nibbles) codiert, was äquivalent ist mit einer Binärdarstellung, die die Binärziffern als gepackte 1-Bit-Gruppen codiert und der üblichen internen Darstellung von Integer-Zahlen im Hauptspeicher von Computern entspricht.
Yalu X. schrieb: > Im Fall des TE (der sich ja nicht mehr meldet) sind die Hexziffern > vermutlich als gepackte 4-Bit-Gruppen (Nibbles) codiert, was äquivalent > ist mit einer Binärdarstellung, Das ist dann aber nicht "hex", sondern eben binär. > die die Binärziffern als gepackte 1-Bit-Gruppen codiert und der üblichen > internen Darstellung von Integer-Zahlen im Hauptspeicher von Computern > entspricht. Du meinst das Dualsystem, bzw. für vorzeichenbehaftete Werte dessen Zweierkomplement.
Rolf M. schrieb: > Das ist dann aber nicht "hex", sondern eben binär. Ja, davon gehe ich aus. Sonst wäre das nicht passiert: Isi S. schrieb: > Die Adresse wird nur bis zu 88 eingelesen, > schätzungsweise da die erste 00 (danach) als Ende angesehen wird.
Rolf M. schrieb: > Yalu X. schrieb: >> Im Fall des TE (der sich ja nicht mehr meldet) sind die Hexziffern >> vermutlich als gepackte 4-Bit-Gruppen (Nibbles) codiert, was äquivalent >> ist mit einer Binärdarstellung, > > Das ist dann aber nicht "hex", sondern eben binär. Das kann als etwas ähnliches wie packed BCD angesehen werden, nur eben für Hexadezimal- statt Dezimalziffern. Man könnte es deswegen auch "packed BCH" (Binary Coded Hexadecimal) nennen. Da im Gegensatz zu BCD der Wertebereich der einzelnen Nibbles voll ausgenutzt wird, ist es letztendlich dasselbe wie binär codiertes Vierersystem und die übliche Binärdarstellung, nur die Betrachtungsweise ist eine andere.
Ich werfe noch mal hämisch Unicode in die erlauchte Runde ... LG, Sebastian
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.