http://www.pronix.de -> Forum -> C-Programmieren -> Code-Schnipsel

Unterseiten

Code-Schnipsel

Moderatoren: broesel, Martin Conrad, Patrick

Thema: hex2ascii

  • (nur registrierte Mitglieder)

hex2ascii

Patrick (Moderator) am 10.03.2006 um 19:24

void hex2ascii (char *s){
    int x=0, y=0;

    if	(NULL==s)
	return;

    for	(;s[y];++x,++y){
	// s[y]=='%'
	if	(s[y]==37){
		// hexadezimale Zeichenfolge in ASCII Code umwandeln
		s[x]=(s[y+1]>=65 ? ((s[y+1] & 0xDF) - 55) : (s[y+1]-48));
		s[x]<<=4;
		s[x]+=(s[y+2]>=65 ? ((s[y+2] & 0xDF) - 55) : (s[y+2]-48));
		y+=2;
		}
	else
		s[x] = (s[y]==43 ? 32 : s[y]);

	/*
		gültigen Bereich festlegen;
		muss nicht, kann aber nutzlich sein;
	*/
	if	(s[x]<32 || s[x]>126)
		x--;

	}

    s[x]=0;
    return;
    }

--
To follow the path: look to the master, follow the master, walk with the master, see through the master, become the master.

 

[EDIT] - Re: hex2ascii

Patrick (Moderator) am 10.03.2006 um 19:31

Die Funktion stammt ursprünglich aus Juergens Buch "C von A-Z".
Vieleicht benutzt ja sonst noch wer ausser mir Juergens Code und kann diese abgeänderte Version gebrauchen bzw. verbessern Grafik: Smilie Zwinker

--
To follow the path: look to the master, follow the master, walk with the master, see through the master, become the master.

 

Re: hex2ascii

Patrick (Moderator) am 04.08.2010 um 15:29

Passend dazu eine Funktion, welche einen String URL-Enkodiert.
Die oben genannte Funktion nutze ich derzeit unter dem Namen urldecode.

/*******************************************************************************
* URL-kodiert einen String.
* Gibt einen String zurueck, in dem alle nicht-alphanumerischen Zeichen durch
* ein Prozentzeichen (%) gefolgt von zwei Hexadezimalwerten ersetzt werden.
* Ausnahmen bilden '-' (Minus), '_' (Unterstrich), '.' (Punkt) und ' '
* (Leerzeichen). Leerzeichen werden durch ein '+' (Plus) ersetzt, die uebrigen
* Ausnahmen bleiben wie alphanumerische Zeichen erhalten.
*
* @param Zeiger auf dekodierten String.
* @param Zeiger auf encodierten String.
*******************************************************************************/
inline
static
char *urlencode ( const char *string )
{
 if (NULL == string)
  return NULL;

 char *encoded = malloc(strlen(string)*3 +1);
 if (NULL == encoded)
  die("urlencode() Speicherreservierung fehlgeschlagen.");

 unsigned long i=0, p=0;
 for (; string[i]; i++)
 {
  if (string[i] < 45
   || (string[i] > 46 && string[i] < 48)
   || (string[i] > 57 && string[i] < 65)
   || (string[i] > 90 && string[i] < 97 && string[i] != 95)
   || string[i] > 122)
  {
   encoded[p++]='%';
   sprintf((encoded+p), "%02X", (unsigned char)string[i]);
   p+=2;
  }
  else
   encoded[p++]=string[i];
 }

 encoded[p]='\0';
 return encoded;
}


Insbesondere die Zeile
sprintf((encoded+p), "%02X", (unsigned char)string[i]);

stört mich noch, es musste einfach nur schnell funktionieren.
Verbesserungsvorschläge?

--
To follow the path: look to the master, follow the master, walk with the master, see through the master, become the master.

 

Re: hex2ascii

broesel (webmaster) am 04.08.2010 um 16:17

Hallo Patrick,

