Forum: Compiler & IDEs pointer auf string funktioniert nicht


von feu (Gast)


Lesenswert?

Hallo,

ich komme nicht weiter. Ich will ein LCD Display ansteuern. Es soll 
einen string anzeigen. Die Länge wird richtig erkannt aber der Inhalt 
ist Blödsinn.

Ich rufe die routine im main.c so auf:
1
unsigned char CHAR[20];
2
  strcpy( CHAR, "HALLO" );
3
lcd_display_string(*CHAR);
Das unterprogramm geht so:
1
void lcd_display_string(char *STR)
2
{
3
  uint8_t i;
4
  unsigned char new_CHAR;  
5
  unsigned char u_CHAR;
6
  for (i=0;i<strlen(STR);i++)
7
  {
8
    new_CHAR = *(STR+1);
9
    if (new_CHAR)
10
    {
11
    u_CHAR = (unsigned char)new_CHAR;
12
    lcd_send_data(u_CHAR);
13
    }
14
  }
15
}
einzelne char mit lcd_send_data(u_CHAR); geht aber


kann mir jemand sagen was falsch ist

Vielen Dank im Voraus

Ralph

von Peter II (Gast)


Lesenswert?

man kann es aber auch kompliziert machen ...

Und variablen CHAR zu nennen, ist auch nicht gerade sinnvoll

unsigned char s[20];
  strcpy( s, "HALLO" );
lcd_display_string(s);

void lcd_display_string(char *s)
{
    while(*s) {
       lcd_send_data( *s );
       s++;
    }
}

von Dirk B. (dirkb2)


Lesenswert?

Durch den * beim *CHAR bekommst du nur das 'H'.
Was lcd_display_string aber als Adresse interpretiert.
Ergebnis ist Müll.

Sollte aber auch der Compiler anmeckern (als Warnung).

Für Zeichen nimmt man char.
Beim rechnen mit kleinen Integerbereichen nimmt man dann signed char 
oder unsigned char

von Ralph F. (feu)


Lesenswert?

Vielen Dank für eure schnelle Antwort und den bereinigten code.
Allerdings zeigt es immer noch nicht das an was es soll. Es kommt irgend 
ein komisches Zeichen, könnte fast arabisch sein. Es ist für "Hallo" 5 
mal genau das gleiche hintereinander. Nehme ich einen anderen String, 
kommt ein anderes Zeichen aber wieder mit der richtigen Anzahl der 
Stellen das Gleiche hintereinander. Es scheint als ob der pointer nicht 
weiter zählt und das ASCII Zeichen falsch interpretiert wird.
?????
Ich danke Euch schon mal

Ralph

von Peter III (Gast)


Lesenswert?

Wenn man
1
new_CHAR = *(STR+1);

statt
1
new_CHAR = *(STR+i);

schreibt, kann das auch nichts werden.

Wer lesen kann, ist klar im Vorteil.

von Vilex (Gast)


Lesenswert?

Peter II schrieb:
> while(*s) {
>        lcd_send_data( *s );
>        s++;
>     }
> }

Und was ist wenn jetzt das Array warum auch immer kein \0 enthält, z.B. 
weil das Array so befüllt wurde?
s[0] = 'H';
s[1] = 'A';
s[2] = 'L';
s[3] = 'L';
s[4] = 'O';

von Dirk B. (dirkb2)


Lesenswert?

Dann werden solange Zeichen ausgegeben, bis eine 0 auftaucht (oder bis 
zur Unendlichkeit und noch viel weiter).
Es kann auch einen Speicherzugriffsfehler geben, wenn das System das 
unterstützt.

Da die Zeichenfolge kein C-String ist, musst du die Länge auf andere 
Weise weiter geben.
Dann funktioniert strlen() aber auch nicht mehr.

von Kaj (Gast)


Lesenswert?

Vilex schrieb:
> Und was ist wenn jetzt das Array warum auch immer kein \0 enthält

Dirk B. schrieb:
> Dann werden solange Zeichen ausgegeben, bis eine 0 auftaucht (oder bis
> zur Unendlichkeit und noch viel weiter).
> Es kann auch einen Speicherzugriffsfehler geben, wenn das System das
> unterstützt.

Wer eine "Funktion" falsch benutzt, muss sich nicht wundern, wenn nicht 
das erwartete raus kommt...

Was ich sagen will:
feu schrieb:
> Es soll einen string anzeigen
Der TO redet von einem String, also muss der TO auch dafür sorgen das es 
ein String (im entferntesten sinne) ist, und mit einer '\0' 
abgeschlossen ist.

