Umwandlung von ASCII-Zeichen, die Hexzahlen darstellen

Gast #2099954
Lesenswert?

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
Persönliche Seite #2099987
Lesenswert?

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.
Persönliche Seite #2099995
Lesenswert?

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.
Gast #2100107
Lesenswert?

Ungeprüft:
1
void HexToDez(const char* sVon, char* sNach)
2
{
3
 long i,j;
4
 for (i = 0, j = 0; *sVon ; sVon++)
5
 {
6
  char c = *sVon;
7
  i = i << 4;
8
  if (c <= '9')
9
  {
10
   i |= c - '0';
11
  }
12
  else
13
  {
14
    c &= 0b11011111;
15
    i |= c - ('A' - 10);
16
  }
17
 }
18
 for (j = 1000000000; !(i / j); j /= 10);
19
 for (; j > 0 ; j /= 10)
20
 {
21
  *(sNach++) = '0' + i / j;
22
 }
23
 *sNach = 0;
24
}
Gast #2100148
Lesenswert?

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
Gast #2100185
Lesenswert?

Hallo,
Hex-String zu Dezimal-String!

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
char s[] = "0D76";
unsigned long x;
x = strtoul(s, 0, 16);

printf("The value represented by the string \"%s\" is\n"

"%lu (decimal)\n" "%#lo (octal)\n" "%#lx (hex)\n",s, x, x, x);
return 0;
}
Gast #2100222
Lesenswert?

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);
}
Persönliche Seite #2100252
Lesenswert?

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.
Gast #2100886
Lesenswert?

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):
1
#include <stdio.h> // für printf im Testaufruf
2

3
void HexToDez(const char* sVon, char* sNach)
4
{
5
  long i,j;
6
  for (i = 0; *sVon ; sVon++)
7
  {
8
    char c = *sVon;
9
    i = i << 4;
10
    if (c <= '9')
11
    {
12
      i |= c - '0';
13
    }
14
    else
15
    {
16
      c &= 0xdf;
17
      i |= c - ('A' - 10);
18
    }
19
  }
20
  for (j = 1000000000; !(i / j); j /= 10);
21
  for (; j > 0 ; j /= 10)
22
  {
23
    int k = (i / j);
24
    *(sNach++) = '0' + (char)k;
25
    i -= k * j;
26
  }
27
  *sNach = 0;
28
  return sNach;
29
}
30

31
int main()
32
{
33
  char sDez[11];
34
  printf("%s\n", HexToDez("1A9c", sDez));
35
  return 0;
36
}
Gast #2101056
Lesenswert?

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
long hexatoi(char*s){
5
  long r=0;//Result
6
  char n;  //Nibble
7
  while(*s){
8
    if((n=*s++ & 31)>15)
9
         n&=15; //0x30 .. 0x3F  '1' 31 --> 1
10
    else n+= 9; //0x40 .. 0x6f  'a' 61 --> 1 +9=10
11
    r=r*16+n;
12
    }
13
  return(r);
14
  }
15

16
void main(void){
17
  long wert = hexatoi("2710");
18
  char c;
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:
1
void main(void){
2
  long wert = hexatoi("2710");
3
  char c,l=' ';//Leading Char (Leerzeichen oder 0)
4

5
  c=-1;while(c++,(wert-=1000000000)>=0);if(c)l='0';putch(l+c);
6
  c=10;while(c--,(wert+= 100000000)< 0);if(c)l='0';putch(l+c);
7
  c=-1;while(c++,(wert-=  10000000)>=0);if(c)l='0';putch(l+c);
8
  c=10;while(c--,(wert+=   1000000)< 0);if(c)l='0';putch(l+c);
9
  c=-1;while(c++,(wert-=    100000)>=0);if(c)l='0';putch(l+c);
10
  c=10;while(c--,(wert+=     10000)< 0);if(c)l='0';putch(l+c);
11
  c=-1;while(c++,(wert-=      1000)>=0);if(c)l='0';putch(l+c);
12
  c=10;while(c--,(wert+=       100)< 0);if(c)l='0';putch(l+c);
13
  c=-1;while(c++,(wert-=        10)>=0);if(c)l='0';putch(l+c);
14
  putch(58+wert);//48+10=58, da bei gerader Stellenzahl wert hier negativ ist
15
  }

Mit Unterdrückung führender Nullen und variabler Ausgabelänge:
1
void main(void){
2
  long wert = hexatoi("2710");
3
  char c,l=' ';//Leading Char (Leerzeichen oder 0)
4

5
  c=-1;while(c++,(wert-=1000000000)>=0);if(c)l='0';if(l!=' ')putch(l+c);
6
  c=10;while(c--,(wert+= 100000000)< 0);if(c)l='0';if(l!=' ')putch(l+c);
7
  c=-1;while(c++,(wert-=  10000000)>=0);if(c)l='0';if(l!=' ')putch(l+c);
8
  c=10;while(c--,(wert+=   1000000)< 0);if(c)l='0';if(l!=' ')putch(l+c);
9
  c=-1;while(c++,(wert-=    100000)>=0);if(c)l='0';if(l!=' ')putch(l+c);
10
  c=10;while(c--,(wert+=     10000)< 0);if(c)l='0';if(l!=' ')putch(l+c);
11
  c=-1;while(c++,(wert-=      1000)>=0);if(c)l='0';if(l!=' ')putch(l+c);
12
  c=10;while(c--,(wert+=       100)< 0);if(c)l='0';if(l!=' ')putch(l+c);
13
  c=-1;while(c++,(wert-=        10)>=0);if(c)l='0';if(l!=' ')putch(l+c);
14
  putch(58+wert);//48+10=58, da bei gerader Stellenzahl wert hier negativ ist
15
  }

Statt putch kann ein neuer String aufgebaut werden: s=s+c;
Gast #2101382
Lesenswert?

Und noch ein Fehler.. :D
1
char* HexToDez(const char* sVon, char* sNach)
2
{
3
  char* p;
4
  long i,j;
5
  p = sNach;
6
  for (i = 0; *sVon ; sVon++)
7
  {
8
    char c = *sVon;
9
    i = i << 4;
10
    if (c <= '9')
11
    {
12
      i |= c - '0';
13
    }
14
    else
15
    {
16
      c &= 0xdf;
17
      i |= c - ('A' - 10);
18
    }
19
  }
20
  for (j = 1000000000; !(i / j); j /= 10);
21
  for (; j > 0 ; j /= 10)
22
  {
23
    int k = (i / j);
24
    *(sNach++) = '0' + (char)k;
25
    i -= k * j;
26
  }
27
  *sNach = 0;
28
  return p;
29
}
30

31
int main()
32
{
33
  char sDez[11];
34
  printf("%s\n", HexToDez("1A9c", sDez));
35
  return 0;
36
}
Gast #2101565
Lesenswert?

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.)
#2101575
Lesenswert?

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(const char* sVon, char* sNach)
2
{
3
  long tmp = hexToLong( sVon );
4
  return longToDez( 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(const char* sVon, char* sNach)
2
{
3
  long tmp = binToLong( sVon );
4
  return longToDez( tmp, sNach );
5
}
6

7
char* HexToBin(const char* sVon, char* sNach)
8
{
9
  long tmp = hexToLong( sVon );
10
  return longToBin( 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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren