Forum: Compiler & IDEs Array Zuweisung


von Peter.h (Gast)


Lesenswert?

Hallo,
warum geht:
char zeichen[4] ={'A','B','C','D'};
lcd_print(0,0,"%s",zeichen[2]);

nicht?
Aber:
char zeichen[5];
zeichen[0]='A';
zeichen[1]='B';
zeichen[2]='C';
zeichen[3]='D';
lcd_print(0,0,"%s",zeichen[2]);


funktioniert einwandfrei? Ich sehe da keinen Fehler?
(Atmega32,AVRGCC,LCD Ansteuerung von Ulrich Radig))
Danke
Peter

von Ralf (Gast)


Lesenswert?

Stichwort: Null-terminierter String

von 2ter Gast (Gast)


Lesenswert?

Was geht nicht? Ist vielleicht bei dem einem Beispiel zufälligerweise 
eine Nullterminierung der Zeichenkette vorhanden und bei dem anderen 
Beispiel nicht ?

von Guru (Gast)


Lesenswert?

Was heisst "geht nicht"?

von Guru (Gast)


Lesenswert?

Mist. Jetzt sehe ich es erst. %s
Nullterminierung ist im zweiten Fall wohl durch das vom Compiler 
implizit auf Null initialisierte Zeichen gegeben. Im ersten Fall werden 
vermutlich eine Weile lang irgendwelche Bytes folgen, die nicht Null 
sind.

Aber was heisst "geht nicht"? Gewöhne Dir bitte aussagekräftige 
Fehlerbeschreibungen an.

von Peter.h (Gast)


Lesenswert?

Also ich bekomme bei dem oberen Beispiel keine Ausgabe am LCD,
und bei dem unteren bekomme ich genau das Zeichen, was ich ich angebe.
In dem Beispiel bekomme ich ein C auf dem LCD ausgegeben.
Peter

von Guru (Gast)


Lesenswert?

@ Peter

Aha. Und? Hast Du das mit der Null-Terminierung mal probiert?

von Rolf Magnus (Gast)


Lesenswert?

Peter.h schrieb:
> allo,
> warum geht:
> char zeichen[4] ={'A','B','C','D'};
> lcd_print(0,0,"%s",zeichen[2]);
>
> nicht?
> Aber:
> char zeichen[5];
> zeichen[0]='A';
> zeichen[1]='B';
> zeichen[2]='C';
> zeichen[3]='D';
> lcd_print(0,0,"%s",zeichen[2]);
>
>
> funktioniert einwandfrei? Ich sehe da keinen Fehler?
> (Atmega32,AVRGCC,LCD Ansteuerung von Ulrich Radig))

Peter.h schrieb:
> Also ich bekomme bei dem oberen Beispiel keine Ausgabe am LCD,
> und bei dem unteren bekomme ich genau das Zeichen, was ich ich angebe.
> In dem Beispiel bekomme ich ein C auf dem LCD ausgegeben.

Sicher daß das der Code ist, den du tatsächlich hast laufen lassen und 
nicht irgendwas, das du für das Posting hier neu getippt hast?

von Ralf (Gast)


Lesenswert?

Dem "%s" nach zu urteilen, müsste der (letzte) Parameter ein Zeiger auf 
eine Null-terminierte Zeichenkette sein. Beide Male wird nur ein 
einzelnes Zeichen übergeben. Dürfte eigentlich beides nicht 
funktionieren??

von Guru (Gast)


Lesenswert?

Und was heisst: "...bekomme ich genau das Zeichen, was ich ich angebe.
In dem Beispiel bekomme ich ein C auf dem LCD ausgegeben."

Du müsstest eigentlich auch das 'D' ausgegeben sehen.

Wenn ich das so überdenke, fehlt mir bei Dir das sichtbare Eigenbemühen 
um eine Lösung. Was hast Du bisher herausgefunden. Welche 
Voraussetzungen sind gegeben? Wo genau hakt es? Was hast Du für eine 
Vermutung?

von Peter.h (Gast)


Lesenswert?

Danke für Eure Antworten!
Es müßte also so:
char zeichen[5] ={'A','B','C','D','\0'};
lcd_print(0,0,"%s",zeichen[2]);
gehen????
Ich sitze gerade nicht an der Schaltung.
Peter

von Guru (Gast)


Lesenswert?

Ralf schrieb:

>Beide Male wird nur ein einzelnes Zeichen übergeben.

Meine Güte. Richtig. Was ist das für ein Sch... Muss wohl daran liegen, 
das ich heute meine Assembler-Brille aufhabe.

Na ich halte mich raus. Sorry.

von Guru (Gast)


Lesenswert?

>Es müßte also so:
>char zeichen[5] ={'A','B','C','D','\0'};
>lcd_print(0,0,"%s",zeichen[2]);
>gehen????

Nein. Eben nicht. %s erwartet einen Zeiger auf einen String und kein 
Zeichen. Mit "zeichen[2]" übergibst Du aber ein Zeichen.

von 2ter Gast (Gast)