Vilex schrieb:
> z.B.
> weil das Array so befüllt wurde?
> s[0] = 'H';
> s[1] = 'A';
> s[2] = 'L';
> s[3] = 'L';
> s[4] = 'O';

Jedes Element des Arrays mit '\0' initialisieren und erst dann befüllen 
könnte helfen. Wenn man natürlich alle elemte belegt, also kein Platz 
mehr für ein '\0' ist, dann hat man was falsch gemacht, denn dann dürfte 
die Version mit
feu schrieb:
> strcpy( CHAR, "HALLO" );
auch nicht mehr funktionieren, weil kein '\0' ins Array geschrieben 
wird. Man sollte halt ganz grob wissen, was man da tut ;)

Grüße

von Karl H. (kbuchegg)


Lesenswert?

Vilex schrieb:
> Peter II schrieb:
>> while(*s) {
>>        lcd_send_data( *s );
>>        s++;
>>     }
>> }
>
> Und was ist wenn jetzt das Array warum auch immer kein \0 enthält

Dann  hat man auch keinen String im C-Sinne und sollte tunlichst keine 
String-Funktionen benutzen.

Man muss halt wissen was man tut. Ansonsten sollte man das Programmieren 
bleiben lassen und lieber im Sandkasten spielen.

von Kaj (Gast)


Lesenswert?

Karl Heinz schrieb:
> Man muss halt wissen was man tut. Ansonsten sollte man ... lieber im
> Sandkasten spielen.

Dann gehöre ich wohl (leider) dazu... Bei mir compiliert das nämlich nur 
bedingt. Ein konstrukt wie:

>     while(*s) {
>        ...
>        s++;
>     }

Compiliert bei mir nur:
- wenn sich das Konstrukt in einer Funktion (also nicht main()) befindet

oder

- Wenn sich das Kontrukt in der main() befindet, und ich einen Pointer 
nehme der auf s zeigt und ich den Pointer anstelle von s verwende.

sonst gibts: (s++) error: lvalue required as increment operand

Erklärung? :-/

Grüße

von Karl H. (kbuchegg)


Lesenswert?

Kaj schrieb:

> Compiliert bei mir nur:
> - wenn sich das Konstrukt in einer Funktion (also nicht main()) befindet

Ähm. Ist das jetzt ein Scherz?

Es ist eine der Grundregeln von C, dass sich ausführbarer Code immer in 
Funktionen befinden muss.

von Kaj (Gast)


Lesenswert?

Karl Heinz schrieb:
> Ähm. Ist das jetzt ein Scherz?
>
> Es ist eine der Grundregeln von C, dass sich ausführbarer Code immer in
> Funktionen befinden muss.
Ich meinte in einer anderen Funktion als der main()-Funktion.

von Kaj (Gast)


Lesenswert?

