Tag zusammen
So geht es:
unsigned char CRCText[8];
CRCText = "CRC-Test";
Aber warum kann ich einen String unbekannter Länge so nicht deklarieren?
unsigned char CRCText[];
Ich dachte wenn in C in der Klammer nichts steht dann ist die
Stringlänge variabel? Geht leider nicht.
Wie kann ich machen dass ich jede Länge Text eingeben kann?
Grüsse
Maria
Du hast nicht nur einen Fehler gemacht ;-)
1. Buffer Overflow weil an jeden String wird eine \0 angehängt. also
brauchst du für 8Zeichen 9Bytes!!!
2. Du willst bestimmt dass hier:
unsigned char CRCText[] = {"CRC-Test"};
3. Man kann keinen kompletten string mit dem Zuweisungoperator >>=<<
während des weiteren Programmablaufes zuweisen. Dazu benötigt man die
Funktion: strcpy() oder strcat()
Mfg
Ulrich
> unsigned char CRCText[8];> CRCText = "CRC-Test";
Das ist aber schon nicht i.O.. "CRC-Test" hat nicht 8, sondern 9
Zeichen. Spätestens, wenn hinter dem String etwas anderes gespeichert
wird, geht Dir der Nullterminator flöten und eventuell zur Ausgabe
benutzte Funktionen finden das String-Ende nicht!
Eine Deklaration eines Strings braucht immer entweder eine Anzahl der
Feldelemente oder eine explizite Definition. Also
> Ich dachte wenn in C in der Klammer nichts steht dann ist die> Stringlänge variabel?
Und um das auch noch explizit anzusprechen.
1) In C gibt es eigentlich keinen eigenen Datentyp
für "String"
2) Strings werden in character Arrays gespeichert
3) Es ist deine Aufgabe dafür zu sorgen, dass das
Array gross genug ist. Dabei das abschliessende '\0'
Zeichen nicht vergessen
4) Der Compiler hilft dir und befreit dich von ermüdender
und fehleranfälliger Zeichenzählerei, indem er bei
char Text[] = "Mein Text";
die Zeichen selbst abzählt und das Array entsprechend gross
macht, sodass der komplette Text, inklusive '\0' Zeichen
da drin Platz hat.
5) Alles darüber Hinausgehende, ist das Bier des Programmierers.
Allerdings fragt man sich, warum das so ist - am Urtext von Kernighan &
Ritchie kann es zumindest seit dessen zweiter Ausgabe nicht liegen, der
beschreibt das eigentlich ganz anständig. Und die deutsche Übersetzung
ist auch in Ordnung (ganz im Gegensatz zu der der ersten Ausgabe).
Vielleicht fangen zu viele Leute mit so merkwürdigen Programmiersprachen
wie Basic, Pascal, Delphi, Java, C# etc. an ... die einem vor den harten
Tatsachen des Lebens schützen wollen.
>(ganz im Gegensatz zu der der ersten Ausgabe).
Ich finde die erste Ausgabe immer noch "besonders gut" (von einem
Computer übersetzt) - das dürfte ein Klassiker werden.
>Aber warum kann ich einen String unbekannter Länge so nicht deklarieren?>>unsigned char CRCText[];
Ich glaube so geht es:
unsigned char* CRCText;
CRCText = "CRC-Test";
Die schon genannten Lösungen mit gleichzeitiger Deklaration und
Zuweisung dürften aber effizienter sein.
Frag mich nicht, was genau der Unterschied zwischen char* und char[]
ist, hatte deine Probleme aber auch schon.
>Ich glaube so geht es:
Sind wir hier in der Kirche?
>Frag mich nicht, was genau der Unterschied zwischen char* und char[]>ist, hatte deine Probleme aber auch schon.
Eigentlich sollte man dir dafür den K&R um die Ohren hauen.
char* ist ein Pointer auf ein Byte.
char[] veranlasst den Compiler dazu, ein entsprechend grosses Array
(inkl. "\n") anzulegen.
Auf das Array wird durch einen Pointer zugegriffen.
Rahul, der Trollige wrote:
> Eigentlich sollte man dir dafür den K&R um die Ohren hauen.> char* ist ein Pointer auf ein Byte.> char[] veranlasst den Compiler dazu, ein entsprechend grosses Array> (inkl. "\n") anzulegen.> Auf das Array wird durch einen Pointer zugegriffen.
Wobei man der Gerechtigkeit halber sagen muss, dass die erste Form
natürlich ebenfalls ein Array anlegt, das hat nur keinen Namen, und
wenn man den Zeiger darauf ,,vergessen'' hat (weil man z. B. mit
Pointerarithmethik CRCText++ ausgeführt hat), gibt es niemanden
mehr, der den im Speicher vorhandenen Inhalt dieses Arrays noch
legal dereferenzieren kann. Gewissermaßen ist
1
char*foo="Text";
sowas wie
1
charinvisible[]="Text";char*foo=invisible;
wobei der Namen invisible danach ,,vergessen'' wird.
Wobei es noch einen Fehler gibt.
Eigentlich müsste es korrekterweise
1
constchar*foo="Text";
heissen.
Illegal wäre auch
1
char*foo="Text";
2
foo[2]='s';
weil foo ja auf ein String-Literal zeigt und das ist per Definition
konstant also nicht änderbar.
wohingegen
1
charfoo[]="Text";
2
foo[2]='s';
absolut legales und gültiges C ist. foo ist ein Array und wird
beim Erzeugen mit den Charactern 'T', 'e', 'x', 't', '\0' gefüllt.
Und wie bei jedem anderen Array kann man natürlich den Arrayinhalt
ändern.
Aber Rahul hat schon recht. Wer Pointer empfiehlt
ohne selbst zu wissen was er tut, dem sollte ...
Hey das ist mein K&R, den nimmst du nicht!
> Frag mich nicht, was genau der Unterschied zwischen char* und char[]> ist, hatte deine Probleme aber auch schon.
Die hat praktisch jeder Anfänger, weil Zeiger und Arrays in C ziemlich
unintuitiv sind. Es gibt viele Feinheiten, und erst wenn man alle davon
kennt, versteht man die ganze Sache. Schon die verwirrende
kontextabhängige Verwendung von [] ist ohne vernünftige Anleitung ein
Mysterium:
1
charc[]="Hello, world\n";// c ist ein Array aus char
2
charc[];// geht nicht.
3
4
voidfunc(charc[]);// c ist ein Zeiger auf char
Wer hier glaubt, das dritte c sei ein Array, wundert sich unter
Umständen nachher, warum sizeof() Müll zurückzugeben scheint.
Viele Anfänger glauben sowieso, Arrays und Zeiger seien dasselbe, oder
daß char* der String-Typ von C sei, und benutzen diese Sachen
entsprechend (char* c = "The number is " + 5;). Das sind zumindest die
von mir am häufigsten beobachteten Fehler von C-Einsteigern. Da die
Annahmen aber falsch sind, kracht's irgendwann, und man hat keine
Ahnung, warum.
Daher würde ich auf jeden Fall ein gutes C-Buch empfehlen. Ich hab's
zwar auch ohne geschafft, aber das hat wesentlich länger gedauert, als
nötig gewesen wäre.
Hallo
Vielen Danke mal für eure Hilfe.
Mit gewisser Kritik hier habe ich Mühle.
Denn jeder fängt mal an.
Irgendwie gibt es hier nur 2 Arten Menschen.
1. Die die C beherrschen
2. Die anderen die C überhaupt nicht beherrschen
Was dazwischen wird von gewissen Leute gar nicht akzepiert.
Ich lese im Moment ein C++ Buch. Leider ist es nicht immer einfach
alles zu verstehen. Es ist vielfach recht schwierig den Befehl in C zu
finden den man in Delphi oder so schon kennt.
Ich suche im Moment den Befehl der in Delphi "Copy" heisst.
In "Pelles C" Hilfe habe ich noch nichts gefunden oder habe es
übersehen.
Gruss
Maria
Es gibt zwei Arten Menschen:
1. Die, die kein Delphi können
2. Die, die glauben, jeder könnte es
SCNR (bitte nicht so ernst nehmen)
Was macht "Copy" in Delphi denn?
Wenn du C++ machst, solltest du das Gerödel mit den
char-Arrays zunächst mal zur Seite legen. In
C++ gibt es die std::string Klasse. Die funktioniert
so, wie man sich eine String-Klasse vorstellt. Damit
ist es schon wieder Kunst etwas falsch zu machen.
Erst später, mit etwas mehr Erfahrung, komm nochmal
auf C-Strings (aka character Arrays und was damit
zusammenhängt) zurück.
> Was dazwischen wird von gewissen Leute gar nicht akzepiert.
Oh doch, das wird es durchaus.
Nur: was nicht akzeptiert wird ist, wenn jemand
einen schlechten Rat gibt. Nicht deshalb weil er sich
vertan hat, sondern weil er (wie er selbst sagt)
keine Ahnung hat, was da eigentlich vor sich geht.
Das ist schliesslich ja auch in deinem Interesse,
dass dieses aufgeklärt wird.
Ausserdem: So schlimm ist das hier gar nicht. Schau
mal in internationale News-Groups (comp.lang.c++,
comp.lang.learn-c-c++). Da werden ab und zu Leute regelrecht
zerfleischt. Dagegen ist das hier harmlos.
Ich weiss dass C++ und C nicht genau das selbe ist.
Ich habe mir ein Buch für C++ für die PC Programmierung gekauft
Somit hoffe ich dass ich C für AVR und C++ für PC mit einer Klappe
schlage.
Mir ist jetzt schon klar dass jetzt viele dageben protestieren bin aber
der Meinung dass ich in so kurzer Zeit schon viel erreicht habe.
Im Moment habe ich keine Lust noch zusätzlich ein Buch nur für C zu
kaufen da neben den Kosten auch der Zeitaufwand steigt.
"Copy" in Delphi kopiert einen Teil aus einem String heraus
Beispiel:
strT :String
strT := Copy ('ABCDEF12345',3,4);
strT = 'CDEF';
>>Frag mich nicht, was genau der Unterschied zwischen char* und char[]>>ist, hatte deine Probleme aber auch schon.>>Eigentlich sollte man dir dafür den K&R um die Ohren hauen.
Das gute Ding!
>char* ist ein Pointer auf ein Byte.>char[] veranlasst den Compiler dazu, ein entsprechend grosses Array>(inkl. "\n") anzulegen.>Auf das Array wird durch einen Pointer zugegriffen.
ebend: durch einen char*
Ich glaube immer noch, dass mein Vorschlag funktioniert.
Ciao, muss in die Messe
>Irgendwie gibt es hier nur 2 Arten Menschen.>1. Die die C beherrschen>2. Die anderen die C überhaupt nicht beherrschen>>Was dazwischen wird von gewissen Leute gar nicht akzepiert.
Es gibt noch die, die C überhaupt nicht beherrschen, die aber meinen,
dass sie zu 1. gehören und noch deshalb nur ihre eigene flasche Meinung
akzeptieren:
>Eigentlich müsste es korrekterweise>>const char* foo = "Text";
Wozu sollte das const nötig sein? Sicherlich ist es in den meisten
Fällen sinnvoll, aber uneigentlich ist "char* foo = "Text";" genauso
korrekt. Glaube ich.
In diesem Zusammenhang habe ich auch eine Frage an die Experten: ich
brauche häufig Aufrufe wie
char s[10];
int x;
sprintf(s,"%10d",x); oder
sprintf(s,"x=%s",s2);
Wie kann ich hier Speicherfehler ausschließen? Zumindest beim ersten
(Format %10d") kann man nicht sichergehen, dass tatsächlich nur 9
Ziffern geschrieben werden, da ints in Zukunft beliebig groß werden
könnten.
Beim zweiten (Format "x=%s", s2 ist ein zweiter char* auf eine
Zeichenkette unbekannter Länge) kann ich gar keine Länge vorschreiben.
Sicher, ich könnte das durch zwei strncpy's lösen, was aber deutlich
umständlicher wird.
Gibt es sowas wie sNprintf, also eine sprintf-Funktion mit Angabe der
maximalen Zeichenzahl?
Was macht man sonst? Vor jedem sprintf mit zig Abfragen checken, dass
z.B. bei einem Format "%10d" die int-Variable nicht mehr als 10 Stellen
hat? Oder einfach 10x mehr Speicher reservieren als für heutige ints
nötig, und hoffen, dass das Programm nicht mehr eingesetzt wird, wenn
die Genauigkeit von ints zu gross geworden ist?
Marion
>>Eigentlich müsste es korrekterweise>>>>const char* foo = "Text";> Wozu sollte das const nötig sein? Sicherlich ist es in den meisten> Fällen sinnvoll, aber uneigentlich ist "char* foo = "Text";" genauso> korrekt. Glaube ich.
In C++ ist 'char* foo = "Text";' definitiv nicht korrekt, weil
String-Literale nicht verändert werden dürfen. Es ist allerdings aus
Kompatibilitätsgründen möglich diese Zeile zu schreiben, allerdings darf
man das String-Literal "Text" eben niemals verändern, auch wenn foo auf
nicht-konstante Zeichen zeigt.
Will man den String verändern ist in C++ nur ein Array korrekt:
char foo[] = "Text";
In C könnte allerdings auch die Zeiger-Variante korrekt sein. Das hängt
davon ab, was der Standard dazu sagt (den ich leider nicht habe).
> Das hängt davon ab, was der Standard dazu sagt (den ich leider> nicht habe).
Seit der Einführung von const ist es eigentlich auch dort nicht
mehr korrekt. Aus den gleichen Gründen wie in C++.
Und ebenfalls aus den gleichen Gründen wie in C++ wird
das trotzdem akzeptiert: Rückwärtskompatibilität
zu bestehendem Code.
>>Eigentlich müsste es korrekterweise>>>>const char* foo = "Text";> Wozu sollte das const nötig sein?
Weil der Zeiger auf ein String-Literal zeigt, dass per
Definition konstant ist.
Du darfst es nicht verändern.
Machst su
char* foo = "Text;
foo[2] = 's';
hast du einen Fehler begangen, vor dem dich der Compiler nicht
bewahren kann.
Machst du
const* foo = "Text";
foo[2] = 's';
dann klopft dir der Compiler auf die Finger.
Das
char* foo = "Text";
überhaupt akzeptiert wird, hat den Grund, dass extra für
diesen Fall in den Standard eine Ausnahme eingebaut wurde.
Ansonsten hätte man praktisch jedes C-Programm auf dieser
Erde korrigieren müssen und diesen Aufwand wollte man den
Programmierern nicht zumuten.
'Moralisch' ist
char* foo = "Text";
nicht korrekt. Durch die spezielle Ausnahmeregelung (die
völlig gegen die sonstige const-Regelung läuft) wird aber
dieser eine spezielle Fall der char Pointer zugelassen,
auch wenn er eigentlich falsch ist.
Maria wrote:
> Ich weiss dass C++ und C nicht genau das selbe ist.
Nein: es sind zwei sehr verschiedene Dinge, die zufällig einen
ähnlichen Namen haben und sich manche Sachen in der Syntax teilen.
Du musst dich aber schon entscheiden, ob du lieber erstmal C oder
lieber erstmal C++ lernen willst. Es ist völlig richtig, dass sich
beides auf einem Universalrechner besser lernen lässt als auf einem
Controller mit seinen eher beschränkten Ressourcen und schlechteren
Debugmöglichkeiten.
C++ auf Controllern kann man auch machen, allerdings sollte man dann
bereits mit den Feinheiten der Sprache vertraut sein und ungefähr
wissen, welche Sprachkonstrukte sich größenordnungsmäßig in welchem
Code niederschlagen, ansonsten kann man hinsichtlich des
Ressourcenverbrauchs schnell sein blaues Wunder erleben.
> In C++ ist 'char* foo = "Text";' definitiv nicht korrekt, weil> String-Literale nicht verändert werden dürfen.
Es ist durchaus korrekt.
> Es ist allerdings aus Kompatibilitätsgründen möglich diese Zeile zu> schreiben, allerdings darf man das String-Literal "Text" eben niemals> verändern, auch wenn foo auf nicht-konstante Zeichen zeigt.
Genau. Das macht das obige aber nicht zu inkorrektem, sondern nur zu
unsauberem Code.
> In C könnte allerdings auch die Zeiger-Variante korrekt sein.
Stringliterale dürfen da genausowenig verändert werden, wie in C++.
[OT]
>Maria>Marion
Wieso wollen die "Weiber" eigentlich immer Sachen machen, die "Männern"
Spaß machen? Können die nicht lieber Kochen lernen? Und Kinder kriegen?
[/OT]
>> Gibt es sowas wie sNprintf, also eine sprintf-Funktion mit>> Angabe der maximalen Zeichenzahl?>>Ja gibt es.
Jetzt wo du es sagst...
Hätte einfach nach meinem Verdacht googeln müssen, wäre schneller
gegangen, als meine Frage hier zu stellen.