Lesenswert?

Guru schrieb:
> Mit "zeichen[2]" übergibst Du aber ein Zeichen.

Ja stimmt,
1
lcd_print(0,0,"%s",&zeichen[2]);

wäre schon mal ein Fortschritt.

von Guru (Gast)


Lesenswert?

>wäre schon mal ein Fortschritt.

... den ich ihn hätte gerne aus eigener Kraft und Erkenntnis heraus 
hätte machen lassen wollen.

von 2ter Gast (Gast)


Lesenswert?

Ah na ja vielleicht nächstemal vorwarnen, dass man nicht sofort die 
Lösung posten sollte...

von Guru (Gast)


Lesenswert?

Naja. Im schlimmsten Fall lernt er nichts daraus und fragt beim nächsten 
analogen Fall wieder das selbe.

von Peter.h (Gast)


Lesenswert?

@2ter Gast,
danke! Ich wäre aber auch nicht so schnell auf die Lösung gekommen. Ich 
hätte noch einige Zeit gesucht, bis ich mir die LCD.C mal angesehen 
hätte!
Wenn überhaupt, da es ja dummerweise mit dem zweiten Besipiel ging.
Peter

von Guru (Gast)


Lesenswert?

Siehst Du, 2ter Gast, was ich meine?

von 2ter Gast (Gast)


Lesenswert?

Tja, ich sehe es. Bin halt optimist und hoffe, dass er es das nächste 
mal besser macht. Wie auch immer

== ENDE ==

von Guru (Gast)


Lesenswert?

"== ENDE ==" ? Ja, ich seh' schon. Du bist ein Optimist. ;-)

von Michael B. (mb_)


Lesenswert?

2ter Gast schrieb:
> Guru schrieb:
>> Mit "zeichen[2]" übergibst Du aber ein Zeichen.
>
> Ja stimmt,
>
>
1
> lcd_print(0,0,"%s",&zeichen[2]);
2
>
>
> wäre schon mal ein Fortschritt.

So und jetzt nochmal überlegen warum das auch falsch ist.

Stichwort: %c

von Guru (Gast)


Lesenswert?

Naja. Insgesamt ein etwas unglücklich eröffneter und verlaufener Thread.

Der TO hat nicht geschrieben, was er eigentlich erreichen will. Einen 
String ausgeben oder ein Zeichen. Das %s lässt auf einen String 
schliessen. Der Satz: "...bekomme ich genau das Zeichen, was ich ich 
angebe." ist nicht eindeutig, weil er sowohl bedeuten kann, das er das 
Zeichen bekommt, das er als Teil eines Strings erwartet oder eben nur 
das Einzelzeichen.

Die ganze Konstruktion deutet auf Einzelzeichen, aber dem widerspricht 
wieder die Verwendung eines Arrays, da mit 'c' etc. das selbe zu 
erreichen wäre. Also bleibt auch die Möglichkeit, das das Array nur ein 
Beispiel ist, aber wofür? Für einen String oder für Einzelzeichen?

Demnach ist es fraglich ob die Nullterminierung und der fehlende 
&-Operator das Problem ist, damit der String richtig ausgegeben wird 
oder der Ersatz von %s durch %c, damit das Zeichen richtig ausgegeben 
wird.

Das das %s grundsätzlich falsch ist, ist also garnicht festzustellen.

von Peter (Gast)


Lesenswert?

Hallo,
ich wollte noch einmal schreiben, bevor mir wieder vorgeworfen wird, 
dass ich nichts lernen will oder etwas vorgekaut bekommen will.
Ich wollte nur aus dem Array zeichen das jeweillige Zeichen, was im 
Index bei  lcd_print(0,0,"%s",&zeichen[2]); angegeben ist, auf dem LCD 
ausgeben. Kein String. Mit der lcd_print(0,0,"%s",&zeichen[2]); Lösung 
geht es jetzt, und ich weiß auch was ich falsch gemacht habe. Ich bin 
nur nicht drauf gekommen warum es bei meinem ersten Besipiel nicht geht 
und im zweiten plötzlich doch.
Bitte nicht falsch verstehen. Ich lerne noch:-)
Peter

P.S. Wäre dann %s auch falsch? Bei %c geht es nicht?!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Statt

   lcd_print(0, 0, "%s", &zeichen[2]);

solltest Du schreiben

   lcd_print(0, 0, "%c", zeichen[2]);


Ersteres erwartet durch "%s" einen Pointer auf einen String, übergeben 
wird die Adresse des dritten Zeichens im Array, ausgegeben wird das 
dritte Zeichen im Array ... und alle anderen, die darauf folgen, bis 
zur nächsten \0.

Die richtige Variante (wobei das mit dem "richtig" so eine Sache ist, 
aber dazu später) erwartet durch "%c" ein einzelnes Zeichen, und genau 
das wird hier übergeben.

