Forum: Mikrocontroller und Digitale Elektronik strcat Problem Nullbyte


von ferdl (Gast)


Lesenswert?

Hallo

Habe ein Problem mit der Stringfunktion "strcat" die 2 Strings 
zusammenfügt.

Der "Text der kein Nullbyte am Schluss hat" kommt aus einem EEPROM.

char Text[100];
strcpy(Text,"Text der kein Nullbyte am Schluss hat");
strcat(Text,"Text der kein Nullbyte am Schluss hat");

Funktion 1 fügt den String in das Array Text ein
Funktion 2 hängt einen String an das Array Text an.

Wenn ich den Gesamten String über den Uart ausgeben will, brauche ich 
jedoch ein Nullbyte am Schluss.
Wie fügt man das an?

mit: strcat(Text, '\0'); hats nicht funktioniert.

von Matthias L. (Gast)


Lesenswert?

>char Text[100]

Das ist ja noch kein Text. Das ist ne Textvaraible, in der (noch) kein 
Text steht.

Durch das zuweisen entsteht automatisch ein Nullbyte. Das macht der 
Compiler. Du musst allerdings die richtigen Hochstriche nehmen:

char Text[100] = 'Text MIT Nullbyte....!';



PS:
>strcat(Text,"Text der kein Nullbyte am Schluss hat");

Wird wohl nicht gehen, da strcat zwei Zeiger (auf char) erwartet.

von Sven P. (Gast)


Lesenswert?

Matthias Lipinsky wrote:
> char Text[100] = 'Text MIT Nullbyte....!';
So ist es falsch.

>PS:
>>strcat(Text,"Text der kein Nullbyte am Schluss hat");
>
>Wird wohl nicht gehen, da strcat zwei Zeiger (auf char) erwartet.
Wird gehen, da "..." zu einem Zeiger wird.

Eine Zeichenkette, die mit "..." angegeben wurde, endet immer mit einem 
Nullbyte. strcat und strcpy funktionieren auch nur, solange die Sache 
mit einem Nullbyte beendigt ist. Beide Funktionen fügen auch wieder ein 
abschließendes Nullbyte an den Ergebnisstring.

Wichtig wäre bei dir: Den Vektor (Text[100]) vorher mit einem einzelnen 
Nullbyte initialisieren (Text[0] = '\0';).

Du kannst dir strcat so vorstellen:
- suche im String 1 nach einem Nullbyte
- überschreibe dieses mit dem ersten Byte von String 2
- war dieses Byte von String 2 kein Nullbyte, gehe zum vorigen 
Schritt...
D.h., das Nullbyte des zweiten Strings wird implizit mitkopiert.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

strcat(Text, "irgendwas") hängt das Nullbyte an. Wenn es das nicht tut, 
ist dieses strcat buggy oder der Puffer ist zu klein (Pufferüberlauf).
http://www.openbsd.org/cgi-bin/man.cgi?query=strcat

> Wenn ich den Gesamten String über den Uart ausgeben will, brauche ich
> jedoch ein Nullbyte am Schluss.

Wie meinst du das? Erwartest du, dass das Nullbyte gesendet wird (macht 
eine ordentliche Stringsendefunktion nicht) oder wird eins 
fälschlicherweise gesendet (Stringsendefunktion buggy) oder wird das 
Nullbyte nicht beachtet (Pufferüberlauf)?

von ferdl (Gast)


Lesenswert?

Naja, strcat ansich funktioniert bei mir schon, jedoch fehlt mir das 
Nullbyte für ein "put_string" über den UART

"Text" ist ja eigentlich ein Pointer auf die Adresse &Text[0]
"Text der kein Nullbyte am Schluss hat" ist bei mir auch ein Pointer.

...deswegen funktioniert strcat

"Text der kein Nullbyte am Schluss hat" ist eigentlich kein echter 
String sondern eine Stringvariable die zwar Char Zeichen enthält, jedoch 
kein Nullbyte.

Um die Frage konkreter zu formulieren hier mein genaues Problem:
3 Textzeilen werden aus einem EEProm gelesen bis zum Zeichen '*'. Das 
EEprom ist standartmäßig mit "$" Zeichen befüllt.

Page5: Testtextssssssssssssssssssssssssssssssssssssssssssssssssssssss*$
Page6: ssssssssssssssssssssssssssssx*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Page7: *$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

Wie man sieht steht in Page 5 & 6 der Nutztext den ich haben will. Page 
7 ist leer.

Hier nun ein Programmausschnitt der den Text aus den Pages holt:
1
  for(int i=5; i<=7; i++)
2
  {
3
     read_page((EEPROM_Pagesize*i), &page[0]); //unwichtig  
4
                  //(holt alle Zeichen einer Page in das Feld page mit der
5
                  //übergebenen Adresse &page[0]) 
6
        
7
  if (i==5) 
8
   { strcpy(Text,strtok_r(page,"*",&str_tok)); //Text aus Page5
9
   }
10
   else
11
   { strcat(Text,strtok_r(page,"*",&str_tok)); //Page 6&7
12
   }
13
  }