1
void foo(char *s)
2
{
3
  while(*s)
4
  {
5
    s++;  // <-- geht
6
  }
7
}
8
9
10
int main(void)
11
{
12
  char s[20];
13
  char x[20];
14
  strcpy( s, "HALLO" );
15
  strcpy( x, "HALLO" );
16
  foo(s);
17
18
  while(*x)
19
  {
20
    x++; // <-- geht nicht: lvalue required as increment operand
21
  }
22
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Kaj schrieb:
> x++; // <-- geht nicht: lvalue required as increment operand

Und? Was ist daran unklar? x ist hier kein Pointer. x ist ein Array.

von Dirk B. (dirkb2)


Lesenswert?

Karl Heinz schrieb:
> Man muss halt wissen was man tut. Ansonsten sollte man das Programmieren
> bleiben lassen und lieber im Sandkasten spielen.

Ein Array ist kein Pointer.
1
  char s[20];
2
  char *x = s;
3
  strcpy( s, "HALLO" );
4
  foo(s);
5
6
  while(*x)
7
  {
8
    x++;
9
  }

von Peter II (Gast)


Lesenswert?

Kaj schrieb:
> int main(void)
> {
>   char s[20];
>   char x[20];
>   strcpy( s, "HALLO" );
>   strcpy( x, "HALLO" );
>   foo(s);
>
>   while(*x)
>   {
>     x++; // <-- geht nicht: lvalue required as increment operand
>   }
> }

dann muss man es halt anders schreiben.
1
int main(void)
2
{
3
  char x[20];
4
  strcpy( x, "HALLO" );
5
 
6
  char *tmp = x;
7
  while(*tmp)
8
  {
9
    tmp++; 
10
  }
11
}

von Kaj (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> x ist hier kein Pointer. x ist ein Array.
x ist "nur" eine Adresse, die Startadresse des Arrays! Und genau 
deswegen leuchtet mir das auch nicht ein! Nach deiner aussage dürfte 
dann
1
*(x+1)
dann auch nicht funktionieren.

von Kaj (Gast)


Lesenswert?

Dirk B. schrieb:
> Ein Array ist kein Pointer.

Rufus Τ. Firefly schrieb:
> Und? Was ist daran unklar? x ist hier kein Pointer. x ist ein Array.

Sagt doch einfach, das es nicht geht, weil ich die Startadresse des 
Arrays nicht verändern darf?! (vermute ich jetzt einfach mal)

von lokale Variable (Gast)


Lesenswert?

Kaj schrieb:
> void foo(char *s)
> {
>   while(*s)
>   {
>     s++;  // <-- geht
>   }
> }

Innerhalb der Funktion foo gilt das lokale s. Und das ist als char *s - 
also pointer - deklariert. Nenn das einfach um in t und du erkennst den 
Unterschied:
1
void foo(char *t)
2
{
3
  while(*t)
4
  {
5
    t++;  // <-- geht
6
  }
7
}

von spontan (Gast)


Lesenswert?

>(vermute ich jetzt einfach mal)

@Kaj:  Da liegt Dein grundsätzlicher Fehler. Vermuten hat in der 
Programmierung nichts zu suchen. Da gibt es klare Regeln. Die gilt es zu 
lernen, zu verstehen und anzuwenden.

von B. S. (bestucki)


Lesenswert?

Kaj schrieb:
> Nach deiner aussage dürfte
> dann*(x+1)
> dann auch nicht funktionieren.

Das ist das selbe wie
1
x[1]

Hier wird der Unterschied zwischen Arrays und Zeiger erklärt:
http://openbook.galileocomputing.de/c_von_a_bis_z/012_c_zeiger_007.htm

von Dirk B. (dirkb2)


Lesenswert?

Bei *(x+1) wird x ja nicht verändert. Ich meine die Adresse und nicht 
den Inhalt.

von lokale Variable (Gast)


Lesenswert?

Macht es doch nicht so kompliziert. Er nicht gemerkt, dass er über den 
Funktionsparameter einen cast ausgeführt hat.
(char *) s // wobei s als char s[123] deklariert wurde

That 's all!

von Ralph F. (feu)


Lesenswert?

muss nochmal fragen ...
warum geht das:
char s[20];

s[0]="h";
s[1]="a";
s[2]="l";
s[3]="l";
s[4]="o";
s[5]=0x00;
lcd_display_string(s);

und das nicht:

char s[20];
  strcpy( s, "hallo\0");
lcd_display_string(s);

beim zweiten kommt Müll raus, auch wenn ich das ganze array mit 0x00 
voll schreibe

Danke schon mal

von Peter II (Gast)


Lesenswert?

Ralph Feuchter schrieb:
> und das nicht:
>
> char s[20];
>   strcpy( s, "hallo\0");
> lcd_display_string(s);
>
> beim zweiten kommt Müll raus, auch wenn ich das ganze array mit 0x00
> voll schreibe

ich sehen keine Fehler, sicher das es nicht funktioniert? die \0 ist 
Hallo ist nicht notwendig, stört aber auch nicht.

von Ralph F. (feu)


Lesenswert?

ich würde es ja gerne zeigen, ist aber tatsächlich so

vielleicht stimmt was mit der strcpy() funktion nicht

von nicht original (Gast)


Lesenswert?

Peter II schrieb:
> ich sehen keine Fehler

Das ist auch nicht der originale Code. Er hat bestimmt wieder das * 
benutzt.

Den Wald vor lauter Bäumen nicht sehen passiert jedem einmal. ;-)

von Dirk B. (dirkb2)


Lesenswert?

Ralph Feuchter schrieb:
> char s[20];
>
> s[0]="h";

Schon der Code muss Fehler, aber zumindest Warnungen liefern.

Du willst einer char-Variablen eine Adresse zuweisen.
"h" ist etwas anderes als 'h'

Daher kann das nicht funktionieren.

von klausr (Gast)


Lesenswert?

Ralph Feuchter schrieb:
> muss nochmal fragen ...
> warum geht das:

Hm... arbeitest du mit einem PC oder Mikrocontrollern? Evtl. liegen 
Strings
in einem besonderen Speicher (z.B. früherer avr-gcc). 
Harvard-Architektur?

von Ralph F. (feu)


Lesenswert?

das ist er schon mittlerweile, der code, meine ich
ich sehs wirklich nicht

char s[20]="";
/*
s[0]="h";
s[1]="a";
s[2]="l";
s[3]="l";
s[4]="o";
s[5]=0x00;
int i;
*/
strcpy( s,"hallo\0");
lcd_display_string(s);
-----------------------------------------
void lcd_display_string(char *s)
{

    while(*s)
    {
       lcd_send_data( *s);
       s++;
    }
}

wenn ich es direkt zuweise gehts, wenn ich den string kopiere gehts 
nicht, aber trotzdem müsste doch in dem Array das Gleiche drin stehen

von Dirk B. (dirkb2)


Lesenswert?

Nochmal:
Der bei dir auskommentierte Teil kann so nicht funktionieren.

"h" ist ein Stringliteral. Du willst aber das Zeichen 'h'.

von Ralph F. (feu)


Lesenswert?

klausr schrieb:

> Hm... arbeitest du mit einem PC oder Mikrocontrollern? Evtl. liegen
> Strings

nein,  neines soll auf einem Atmega16 laufen. Programmiert wir auf einem 
linux PC mit AVR-gcc-Toolchain

s[] geht
u[] ist ganz genau der selbe Misst wie t[] , jedoch die Zeichenzahl 
stimmt

char s[20]="";
char t[20]="";
char u[10]="";

s[0]="h";
s[1]="a";
s[2]="l";
s[3]="l";
s[4]="o";
s[5]=0x00;

u[0]='h';
u[1]='a';
u[2]='l';
u[3]='l';
u[4]='o';
u[5]=0x00;


strcpy( t,"hallo");
lcd_display_string(s);
//lcd_display_string(t);
//lcd_display_string(u);

von Dirk B. (dirkb2)


Lesenswert?

Bist du dir sicher, das du C (oder C++) programmierst?

Was kommt bei
1
lcd_display_string("Hallo!");
 raus?

von fibonacci de gogolores (Gast)


Lesenswert?

Dirk B. schrieb:
> Der bei dir auskommentierte Teil kann so nicht funktionieren.
>
> "h" ist ein Stringliteral. Du willst aber das Zeichen 'h'.

Das ist mir auch ein Rätsel wie der Teil überhaupt funktionieren soll 
wenn du "h" statt 'h' schreibst.
Bist du sicher dass nicht der untere Teil derjenige ist der eigentlich 
funktioniert?

von maik (Gast)


Lesenswert?

alle c-strings sind 0 terminiert!

"Hallo" ist 0 terminiert.


strcpy kopiert bis zur 0 aber nicht die 0.
1
extern char *
2
strcpy (char *s, const char *ct)
3
{
4
    char *temp = s;
5
6
    while ((*s++ = *ct++) != '\0');
7
    return temp;
8
}

von Peter II (Gast)


Lesenswert?

maik schrieb:
> strcpy kopiert bis zur 0 aber nicht die 0.

klar macht es das. bzw. es fügt an das ziel hinten eine 0 an. Sonst 
würde ja im Ziel keine 0 am ende stehen und damit währe es keine 
sinnvolle Stringfunktion.

von maik (Gast)


Lesenswert?

stimmt sorry steht ja eh so im code:)