in solchen Fällen wie diesem, wo Speicher reserviert wird und damit dann irgendwas gemacht wird (Standardbeispiel: explode()), ist es ratsame Praxis, eine Version zu bauen die mit "statischem Speicher" auskommt, und darauf aufbauend dann eine Wrapper-Funktion, die entsprechend Speicher reserviert und dann die statische Version aufruft:


#define is_urlencode_special_char(c) (!(isalnum(c) || (strchr("-_ .:/?&@", c) != NULL)))

void urlencode_s(char *dest, const char *src)
{
        while (src && *src) {
                if (is_urlencode_special_char(*src)) {
                        *dest++ = '%';
                        *dest++ = "0123456789ABCDEF"[(*src & 0xF0) >> 4];
                        *dest++ = "0123456789ABCDEF"[(*src & 0x0F)];
               } else if (*src == ' ') {
                        *dest++ = '+';
                } else {
                        *dest++ = *src;
                }

                src++;
        }

        *dest = '\0';
}

char *urlencode(const char *src)
{
        char *ret = NULL;
        char *p = (char *)src;
        int num = 0;

        while (p && *p) {
                if(is_urlencode_special_char(*p))
                        num += 3;
                else
                        num += 1;

                ++p;
        }

        ret = malloc(num + 1);
        if (ret == NULL)
                return NULL;

        urlencode_s(ret, src);
        return ret;
}


Das hat den Vorteil, dass der Benutzer entscheiden kann, wie er's denn gerne hätte, und in erster Linie natürlich dass man nur so viel Speicher reserviert, wie man auch tatsächlich braucht. strlen(string)*3+1 ist eine äusserst schlechte obere Schranke für den benötigten Platz.

Das nervige sprintf() wird man los, wenn man einen Lookup-Table baut (in unserem Fall den String "0123456789ABCDEF") und als Index den ASCII-Wert des jeweiligen Zeichens und ein bißchen Bit-Rumgeschiebe.

Weiterhin solltest Du beachten, dass @, :, ? und & üblicherweise nicht ersetzt werden. @ und : braucht man, um Benutzername und Passwort an Seiten zu übermitteln, also z.B. http://username:password@www.google.de/, und ? und & sind ja eh klar...

Möglich, dass es da noch andere Zeichen gibt, die üblicherweise nicht kodiert werden.

Hoffe, ich konnte Dir helfen. Ich hab mir das alles gerade aus dem Ärmel gezaubert, möglich dass sich da noch der ein oder andere Fehler versteckt.

Gruss,
Philip

--
The C Programming Quiz (externer link) - bitte Fragen einreichen :)

 

[EDIT] - Re: hex2ascii

Patrick (Moderator) am 05.08.2010 um 08:23

Die Idee mit der Lookup-Tabelle werde ich heute im Verlauf des Tages testen, danke sehr dafür.
Zitat:
Weiterhin solltest Du beachten, dass @, :, ? und & üblicherweise nicht ersetzt werden. @ und : braucht man, um Benutzername und Passwort an Seiten zu übermitteln, also z.B. http://username:password@www.google.de/, und ? und & sind ja eh klar...

Afaik stimmt das nicht ganz.
Die von dir genannten Zeichen haben eine Sonderstellung, ganz klar.
Sind diese Zeichen aber Bestandteil eines Parameterwertes, so müssen sie sehr wohl urlenkodiert werden.
Soll z.B. der Parameter 'msg' den Text 'thx&bye' enthalten, wird 'msg' urlenkodiert zu 'msg', gefolgt von einem Gleichzeichen '=', gefolgt vom urlenkodierten 'thx&bye' - 'thx%26bye'.
Das Ergebnis wäre dann also 'msg=thx%26bye' und nicht 'msg%3Dthx%26bye' oder 'msg=thx&bye'.

thx%26bye Grafik: Smilie Zwinker

--
To follow the path: look to the master, follow the master, walk with the master, see through the master, become the master.

 
  • (nur registrierte Mitglieder)