Alle Teiltexte die mit * aufhören werden in Text zusammengefügt. Jetzt 
muss aber noch ein Nullbyte angehängt werden.

von ferdl (Gast)


Lesenswert?

@stefan
Eine String Sendefunktion sendet so lange bis sie das Nullbyte ließt. 
Deswegen brauche ich eines.

von ferdl (Gast)


Lesenswert?

Habe soeben festgestellt, dass

uart1_puts(strtok_r(page,"*",&str_tok));

Also ein String bis zum '*' über den Uart ausgeben, bei Page 5 und 6 
richtig ist, jedoch bei Page 7 nur Mist ausgibt.

Testtextssssssssssssssssssssssssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssx
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ MBý

Nach dem MBý wird wahrscheinlich irgendwo mal ein Nullbyte auftauchen...

Kann jemand einen Fehler erkennen?

von hihi (Gast)


Lesenswert?

> Um die Frage konkreter zu formulieren hier mein genaues Problem:
> 3 Textzeilen werden aus einem EEProm gelesen bis zum Zeichen '*'. Das
> EEprom ist standartmäßig mit "$" Zeichen befüllt.

Einfach:

Füll das EEprom halt standar_d_mässig mit 0x00.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich schätze, das macht die Probleme:

> Page7: *$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

Du wirst von strtok_r() ganz korrekt einen Zeiger auf das erste '$' 
bekommen, den du so nicht erwartest.

Denn eine der ersten Aktionen von strtok_r nach dem Check auf 
Nullpointer ist:
1
.L_del_lead_init:      ; Remove leading delimiters
2
  X_movw  XL, str_lo

Bzw. hier in Worten:
http://opengroup.org/onlinepubs/007908775/xsh/strtok.html

"The first call in the sequence searches the string pointed to by s1 for 
the first byte that is not contained in the current separator string 
pointed to by s2. If no such byte is found, then there are no tokens in 
the string pointed to by s1 and strtok() returns a null pointer. If such 
a byte is found, it is the start of the first token."

Alternative:

Such das '*' in page mit strchr() und setze an die Stelle ein '\0'. 
Dann kopiere page nach Text (strcpy) oder hänge page an Text an 
(strcat).

von ferdl (Gast)


Lesenswert?

Probiere jetzt das EEprom mit 0x00 statt '$' zu füllen und als 
Stringendezeichen ebenfalls 0x00 zuverwenden.

Weiß jemand zufällig wie man VB6 (Visual Basic6) mitteilt, dass es 0x00 
mit der MSCOMM einheit versenden soll?

MSComm1.Output = Combobox.ListIndex & Chr(0) & Textbox.text & Chr(0)

Chr(0) soll angeblich ein ASCII aus dezimal 0 machen.

von ferdl (Gast)


Lesenswert?

*(strchr(page, '*'))='\0';
strcpy(Text,page);

hats gebracht, danke!

von Mark M. (mom-jovi)


Lesenswert?

Ich habe ein ganz ungewöhnliches Problem:
1
char pfad[1024];
2
char datei[1024];
3
FILE* stream;
4
5
fgets(pfad,sizeof(pfad),stdin); // Pfad eingeben:  pfad=="C:\\meinPfad"
6
fflush(stdin);
7
fgets(datei,sizeof(datei),stdin); // Dateinamen eingeben:  datei=="text.txt"
8
fflush(stdin);
9
10
strcat(pfad,datei);
11
stream=fopen(pfad,"r");

Diese letzte Zeile wird nicht ausgeführt, da schon davor bei strcat ein 
falscher String entsteht.
Mein Debugger (GNU GCC Compiler) sagt, dass pfad nach strcat so 
aussieht:
1
pfad=="C:\\meinPfad\ntext.txt\n"
d.h. dass er den ersten Nullterminator nicht überschrieben hat.

Ok, ich merke gerade, dass man nach "meinPfad" auch noch "\\" einfügen 
müsste. Aber trotzdem hab ich noch das andere Problem.

von Schorsch (Gast)


Lesenswert?

Warum hast du einen thematisch nicht wirklich passenden, über 1 Jahr 
alten Thread dafür aus der Tonne gekramt?


Zu deinem Problem:
fgets liest die ganze eingegebene Zeile, INCLUSIVE dem "Enter" am 
Zeilenende.

Das musst du wieder rauslöschen.

von Huch (Gast)


Lesenswert?

>pfad=="C:\\meinPfad\ntext.txt\n"

>d.h. dass er den ersten Nullterminator nicht überschrieben hat.

So? Woraus genau schliesst Du das?

von Klaus W. (mfgkw)


