Hallo zusammen,
ich möchte gerne ASCII-Zeichen eines Strings, die Hexzahlen dastellen,
in Dezimalzahl umwandeln.
Also:
Buffer[4]== '2'
Buffer[5]== '7'
Buffer[6]== '1'
Buffer[7]== '0'
2710(hex) = 10000(dec)!
wie kann ich das am besten in C bewerkstelligen?
Grüße
Hallo Philipp,
ich bräuchte die Dezimalzahl als fertigen String. Mit Hilfe einer
for-Schleife würde ich die benötigten ASCII-Zeichen in ein char laden.
Nun habe ich ja "2710". Gibt es da schon ne fertige Funktion die mir das
in 10.000(dec) umwandelt bzw. wie muss ich vorgehen? Ich meine mich zu
erinnern, dass strtol() das nicht kann.
Grüße
Man kann dies auch selbst recht fix implementieren, man muss halt immer
Modulo 10 teilen und das Ergebnis mit 0x30 addieren. Dieses wird solange
wiederholt bis das Ende der Zahl erreicht ist. Ähnlich wird es bei
char-Arrays gemacht- jedoch mit dem Unterschied das die 0x30 abgezogen
werden müssen. Das Ende des Strings wird erreicht wenn der ausgegebene
Wert "\0" entspricht. Printf und Scanf, dort wäre mir das in der Form
nicht bekannt.
bei hexadezimal müsste man alles über 9 dann entsprechend mit A...F
ersetzen. Auch dies könnte man mittels eines Offsets realisieren.
Entsprechend muss man dann beim Modulo nicht mehr die Konstante 10
sondern 16 benutzen.
Wobei die verschiedenen Darstellungen können bei printf und scanf
entsprechend angepasst werden. Im wesentlichen muss der String in einen
Int umgewandelt werden. Alles andere kann mittels printf usw. realisiert
werden.
Wenn da allerdings jetzt ein Wert von A6B7C auftaucht, wie wird das
bspw. mit atoi() geregelt? Also wenn ich jetzt 'A' in einen Integer
umwandeln will...erhält der dann automatisch den Wert 10? sprich
10611712? Ich behandle nämlich derzeit in etwa die selbe Problematik.
VG
Hallo,
vielen Dank für die Tipps und Hinweise. Ich habe nun mal was probiert.
Allerdings will es noch nicht so richtig funktionieren.
Hier gibt es viele erfahrene Programmierer, für die es sicherlich ein
Klacks ist. Allerdings, ich als Anfänger, habe so meine Mühen. Ich
möchte ja den String 2710(hex) inden String 10000(dez) überführen und
über die serielle Schnittstelle wieder ausgeben.
Zu Marks Beitrag: Lässt sich diesr printf-Varaiante auch bei der
seriellen Übertragung einsetzen?
unsigned int hexatoi(const char * s) {
unsigned int i,summe;
summe = 0;
for (i=0;i<=3;i++)
{
summe *= 16^i;
if ((s[i] >= '0') && (s[i] <= '9'))
summe += (s[i] - '0');
if ((s[i] >= 'A') && (s[i] <= 'F'))
summe += (s[i] - 'A' + 10);
}
return(sum);
}
int main(void){
char wert;
wert = (char)hexatoi("2710");
send_string(wert);
}
Klaus schrieb:> int main(void){>> char wert;>> wert = (char)hexatoi("2710");>> send_string(wert);> }
Das geht so nicht. Einerseits ist ein char vom Wertebereich nicht
ausreichend, um den Wert 0x2710 aufnehmen zu können (je nach
Vorzeichen/nicht-Vorzeichen -128..+127 oder 0..255).
Dazu kommt, daß Du anzunehmen scheinst, daß "hexatoi" eine Zeichenkette
zurückgibt (auch wenn Du versuchst, statt der Zeichenkette nur ein
einzelnes Zeichen zu verwenden), das aber tut es nicht.
Du musst Deine Aktivität in zwei Schritte zerlegen:
1. Bestimme den Wert des "Hexstrings", also den Wert der als
Zeichenfolge vorliegenden Zahl in hexadezimaler Notation.
Das macht "hexatoi". Der zurückgegebene Wert ist ein vorzeichenloser
int, also ein 16-Bit-Wert. Kein char!
2. Wandle diesen Wert in einen "Dezimalstring" um, also in eine
Zeichenfolge, die die Zahl in dezimaler Notation wiedergibt.
Dazu benötigst Du Speicherplatz für den "Dezimalstring", dafür benötigst
Du Speicher. Der größte mit einer vorzeichenlosen 16-Bit-Zahl
darstellbare Wert ist 65535, das sind fünf Zeichen. Dazu kommt das
Stringendezeichen, also muss der Speicher für diese Zeichenkette
mindestens 6 Zeichen lang sein.
Die Umwandlung erledigt entweder eine der /printf/-Varianten (hier:
sprintf) oder aber eine von Dir selbst zu schreibende
/uitoa/-Funktion.
3. Sende den Inhalt dieses "Dezimalstrings" über Deine serielle
Schnittstelle irgendwohin.
"send_string" scheint dafür ausgelegt zu sein.
Klaus schrieb:> Allerdings will es noch nicht so richtig funktionieren.
Jo, da war ja auch noch ein kleiner Bug drin.
hier die korrigierte Version (mit Testaufruf):
Ich würde die Möglichkeit vorsehen (wie bei &=df geschehen), dass statt
der Großbuchstaben auch Kleinbuchstaben funktionieren:
So geht es eleganter, macht in der esten Version keine Unterdrückung
führender Nullen und 5 Stellen:
1
#include<stdio.h>
2
#include<conio.h> //für putch()
3
4
longhexatoi(char*s){
5
longr=0;//Result
6
charn;//Nibble
7
while(*s){
8
if((n=*s++&31)>15)
9
n&=15;//0x30 .. 0x3F '1' 31 --> 1
10
elsen+=9;//0x40 .. 0x6f 'a' 61 --> 1 +9=10
11
r=r*16+n;
12
}
13
return(r);
14
}
15
16
voidmain(void){
17
longwert=hexatoi("2710");
18
charc;
19
20
c=47;while(c++,(wert-=10000)>=0);putch(c);
21
c=58;while(c--,(wert+=1000)<0);putch(c);
22
c=47;while(c++,(wert-=100)>=0);putch(c);
23
c=58;while(c--,(wert+=10)<0);putch(c);
24
putch(48+wert);//48, da bei ungerader Stellenzahl wert positiv ist
25
}
Mit Unterdrückung führender Nullen und konstanter Ausgabelänge:
Philipp Klostermann schrieb:> Und noch ein Fehler.. :D
Die kann man vermeiden oder zumindest reduzieren, indem man nicht eine
einzige große Eierlegende-Wollmilchsau-Universalfunktion schreibt,
sondern sich die komplette Aufgabe in einfachere Teilaufgaben zerlegt
und für jede Teilaufgabe eine eigene Funktion schreibt.
Karl Heinz Buchegger schrieb:> Die kann man vermeiden oder zumindest reduzieren, indem ..
Oder indem man sich die Mühe macht, das auch mal zu kompilieren, bevor
man es ins Forum stellt. Der Fehler war ein falscher Rückgabetyp im
Funktionskopf, wofür sich die Fehler-Wahrscheinlichkeit im Falle der
Verwendung zweier Funktionen verdoppelt hätte, und die nicht-Verwendung
einer Temporären Variable zum Durchreichen des 2. Parameters an den
Rückgabewert, was durch die Verwendung zweier Funktionen auch nicht
vermieden worden wäre.
Ich stimme Dir grundsätzlich zu, dass es besserer Programmierstil ist,
große Funktionen aufzuteilen, aber das, worum es hier geht, ist doch
etwas zu einfach und klein, um noch weiter aufgeteilt zu werden. (Die
übliche Vorgabe aus meiner beruflichen Erfahrung ist, dass eine Funktion
nicht größer als eine Bildschirmseite sein sollte, was ich wiederum für
übertrieben und vor allen Dingen für zu pauschal halte.)
Philipp Klostermann schrieb:> Ich stimme Dir grundsätzlich zu, dass es besserer Programmierstil ist,> große Funktionen aufzuteilen, aber das, worum es hier geht, ist doch> etwas zu einfach und klein, um noch weiter aufgeteilt zu werden.
Gerade hier sind wir dann anderer Ansicht
Die Aufgabe lässt sich wunderbar aufteilen in:
Aus dem HEX-String eine tatsächliche Zahl zu machen
Aus der Zahl einen Dezimal-String generieren.
Da beides für sich alleine gesehen durchaus sinnvolle Einzelkomponenten
sind, macht es auch Sinn die beiden Teile getrennt zu behandeln.
1
char*HexToDez(constchar*sVon,char*sNach)
2
{
3
longtmp=hexToLong(sVon);
4
returnlongToDez(tmp,sNach);
5
}
Zusammen mit weiteren Umwandlungsfunktionen entsteht so ein Baukasten,
mit dem man sich die jeweils konkret benötigte ohne viele Umschweife
leicht zusammenstellen kann.
1
char*BinToDez(constchar*sVon,char*sNach)
2
{
3
longtmp=binToLong(sVon);
4
returnlongToDez(tmp,sNach);
5
}
6
7
char*HexToBin(constchar*sVon,char*sNach)
8
{
9
longtmp=hexToLong(sVon);
10
returnlongToBin(tmp,sNach);
11
}
12
13
....
Man kann das nicht früh genug lernen, dass sinnvolle Modularisierung
einer der Schlüssel zu einem guten, tragfähigen Programmierstil ist.
Es ist einer der Schlüssel, warum die Unix-Shells so überaus erfolgreich
und leistungsfähig sind.