von ok (Gast)


Lesenswert?

1
#include <string.h>
2
3
4
void print_it(char *str)
5
{
6
7
  while( str)
8
  {
9
    
10
    putchar( *str );
11
    str++;
12
    
13
  }
14
}
15
16
17
void main( void )
18
{
19
20
  char txt[20];
21
  strcpy( txt, "HALLO" );
22
  print_it (txt);
23
  
24
}
läuft so!

von Dirk B. (dirkb2)


Lesenswert?

ok schrieb:
> while( str)

Hast du das so selber ausprobiert?

von Stefan E. (sternst)


Lesenswert?

Ralph Feuchter schrieb:
> wenn ich es direkt zuweise gehts, wenn ich den string kopiere gehts
> nicht, aber trotzdem müsste doch in dem Array das Gleiche drin stehen

Du hast vermutlich ein grundlegendes Problem in deinem Build-Prozess. 
Ich tippe darauf, dass du die .data-Section nicht in das HEX-File 
exportierst.

von Ralph F. (feu)


Lesenswert?

Habs raus gefunden woran es lag, an mir natürlich

nicht original schrieb:
> Das ist auch nicht der originale Code. Er hat bestimmt wieder das *
> benutzt.

das wars zwar nicht ganz, aber so ähnlich
im Unterprogramm wo das Byte in seine nibble zerlegt wird sollte die 
adresse übergeben werden und ich hatte das & vergessen.

Vielen Dank an alle, .. habe prima dazugelernt

sorry nochmal

Ralph

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.