Hallo gibt es eine Mödlickeit in C einen String in einen Hexstring
umwandeln.
BSP.(Hexwerte stimmen natürlich nicht)
char x[]="Ha"
char b[]= "04 F8"
etwas so,
dank im Voraus
Natürlich gibt es die Möglichkeit. Du schreibst Dir eine entsprechende
Funtion, und schon geht's.
Du musst ja nur den String zeichenweise iterieren, jedes Zeichen in eine
zweistellige Hexzahl umwandeln, ein Leerzeichen dazwischen packen und
das Resultat in den Ergebnispuffer packen.
Leichte Übung.
na ich hab auch ne vorstellung wie man das eventuell machen könnte.
ich hab mir zwei variablen abgelegt lowbyte,highbyte,
dann hab ich ne for schleige wo ich für jedes Zeichen des Strings den
dec wert bestimme
in der for schleife ab ich ne switch anweisung
und dann hab ich das 256 cases
wo ich dann, wenn dec zum bsp 1 ist lowbyte 0 und highbyte 1
und zum schluss setze ich dann meinen neuen string zusammen
aber das muss doch auch einfacher gehen, falls das so überhaupt geht
mein Weg gefällt mir überhaupt nicht
ich probiere es jetzt über modulo
hab zuerst char array angelegt, char a{0,1,2,.....,E,F}
char highbyte
char lowbyte
hab jedes Zeichen durch 16 gerechnet, da bekomme ich ja einen Integer
zurüch, der mir die hexzahl beschreibt.
und dann hab ich ne if-Anweisung
Integer<127
highbyte 0;
lowbyte=tab[a]
aber irgendwie funktionierts noch nicht so ganz
Dann zeig doch mal den kompletten quellcode.
Wenn du die dann noch die ASCII Tabelle anschaust, den bereich von
'0'-'F' wirst du auch noch merken das du das array nicht wirkich
brauchst.
Gast schrieb:
> hab jedes Zeichen durch 16 gerechnet, da bekomme ich ja einen Integer> zurüch, der mir die hexzahl beschreibt.>> und dann hab ich ne if-Anweisung>> Integer<127>> highbyte 0;>> lowbyte=tab[a]
Sehr brav. Damit bist du dann auch für EBCID gerüstet. Damit
programmierst du exakt am C-Standard und dem was er dir alles erlaubt.
(Zurücklehn und auf das Geheul wartend)
> aber irgendwie funktionierts noch nicht so ganz
Grundregel:
Beschreibe nicht deinen Code. Zeig ihn einfach her.
@ asffrsff
spielverderber, damit lernt er doch nichts.
und warum 2 Schleifen, das ganze dann noch mit printf ist auch nicht
gerade performant.
Der Gast war doch schon auf dem richtigen weg.
**grins**
ein paar Sachen korrigiert usw., ...
Ansonsten:
sizeof(array) liefert die Grösse des Arrays zurück,
strlen(array) liefert die Länge des Strings im Array zurück. Das hab ich
im while(...) verhackstückt.
VG,
/th.
Peter schrieb:
> @Random ...> Hoffentlich wird "Hallo" nicht mal länger als 20 Zeichen ...
Nunja, ist ja nur ein sample :-)
Latürnich muss man sich da vorher Gedanken drüber machen.
Aber, ich kann dich beruhigen, solange wir ASCII verwenden wird "Hallo"
immer 5+1 Zeichen lang sein **grins**
VG,
/th.
Über die Namen lässt sich noch streiten...
Man beachte, nun ist kein Array mehr drin. Damit ist nun auch 'Wort' ein
schöner(er) String.
Btw: Ich liieeeebe Zeiger **grins**
VG,
/th.
immer diese magic numbers..
> HexWort = (char *) malloc ((strlen(Wort)* 5 * sizeof(char)) +1);
jetzt noch das langsame printf rausschmeissen und dann ist es auch noch
schnell...
Random ... schrieb:
> Man beachte, nun ist kein Array mehr drin. Damit ist nun auch 'Wort' ein> schöner(er) String.
Nur noch eine winzig kleine Unschönheit :-)
Der erzeugte String endet mit einem ' '
Hmm. Jetzt bist du übers Ziel hinausgeschossen.
Das was du da vorhast, ist gar nicht so einfach wasserdicht zu machen.
sizeof(Format) ergibt in diesem speziellen Fall 8
ok, machen wir strlen(FORMAT).
Hatte das hier kurz getestet und das Ergebnis war 6. Damit dachte ich,
das wär ok.
Aber so kann man sich irren :-)
VG,
/th.
>Probier das mal mit> char *Wort = "";
Hier gehts, weil wir ja mit dem Pointer schon einen hinterm letzten
(Leer-)Zeichen stehen.
Klar, dass man das nciht zu Beginn machen darf :-)
Random ... schrieb:
> ok, machen wir strlen(FORMAT).
Auch das funktioniert nicht.
Das Problem: Der Inhalt von FORMAT codiert wieviele chars du pro
Einheit benötigst. Du bräuchtest so etwas wie einen Parser, der sich den
Formatstring vornimmt und ausrechnet, wieviele Character printf dafür
erzeugen wird.
"0x02X " produziert 5 Stellen
"0x04X " produziert 7 Stellen
Und selbst das wird nicht stimmen, da printf auch die angegebenen Zahlen
ignorieren kann, wenn das Feld zu klein ist um das Ergebnis aufzunehmen.
Machst du
printf( "%2d", 128 );
ist das Ergebnis 3 Character lang, auch wenn im Formatstring steht, dass
du nur 2 Character haben willst.
Random ... schrieb:
>>Probier das mal mit>> char *Wort = "";>> Hier gehts, weil wir ja mit dem Pointer schon einen hinterm letzten> (Leer-)Zeichen stehen.> Klar, dass man das nciht zu Beginn machen darf :-)
:-)
Das einfachste an dieser Stelle wird wohl ein vorzeitiger return sein
(Ich geh mal davon aus, dass der ganze Klapperatismus sinnvollerweise in
einer Funktion stattfinden wird)
Was soll man auch bei einem leeren Eingabestring für einen Hex-String
erzeugen :-)
Ich wollte nur aufzeigen, dass der Teufel oft im Detail steckt.
Es ist nämlich erstaunlich schwierig, solche
String-wird-aus-anderem-String-generiert Funktion zu schreiben, die
absolut wasserdicht sind.
Karl heinz Buchegger schrieb:
>> da ich ja noch an was anderem arbeite **g**>> Da gehts dir wie mir. ggggg
aber immer wieder nett so ne spielerei. Schön wirds dann bei **array :-)
Hallo, hab einen eurer Codes mal ausprobiert und etwas herumgespielt.
Mir ist irgendwie unklar warum nicht der String HexWort richtig
ausgegeben wird wenn ich ihn in einer Funktion zurückgebe, ich versuche
grad C zu lernen.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
char* test(void);
int main(int argc, char *argv[])
{
char *d;
d=test();
printf("%s\n", d);
system("PAUSE");
return 0;
}
char* test(void)
{
int b=5;
char Wort[] = "Hallo";
char co[100];
char HexWort[100];
int i=0;
for( i=0; i < b; ++i)
{
sprintf(&HexWort[i*3], "%02X ", Wort[i]);
}
//printf("%s", HexWort);
for(i=0; i < sizeof(Wort)*5; ++i)
{
//printf("%c", HexWort[i]);
}
strcpy(co,HexWort);
//printf("\n%s\n", co);
return co ;
}
co ist eine lokal variabel in der Funktion, sie existiert nicht mehr
wenn die funktion beenden ist.
> system("PAUSE");
bitte mach soetwas nicht, das ist ja furchtbar.
> also müsste ich ein zeiger der auf die adresse von co zeigt zurückgeben
Nein, das tust Du ja schon.
Vielmehr muss die Variable außerhalb der Funktion definiert/deklariert
und ihr als Zeiger übergeben werden.
Sprich: Der Aufrufer hat den Speicherplatz zur Verfügung zu stellen.
nein du musst mit malloc neuen speicher anfordern, dort den inhalt
reinkopieren und dann den zeiger zurückgeben.
Danach hast du aber das Problem das du den Zeiger auch wieder mit free
freigeben musst.
Alternativ kann du der funktion test auch schon ein zeiger reingeben wo
er den string reinkopierne soll.
void test( char* out, size_t size, const char* data )
{
//code von oben
strncpy( out, size, variabel mit hexdaten );
}
char[10] out;
test( out, sizeof( out ), "Hallo" );
printf("%s\n", out );
gut danke ich probier es erstmal mit der funktion malloc und dann
versuch ich den weg von rufus. kann ja schließlich nicht schaden alles
beides zu verstehen. das freigeben eines speicherbereich wird ja
sicherlich in einem Buch erklärt sein. Als Laie stelle ich mir das erst
mal nicht so schwer vor.
> Als Laie stelle ich mir das erst mal nicht so schwer vor.
ja bei dem kleinen Programm mag das auch noch gehen, wenn es mal größer
wird und auch noch eine Fehlerbehandlung mit rein soll wird es schon
schwerer.
Es gibt genug Programm die mit der zeit immer mehr Speicher brauchen,
ganz trivial scheint es also nicht zu sein.
hab das jetzt auf allen beiden Wegen probiert und es hat funktioniert,
sogar ohne das freigeben.
Mir ist trotzdem immer noch nicht ganz klar, wieso das bei Übergabe der
lokalen Adresse nicht funktioniert hat. Eigentlich gebe ich doch die
lokale Adresse als Wert auf einen Zeiger zurück. Wenn ich nun einen
neuen Speicherbereich mit der Funktion malloc, der ja die Adresse des
zurückgegebenen Strings enthält, in meiner Funktion anlege ist der
Zeiger ja auch local. Oder ist das bei Zeigern anders. Sind Zeiger
vielleicht ein spezieller Typ. Sehr seltsam mit den Zeigern!!!
> Mir ist trotzdem immer noch nicht ganz klar, wieso das bei Übergabe der> lokalen Adresse nicht funktioniert hat.
Die "lokale Adresse" war die Adresse einer automatischen Variablen.
Das sind Variablen, die innerhalb einer Funktion definiert werden. Diese
sind nur während der Laufzeit der Funktion gültig und werden auf dem
Stack abgelegt.
Mit Beendigung der Funktion steht der von der Funktion auf dem Stack
belegte Speicherplatz wieder einer anderen Verwendung zur Verfügung.
malloc fordert Speicher auf dem Heap an, der ist nicht mit dem Stack zu
verwechseln.
Gast schrieb:
> hab das jetzt auf allen beiden Wegen probiert und es hat funktioniert,> sogar ohne das freigeben.> Mir ist trotzdem immer noch nicht ganz klar, wieso das bei Übergabe der> lokalen Adresse nicht funktioniert hat. Eigentlich gebe ich doch die> lokale Adresse als Wert auf einen Zeiger zurück. Wenn ich nun einen> neuen Speicherbereich mit der Funktion malloc, der ja die Adresse des> zurückgegebenen Strings enthält, in meiner Funktion anlege ist der> Zeiger ja auch local. Oder ist das bei Zeigern anders. Sind Zeiger> vielleicht ein spezieller Typ. Sehr seltsam mit den Zeigern!!!
Nicht wirklich
Es geht grundsätzlich um den Unterschied bei der Übergabe von 'normalen
Variablen' und Arrays.
'normale Variablen' werden, sowohl in die Funktion als auch als
Returnwert, grundsätzlich immer übergeben, indem eine Kopie des Wertes
erzeugt wird.
1
intfoo()
2
{
3
intj=5;
4
returnj;
5
}
Beim return wird nicht j selbst (als Objekt) zurückgegeben, sondern es
wird eine Kopie des Inhalts von j (nämlich der Wert 5) zurückgegeben,
welcher dann vom Aufrufer
1
intk=foo();
seinerseits in einer Variablen abgespeichert werden kann. Hier geht also
ein Wert über die Funktionsschnittstelle.
Arrays sind in C die grosse Ausnahme.
Wenn du ein Array an eine Funktion übergibst oder von einer Funktion ein
Array returnierst, dann wird keine Kopie des Arrayinhaltes erzeugt,
sondern es wird die Adresse des Arrays an die Funktion übergeben, oder
die Funktion würde diese in einem Returnwert liefern.
Adresse ist gut. Nur muss der Arrayinhalt auch existieren, damit die
Adresse Sinn macht.
Bei Übergabe in eine Funktion hinein ist das kein Problem. Der Aufrufer
hat das Array und wenn er die Adresse in die Funktion hinein übergibt,
dann existiert das Array auch weiterhin. Aber beim return ist das anders
1
int*foo()
2
{
3
intk[2]={1,2};
4
5
returnk;
6
}
Hier wird die Adresse von k aus der Funktion heraus übergeben.
Gleichzeitig hört aber k mit dem Ende der Funktion auf zu existieren.
Damit hat der Aufrufer eine Adresse eines Arrays
1
int*kArray=foo();
welches, wenn er auf das erste mal auf die Werte im Array zugreifen
könnte, ganz einfach nicht mehr existiert.
Das ist ungefähr so, wie wenn ich dir die Adresse eines wahsinnig guten
Arztes gebe. Wenn du dann an die angegebene Position hinfährst, ist das
zugehörige Haus schon abgerissen. Möglicherweise wurde dort sogar schon
ein neues Haus gebaut, in dem jetzt ein Steuerberater residiert. Der
wird aber ziemlich dumm schauen, wenn du ihm deine Unterleibsbeschwerden
schilderst.
Gast schrieb:
> Sehr seltsam mit den Zeigern!!!
:-)
Es dauert ein bisschen, bis man dahinter steigt. Ein Großteil der
Laufzeitfehler in C-Programmen beruht auf nicht richtig initialisierten
oder falsch veränderten Zeigern. Dafür kann man viel mit Zeigern machen
- eben auch viel Unsinn ;-)
> Arrays sind in C die grosse Ausnahme.
Naja, was heisst ausnahme.
eigentlich ist char array[100] - abgesehen vom fix reservierten
Speicherplatz - ja nur eine andere Schreibweise für char *array, was die
weitere Behandlung angeht.
array[i] ist halt lesbarer als *(array+i).
Das es noch andere Unterschiede gibt, z.B. array[][] immer "rechteckig"
ist im Gegensatz zu *array[] oder **array, ist auch klar, aber die
Übergabe an Funktionen oder die Rückgabe ist identisch.
etwas OT:
Mir ist als einfacher Merksatz für Anfänger mal aufgefallen, wie sehr
sich die Typengleichheit durch C zieht. Rechts muss immer das stehen,
was links vorgegeben ist.
Z.B.
1
charFunc(intnum){return((num+48)&0xff);}
2
3
main
4
{
5
charval;
6
7
val=Func(1);
8
}
Ist typenmässig:
1
(char)val=(char)((int)(num+48)&0xff)
d.h. nach Auflösung des Funktionskopfes bleibt immer der (hoffentlich
richtige) Typ stehen.
Kann man z.B. in diesem Beispiel sehr deutlich machen:
Random ... schrieb:
>> Arrays sind in C die grosse Ausnahme.>> Naja, was heisst ausnahme.>> eigentlich ist char array[100] - abgesehen vom fix reservierten> Speicherplatz - ja nur eine andere Schreibweise für char *array, was die> weitere Behandlung angeht.
Nein.
Nicht schon wieder!
Du schreibst jetzt 100 mal: Arrays sind keine Pointer!
Lediglich dann, wenn der Arrayname alleine (also ohne Index) vorkommt,
degneriert ein Array zu der Startadresse seines ersten Elements und das
uch nicht in allen Fällen (zb sizeof). Wenn ein Array an eine Funktion
übergeben wird, kommt der Arrayname alleine vor und daher wird
konsequenterweise die Startadresse des Arrays übergeben.
Die Ansicht: Ein Array ist nur eine andere Schreibweise für einen
Pointer ist schlicht und ergreifend falsch ....
a.c
1
intglobalArray[100];
b.c
1
externint*globalArray;
... hier zb. geht es mächtig in die Hose.
Erzähl einem Nueling niemals, dass Arrays eigentlich Pointer sind (egal
in welchem Zusammenhang). Du führst ihn nur auf eine falsche Fährte.
LOL
Arrays sind keine Pointer, jep, aber werden genau so übergeben (wie du
ja sagst, ist der Array Name ein zeiger aufs erste element).
Oder nich?!?
:-)
Random ... schrieb:
> ...> Das es noch andere Unterschiede gibt, z.B. array[][] immer "rechteckig"> ist im Gegensatz zu *array[] oder **array, ist auch klar, aber die> Übergabe an Funktionen oder die Rückgabe ist identisch.
Das stimmt so auch nicht, man kann jeweils eine Dimension des Feldes
ungestraft durch einen Zeiger ersetzen, mehr nicht.
[][] ist etwas anderes als **
Biespiel:
1
#include<stdio.h>
2
#include<stdlib.h>
3
4
5
voidup_ff(intff[][2])
6
{
7
printf("ff[2][1] = %d\n",ff[2][1]);
8
}
9
10
voidup_pp(int*pp[])
11
{
12
printf("pp[2][1] = %d\n",pp[2][1]);
13
}
14
15
16
17
intmain(void)
18
{
19
intff[3][2]=
20
{
21
{11,12},
22
{21,22},
23
{31,32},
24
};
25
26
int*pp[3];
27
pp[0]=(int*)malloc(2*sizeof(int));
28
pp[0][0]=111;
29
pp[0][1]=112;
30
pp[1]=(int*)malloc(2*sizeof(int));
31
pp[1][0]=121;
32
pp[1][1]=122;
33
pp[2]=(int*)malloc(2*sizeof(int));
34
pp[2][0]=131;
35
pp[2][1]=132;
36
37
38
up_ff(ff);
39
up_pp(pp);
40
41
return0;
42
}
So wie hier im Beispiel klappt es; es wird einmal ein
int[][]-Feld an eine Funktion übergeben und ein int**
bzw. int*[] an eine andere.
Vertauscht man aber die Parameter (also pp an up_ff()
oder ff an up_pp()) geht es schief.
Die Übergabe eines int[][] ist etwas anderes als int**.
Sehr wohl lässt sich int** durch int*[]; wie gesagt der
erste [] ist durch * ersetzbar, alle weiteren (hier nur
einer) dann nicht mehr.
> ...
Diese beiden Versionen von func() sind austauschbar, weil es nur
ein eindimensionales Feld ist, und bei dieser einen und damit
ersten Dimension geht es.
Es wird in beiden Fällen der Zeiger auf das erste Element übergeben.
Dagegen in meinem obigen Beispiel mit pp und ff:
Bei ff gibt es nur die 3*2=6 Feldelemente; übergebe ich ff
an eine Funktion, wird die Adresse des ersten Elements in
ff übergeben.
Bei pp dagegen gibt es die 3 allokierten Felder (wenn man
sie so nennen mag, darum will ich mich nicht streiten),
sowie ein Feld mit Elementen jeweils vom Typ int*.
Und die Adresse des ersten dieser drei Elemente (also des
untersten der 3 int*) wird übergeben, wenn ich pp in die
Parameterliste schreibe, nicht die Adresse einer der int.
khb hat schon recht, wenn er die pauschale Aussage "Feld
gleich Zeiger" anmäkelt. Manchmal erscheinen sie austauschbar,
aber eben nicht immer.
Random ... schrieb:
> zugegeben, wo ich etwas holpere ist, wo ist der unterschied zwischen:>>
1
>voidfunc(chararray[]);
2
>voidfunc(char*array);
3
>
In dem Fall gibt es tatsächlich keinen Unterschied. Noch nicht mal C++
unterscheidet zwischen den beiden Formen. Der [] ist lediglich
"syntaktischer Zucker" der irgendwann einmal eingeführt wurde. Das
einzige was man der [] Schreibweise zugute halten kann, ist ein gewisser
dokumentarischer Wert, da hier die Funktion dokumentiert, dass die
übergebene Adresse nicht irgendein Pointer sein sollte, sondern dass die
Funktion ihn als Anfang eines Arrays auffassen wird. Aber was hilft dir
die 'Dokumentation', wenn sie vom Compiler zu keiner
Datentyp-Überprüfung herangezogen wird (was allerdings auch tatsächlich
nicht in allen Fällen möglich wäre - Stichwort dynamische Allokierung).
1
#include<iostream>
2
#include<typeinfo>
3
4
usingnamespacestd;
5
6
voidbar(intb[])
7
{
8
cout<<typeid(b).name()<<endl;
9
}
10
11
voidfoo(int*b)
12
{
13
cout<<typeid(b).name()<<endl;
14
}
15
16
intmain(){
17
18
inta[]={1,2};
19
intb;
20
21
cout<<typeid(a).name()<<endl;
22
23
foo(a);
24
bar(a);
25
26
bar(&b);// surprise: bar will ein Array, ich stopfe einen Pointer
27
// auf kein Array rein.
28
}
Ausgabe:
1
int [2]
2
int *
3
int *
4
int *
Arrays waren und sind in C (und aus Kompatibilitätsgründen auch in C++)
Bastarde, die anders funktionieren als die restlichen Datentypen ...
... mit einer klitzekleinen Ausnahme: Funktionspointer.
Bei jedem anderen Pointer muss man den Pointer dereferenziern um an das
Objekt hinter dem Pointer zu kommen. Bei Funktionspointern kann man die
dahinterstehende Funktion mittels
1
pointer(argumente);
aufrufen, also ohne Dereferenzierung des Pointers
1
(*pointer)(argumente);
Das ist zwar in der Schreibweise praktisch, aber eigentlich
inkonsequent.
Hallo Karl hein,
danke für deine Version, dachte es geht einfacher :-)
Hier ist meine Version:
string hexStr ("48616C6C6F");
string asciiStr;
int tmpHexNr=0;
int i=0;
while (i<hexStr.length()) {
string tmpStr (hexStr, i, 2);
sscanf (tmpStr.c_str(), "%X", &tmpHexNr);
char tmp = tmpHexNr;
asciiStr += tmp;
i +=2;
}