Lesenswert?

Sicherheitshalber: \n ist NICHT ein Nullbyte.

von Mark M. (mom-jovi)


Lesenswert?

Klaus Wachtler schrieb:
> Sicherheitshalber: \n ist NICHT ein Nullbyte.

Ups, sorry. Ich meine natürlich das Nullbyte '\0' . Habe das vor lauter 
Zeilenumbrüchen falsch gemacht. Im Programm steht natürlich \0.

>Warum hast du einen thematisch nicht wirklich passenden, über 1 Jahr
>alten Thread dafür aus der Tonne gekramt?

Es ist doch in allen Foren dasselbe! Hätte ich nen neuen Thread 
aufgemacht, dann hättet ihr mich auf die Suche hingewiesen. So hab ich 
eben den passendsten schon vorhandenen Thread genommen, der gleich 3 
Stichworte (und nicht viel anderes) für mein Anliegen beinhaltet:
- strcat
- Problem
- Nullbyte

von Karl H. (kbuchegg)


Lesenswert?

Mark M. schrieb:

> Es ist doch in allen Foren dasselbe! Hätte ich nen neuen Thread
> aufgemacht, dann hättet ihr mich auf die Suche hingewiesen.

Das kann dir auch so passieren, wenn es in deiner Frage eigentlich schon 
gar nicht mehr um das Threadthema geht.

> So hab ich
> eben den passendsten schon vorhandenen Thread genommen, der gleich *3*
> Stichworte (und nicht viel anderes) für mein Anliegen beinhaltet:
> - strcat
> - Problem
> - Nullbyte

Und, was bringts?
Du musst dein Problem sowieso neu erklären, weil es eben nicht identisch 
zum Urthreadthema ist. Da kannst du auch gleich einen neuen aufmachen.

Und auf die Suche wird meistens nur dann verwiesen, wenn es sich 
wirklich um ein Dauerthema handelt. Gerade in der Programmierung sind 
die meisten Fragen aber nicht von dieser Art, sondern jeder Fall ist je 
nach den Details anders.
Das wissen auch die Antworter.

von Huch (Gast)


Lesenswert?

>Es ist doch in allen Foren dasselbe! Hätte ich nen neuen Thread
>aufgemacht, dann hättet ihr mich auf die Suche hingewiesen.

Das ist möglicherweise ein Missverständnis. Ma weist Dich nicht deswegen 
darauf hin, damit Du Deine Frage an einen der gefundenen Threads 
anhängst, sondern für den Fall, das die Frage schon beantwortet worden 
ist.

>Ich meine natürlich das Nullbyte '\0' .
Womit meintest Du das?

>Im Programm steht natürlich \0.
In welchem Programm? Ich sehe weder ein \n noch ein \0 in Deinem 
Programm.
Du hast von gdb ein \n in einem String  angezeigt bekommen.

Die Frage war:

>pfad=="C:\\meinPfad\ntext.txt\n"

>d.h. dass er den ersten Nullterminator nicht überschrieben hat.

So? Woraus genau schliesst Du das?

Denn in Deinem String ist garnicht erkennbar, das von den darüber 
stehenden Codeschnipsel irgendwo ein Nullterminator nicht überschrieben 
wurde.

Es ist jetzt natürlich nicht so einfach, aber bitte bemühe Dich mehr 
Dein Problem klar und eindeutig zu beschreiben. Dazu gehört das Du nicht 
nur Deine Schlüsse präsentierst sondern auch wie Du zu ihnen gelangst.

von Schorsch (Gast)


Lesenswert?

Mark M. schrieb:
> Im Programm steht natürlich \0.

WO steht das in dem Programm?

In C-Strings macht "\0" keinen Sinn, da das den String vorzeitig beenden 
würde. Und das \0 ganz am Ende macht der Compiler von sich aus, und auch 
sicher korrekt.

Und, oben hab ichs schonmal geschrieben: die "\n" kommen über die 
Tastatur durch stdin über fgets in deine Strings. Und das zu Recht und 
korrekt. Wenn du die nicht "strcat"-ten willst, musst du die selber 
löschen.

von Huch (Gast)


Lesenswert?

Ich möchte Dich bitte zu berücksichtigen, dass es sich um ein absolutes 
Grundlagenproblem handelt. Wir leiten Dich ja gerne auf die Lösung, aber 
wenn ich mich nicht irre, klingt da so ein klein wenig, Ungeduld mit uns 
durch, die Deiner Situation hier nicht angemessen ist.

Du weisst selbst nicht weiter und willst von UNS Hilfe. Wir wissen wie 
man Probleme analysiert und beschreibt. Du weisst es nicht. Also passe 
Dich bitte den Gepflogenheiten an und fange nicht auch noch an diese zu 
kritisieren. Dies in aller Höflichkeit.

von Schorsch (Gast)


Lesenswert?


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.