"richtig" ist diese Variante zwar, aber sehr ineffizient. Um ein 
einzelnes Zeichen auszugeben, ist der Gebrauch einer auf (s)printf 
aufbauenden Routine ziemlicher Overkill. Für Dein LC-Display solltest Du 
auch eine Routine haben, die lcd_putc oder so ähnlich heißt, und die 
enthält den ganzen Formatstring-Wasserkopf nicht.

von Ralf (Gast)


Lesenswert?

Peter schrieb:
> Mit der lcd_print(0,0,"%s",&zeichen[2]); Lösung
> geht es jetzt, und ich weiß auch was ich falsch gemacht habe.

Und was war falsch?

Ein Zeichen ausgeben, geht bei beiden Varianten nicht:

Peter.h schrieb:
> char zeichen[4] ={'A','B','C','D'};

-> "CD" und dann Müll

Peter.h schrieb:
> char zeichen[5];
> zeichen[0]='A';
> zeichen[1]='B';
> zeichen[2]='C';
> zeichen[3]='D';

-> "CD"
1
char z[]={'D','\0'};
2
lcd_print(0,0,"%s",z);
geht zwar, aber:

Rufus Τ. Firefly schrieb:
> Um ein
> einzelnes Zeichen auszugeben, ist der Gebrauch einer auf (s)printf
> aufbauenden Routine ziemlicher Overkill.

von Guru (Gast)


Lesenswert?

Das Problem ist folgendes:

Bei
1
lcd_print(0, 0, "%s", &zeichen[2]);

kann es sein, das Du, wie erwartet das erste Zeichen der Kette, am 
Index 2 angezeigt bekommst.

Korrekt ist diese Lösung dennoch nicht. Denn es ist nicht allein 
maßgebend ob etwas funktioniert in dem Sinne, das es das macht, was Du 
willst. Es spielt auch eine Rolle ob gewisse formale Regeln eingehalten 
werden. Erst dann ist sichergestellt, das es auch zuverlässig richtig 
geht. Etwa nach Codeänderungen, Einfügungen oder Entfernung von 
Variablen etc. Ohne die Einhaltung der formalen Kriterien ist es nur 
Zufall das es scheinbar funktioniert.

Du schreibst:
>bevor mir wieder vorgeworfen wird, dass ich nichts lernen will oder etwas 
>vorgekaut bekommen will.

Bitte sei nicht beleidigt.
Es geht darum, das es sich hier um Grundkenntnisse handelt, die Du in 
einem C-Buch nachlesen kannst. Es geht darum, das Du Fehler so 
beschreibst, das klar erkennbar ist, was Du erreichen willst und was 
eigentlich das Problem ist. Das hat hier nämlich zu Verwirrung geführt. 
Nimmt man das %s als gegeben, dann hat die Verwendung des 
Adressoperators und die Nullterminierung gefehlt. Nimmt man aber an, das 
Du tatsächlich nur ein Einzelzeichen ausgeben wolltest, dann war %c 
anstelle von %s richtig.
Nach meinem Post hier: 
Beitrag "Re: Array Zuweisung" wäre die natürliche 
Reaktion, die ich auch provozieren wollte, das Du Dich fragst: Was 
bedeutet denn %s und %c? Was ist in diesem Zusammenhang nochmal der 
Unterschied und der Zusammenhang zwischen Arrays, Zeigern und 
Indizierung von Arrays? Dabei wärst Du dann auch auf den Adressoperator 
gestossen.

Ich hätte nun alle diese Eventualitäten berücksichtigen können 
(abgesehen davon, das ich mich beim ersten lesen auch verguckt habe). 
Aber das hätte Dir den Eindruck vermittelt, das Du hier Leute findest, 
die kurz gesagt, Deine Defizite an Grundlagenwissen ausgleichen. Da das 
aber wiederrum dazu führt, das man sich dann diese Grundlagen immer noch 
nicht aneignet und also gezwungen ist, bei einem ähnlichen Fall wieder 
die selbe Frage zu stellen, wollte ich Dir nicht einfach die Antwort 
vorgeben bzw. die Möglichkeiten aufschlüsseln.

Deine Reaktion auf die Antwort von 2ter Gast hat meine Vermutung auch 
genau bestätigt. Du hattest immer noch eine widersprüchliche Lösung 
(weil die Terminierung des Strings immer noch eine implizite war) und es 
war nicht erkennbar welches Problem Du erkannt hast. Stattdessen hast Du 
angenommen das die Lösung korrekt ist weil es "funktioniert" aber ohne 
zu berücksichtigen das es eben, wie oben erwähnt auch notwendig ist, 
formale Korrektheit zu erreichen. Das aber wäre genau das gewesen, was 
Du erkannt hättest, wenn Du, wie von mir beabsichtigt nochmal die Texte 
über das Thema gelesen hättest.

Das Ganze wäre also nicht so passiert, um das Thema nun sinnvoll 
abzuschliessen, wenn Du
1. Genau schreibst was Du erreichen willst und wie.
2. Genau schreibst was tatsächlich passiert (anstelle von "funktioniert 
nicht").

Also, nichts für ungut und viel Erfolg.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.