PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : String zerlegen und umwandeln ?!



Roberto
02.08.2007, 00:47
Hallo
Der Thread geht von hier weiter:
https://www.roboternetz.de/phpBB2/viewtopic.php?p=303371#303371

Habe das mal durchgenommen:
http://www.pronix.de/pronix-735.html

Geht aber doch nicht ganz so wie ich wollte :-s

Also mein Problem:
Ich möchte im eine Routine schreiben, wo ich auf einem Grafikdisplay, Text ausgeben kann.

Dazu möchte ich schreiben können:
Zeile=xx
Spalte=xx
Text="xxxxx"

(Das mit Zeile und Spalte funktioniert schonmal)

Jetzt muss ich aber irgendwie das schaffen, dass ich da eine String-Kette übergeben kann:-k (Text="xxx")
Diese Stringkette muss ich dann zerlegen und beginnend mit dem ersten Zeichen, umwandeln in den ASCII-Code.
Mit dem ASCII-Code könnte ich dann in meinem Zeichensatz nachschauen und die entsprechenden Daten dann am LCD ausgeben.

Leider habe ich gemerkt, dass ich mit Text[]= "T"; nur ein Zeichen übergeben kann.
Ich dachte mir, ich könnte da meine max. 40 Zeichen gleich übergeben:-s

Wie gesagt in Bascom funktioniert es ja...aber C ist da wieder so eine eigene (fremde) Welt ](*,)


Habe zu string.h noch hier was gefunden.
http://www.pronix.de/pronix-737.html
Muss das aber noch durchkauen..


Vielleicht könnt Ihr mir ja da ein paar Hinweise geben O:)

L.G. Roberto

p_mork
02.08.2007, 11:11
Hallo Roberto,

Du kannst das n-te Zeichen eines strings s mit s[n] abrufen(beginnend mit 0, nicht mit 1!)


Wenn Du ein einzelnes Zeichen schon auf das Display Zaubern kannst, dann kannst Du einen ganzen String ungefähr so ausgeben:



void LCD_puttext(char* pstr,unsigned char x_pos, unsigned char y_pos)
{
while(*pstr)//solange der string nicht zu ende ist (*pstr nicht 0 ist)
{
LCD_putchar(*pstr,x_pos,y_pos);//zeichne einen buchstaben
x_pos+=Zeichenbreite;//erhöhe die x-Position für das nachste Zeichen
pstr++;//erhöhe den Zeiger
}
}


Der erste Parameter ist dann ein Zeiger auf die Zeichenkette, der zweite und der dritte die Position.

MfG Mark

Roberto
02.08.2007, 21:27
Hallo Mark

Danke für die Antwort.
Muss mir das noch durchkauhen... (dauert noch ein bisschen)
Aber bevor alle schlafen gehen... Vielleicht kann mir noch wer sagen, wie ich eigentlich einen z.B. 30 Zeichen langen String überhaupt in ein String-Array bekomme :-k (irgendwo im Programm)

Mit :const char hallo[] = { "Hallo Welt\n" };
geht es ja nur beim deklarieren am Anfang des Codes.


Einmal hatte ich es dann im "Main" geschafft..
(Durch das probieren weis ich jetzt aber nicht mehr, ob das mit "const char..." war, oder nicht war)
Auf jedenfall wollte er es dann am Anfang von "Main" haben und nicht am Ende. (Fehler)



Und noch eine Frage dazu ;-)
Wird eigentlich immer die ganze Include Datei eingebunden oder nur die Befehle, die davon auch verwendet werden :-k

l.G. Roberto

izaseba
02.08.2007, 22:00
Hallo,

Mit :const char hallo[] = { "Hallo Welt\n" };
geht es ja nur beim deklarieren am Anfang des Codes.

1. Lass Dir dieses const auf der Zunge zergehen überleg 2 Sekunden und gib Dir selbst eine Antwort darauf, ob Du da noch was im laufendem Programm verändern kannst ;-)
2. Gut angenommen, Du läßt const Weg damit ist Dein char hallo[] genau 11 Bytes lang (der Text + Zeilenumbruch + '\0')
Damit mußt Du dafür Sorgen, daß Du nichts größeres hineinkopierst.
3. Nach der Einführung gibt es wieder 2 Wege:
A. Du nutzt die string.h und gukst Du dir strcpy(char *a,char *b) an,
es kopiert Array/Zeichenkette b in a inklusive '\0' a u. b müssen natürlich auch Nullterminiert sein.
B. Du implementierst Dir eine eigene Routine dafür z.B. so



void kopierebina(char *a,char *b) {
while(*a++ = *b++);
*a='\0';
}

Du hast die Wahl ;-)

Gruß Sebastian

Roberto
02.08.2007, 23:20
Hallo Sebastian



1. Lass Dir dieses const auf der Zunge zergehen überleg 2 Sekunden und gib Dir selbst eine Antwort darauf, ob Du da noch was im laufendem Programm verändern kannst Zwinkern
2. Gut angenommen, Du läßt const Weg damit ist Dein char hallo[] genau 11 Bytes lang (der Text + Zeilenumbruch + '\0')

Ok, das Beispiel hatte ich schnell von hier genommen:
http://www.pronix.de/pronix-735.html

Habe nachgeschaut und gesehen, dass ich es eh nur mit :
char Text [30];
deklariert habe.

Ich kann aber im "main" leider nicht richtig einen längeren String übergeben ](*,)

z.B.:

Text [] = "test test"; (invalid expression)
Text [] = 'test test; (invalid expression)
char Text [] = 'test test; (must declare in first in block) (auch bei " ")

Wenn ich das am Anfang von "main " einfüge, nimmt der Compiler es. :-k

Was mache ich falsch?

izaseba
02.08.2007, 23:40
Roberto,
langsam und nochmal von vorne:

C kennt keine Strings, leider (oder Gott sei dank) das mußt Du Dir hinter die Ohren schreiben.
Strings kannst Du in C darstellen als char Array, mit einer NULL '\0' am Ende.
Ein Array kannst Du nicht direkt in ein anderen kopieren, wie Du das vorhast
Die leeren Klammeren [] sind nur bei der Deklaration zuläßig und die muß ganz am Anfang erfolgen.
Was in die Klammer reinkommt berechnet der Kompiler selber anhand der Zeichen die zwischen "" stehen plus 1 Byte für die NULL '\0'
Zu Laufzeit ist es nicht möglich.
Was aber möglich ist, ein Array in ein anderen zu kopieren
Und in Verbindung mit Strings benutzt man die string.h !

Hier ein Beispiel:


#include<string,h>
char puffer[30]; /*Hier passen max 29 Zeichen*/
const char eintext[]="noch was";
char nocheinpuffer[10];
strcpy(puffer,"Hallo Roberto");
put_lcd(puffer);/*es wird Hallo Roberto ausgegeben*/
strcpy(puffer,eintext);
put_lcd(puffer);
strcpy(puffer,nocheinpuffer);
put_lcd(puffer);
usw.usw
Willst Du aber string.h nicht nutzen, weil Du alles zu Fuß machen willst, oder es Dir gerade danach ist nimmst Du die Funktion, die ich oben geschrieben habe und machst Du damit weiter anstatt von strcpy
ufff, ich hoffe daß es hilft

Gruß Sebastian

Roberto
03.08.2007, 00:20
Hallo Sebastian (Danke für die Geduld ;-)

So langsam dämmert es..
(Aber mit den Zeigern tue ich mich noch ein bisschen schwer)

Was sagst Du zu diesem Versuch? :-)

#include<String.h>
char Text[30];

void Lcd(char a)
{
strcpy(Text,a);
}


void main(void)
{
Lcd("Test test");
}

Oder muss ich das irgendwie mit Zeigern machen? (*)
Muss noch nachschauen, wie das mit der Übergabe von Werten an eine Funktion funktioniert...

Ps.: zur Erklärung:
Ich möchte einen Text im Code angeben ( z.B. mit: Lcd("Test test"); ) der mir dann
in das char "Text" kopiert wird.
Später zerlege ich dann char "Text" in die einzelnen Zeichen und ASCII-Werte

p_mork
03.08.2007, 09:55
Hallo Roberto!


Ich möchte einen Text im Code angeben ( z.B. mit: Lcd(Test test); ) der mir dann
in das char "Text" kopiert wird.

'Text' ist in diesem Fall kein char, sondern ein Araay von chars. Ein einzelner char kann nur einen einzigen Buchstaben aufnehmen.

Deine Funktion LCD(char a) ist auch fehlerhaft, da strcpy zwei Zeiger auf einen char erwartet und nicht einen Zeiger und einen char.

Wenn Du eine Funktion LCD_putchar(char) hast, dann kannst Du mit der Funktion meines ersten Beitrags den ein char-Array ausgeben. Da Du in C aber noch einige Probleme hast(keine Sorge, am Anfang hat jeder Probleme), werde ich Dir die Funktion näher erläutern:


/*Die Funktion LCD_puttext erwartet als ersten Parameter einen Zeiger auf das
mit 0 abgeschlossene Array von zeichen, das ausgegeben werden soll. Der
weite und dritte Parameter ist die Position des Textes
*/
void LCD_puttext(char *pstr,unsigned char x_pos, unsigned char y_pos)
{
while(*pstr)/*Folgende schleife wird solange durchgeführt, bis das char,
auf das der Zeiger pstr zeigt, nicht 0 ist. '*' ist der Dereferenzierungsoperator,
der dafür sorgt, dass der Compiler nicht mit dem Zeiger rechnet, sondern mit dem
Wert, auf den der Zeiger zeigt.*/
{
LCD_putchar(*pstr,x_pos,y_pos);/*Zeichnet den Buchstaben, der sich an der Stelle befindet,
worauf pstr zeigt auf das LCD*/
x_pos+=Zeichenbreite;//erhöhe die x-Position für das nachste Zeichen.
pstr++;/*erhöhe den Zeiger selbst. Nun zeigt er nicht mehr auf den char, der gerade
gezeichnet wurde, sondern auf den nächsten. Sollte der char, auf den er jetzt zeigt,
eine 0 sein, so wird die Schleife verlassen, weil die Bedingung in while(*pstr) nicht
mehr stimmt.*/
}
}



Jetzt Kannst Du mit LCD_puttext("Dein Text"); oder LCD_puttext(Text); (Text ist in diesem Fall das char-Array aus deinem Beitrag unten) ausgeben. Ich hoffe Du hast es jetzt einigermahßen verstanden. Guck mal hier (http://www.cpp-tutor.de/cpp/le03/le03_05.htm), wenn Du mehr über Zeiger erfahren willst.

MfG Mark

Roberto
03.08.2007, 12:01
Hallo Mark (Elefant geht leider noch nicht von der Leitung ](*,) )


Deine Funktion LCD(char a) ist auch fehlerhaft, da strcpy zwei Zeiger auf einen char erwartet und nicht einen Zeiger und einen char.
Aber das Beispiel von Izaseba
kopiert ja auch zwei Arrays?!


#include<string,h>
char puffer[30]; /*Hier passen max 29 Zeichen*/
char nocheinpuffer[10];
strcpy(puffer,nocheinpuffer);


Kann ich jetzt mit strcpy nur char aneinander hängen oder auch char-Arrays?
Sind das im obigen Beispiel jetzt Zeiger oder nur Arrays?

----------------
Angenommen ich schreibe jetzt:
Lcd ("test test");

Dann mache ich mir eine Funktion:

Lcd (char *a);

Dann habe ich ja einen ZEIGER (der "a" heißt) der auf das
Array "test test" zeigt?!

Wahrscheinlich ist "test test" kein Array?!
Wo muss ich das deklarieren?

Ps.:
@Mark

Habe deine Code mal probiert.
Leider fange ich da nix mit dem LCD_putchar..... an
(Habe das mal weggelassen)
Leider schreibt der Compiler mir bei :
LCD_puttext("test test");
immer den Fehler:
Parameter #1 of type 'flash unsigned char*' is incompatible with type 'unsigned char*' specified in the function 'LCD_puttext' declaration

p_mork
03.08.2007, 13:13
Hallo Roberto!



Aber das Beispiel von Izaseba
kopiert ja auch zwei Arrays?!


Jaja, Deine Lcd(char a)-Funktion versucht einen char in ein Array zu kopieren und nicht einen Array in ein Array.



Kann ich jetzt mit strcpy nur char aneinander hängen oder auch char-Arrays?
Sind das im obigen Beispiel jetzt Zeiger oder nur Arrays?
Aneinanderhängen kann man mit strcpy garnix, sondern nur kopieren. Du übergibst der Funktion einen Zeiger auf das Array, wo was reinkopiert werden soll und einen Zeiger auf das Array, von wo kopiert werden muss.



Wahrscheinlich ist "test test" kein Array?!
Wo muss ich das deklarieren?
Doch, "test test" ist ein Array, was anderes bleibt ja nicht übrig.


Habe deine Code mal probiert.
Leider fange ich da nix mit dem LCD_putchar..... an
(Habe das mal weggelassen)
Leider schreibt der Compiler mir bei :
LCD_puttext("test test");
immer den Fehler:
Parameter #1 of type 'flash unsigned char*' is incompatible with type 'unsigned char*' specified in the function 'LCD_puttext' declaration

Was für einen Compiler benutzt Du? Keinen GCC oder? 'flash unsigned char*' ist kein Standart-C sondern anscheinend auf die AVRs angepasstes. Ich nehme an, es soll einen Zeiger auf ein char im Flash darstellen. Dann musst Du auch in der Funktion anstatt 'unsigned char*pstr' 'flash unsigned char*pstr' schreiben. Das wird dann aber wiederum nur mit konstanten Texten gehen, aber nicht mit variablen Arrays. LCD_puttext("Hallo Welt") geht dann, LCD_puttext(Text) dann aber nicht mehr. Um Arrays auszugeben, die im RAM sind, musst Du eine zweite Funktion mit 'unsigned char*pstr' als Parameter erstellen.

MfG Mark

izaseba
03.08.2007, 17:57
Was für einen Compiler benutzt Du?
Genau, vorsicht, Roberto nutzt CodeVision, bin auch schon drauf reingefallen :-)
Trotzdem muß die Standardbibliothek funktionieren, nur die AVR spezifischen Sachen haben die Jungs anders gelöst als bei avr-gcc

@Roberto,
ein Tip von mir, besorge Dir C Kompiler für PC ( dev-c++, oder so)
Damit kannst Du erstmal rumprobieren, bis Du die Arrays und Zeiger verstanden hast ;-)

Gruß Sebastian

Roberto
03.08.2007, 18:36
Hallo

Sch.... C ](*,)
Aber ich werde nicht aufgeben O:)
Schreibe gerade einen minimum Code um ein bisschen zu probieren.
Da kann ich dann auch die Wertübergabe bei den Funktionen probieren und die Zeiger.
Eventuell dann im GCC gegenvergleichen

Frage mich nur, warum das in C so kompliziert sein muss :-k (Strings)
Bringt das irgendeinen Vorteil ?
In Bascom kann man einfach: String= "text" eingeben und fertig.

Und warum findet man da eigentlich so wenig im Forum darüber :-k


Danke einstweilen für die Geduld ;-)

l.G. Roberto

izaseba
03.08.2007, 19:07
Hmmm,
ich frage mich, warum es C sein muß, wenn Du Dich mit Bascom gut auskennst ?


Frage mich nur, warum das in C so kompliziert sein muss (Strings)
Bringt das irgendeinen Vorteil ?

Was ist daran kompliziert ?
Und ja, es bringt einen Vorteil mit sich, schon alleine bei der übergabe an eine Funktion.
Egal, wie groß Dein String ist wird immer ein Zeiger auf die erste Speicherzelle übergeben, also 16Bit.
Auch bei Strukturen, egal wieviele Elemente sie haben, werden auch nur 16 Bit übergeben.
Das bringt Power mit sich.

Und warum findet man da eigentlich so wenig im Forum darüber
Gibt es nicht genug C Tutorials/Bücher ? :-k

Ach ja C lernt man nicht von Heute auf morgen, ich widerhole mich nicht gerne, aber fang mit C auf PC an
Gruß Sebastian

Roberto
03.08.2007, 20:30
Hallo Izaseba

ich frage mich, warum es C sein muß, wenn Du Dich mit Bascom gut auskennst ?
Najaaa, irgendwann werde ich wohl C brauchen.
Sind ja schon fast alle Programmier-Sprachen irgendwie an C angelehnt.

Gibt es nicht genug C Tutorials/Bücher ? Think
Meinte Beiträge zum Thema String u.s.w. im Forum

l.G. Roberto

p_mork
03.08.2007, 20:45
Hallo!


In Bascom kann man einfach: String= "text" eingeben und fertig.

Dann musst Du wohl auf C++ umsteigen. Aber bis es soweit ist, erklär mir bitte erstmal, wofür Du 'sting="text"' brauchst. Gib mir ein Praktisches Beispiel dafür.

MFG Mark

Roberto
04.08.2007, 01:37
Hallo Mark

Aber bis es soweit ist, erklär mir bitte erstmal, wofür Du 'sting="text"' brauchst. Gib mir ein Praktisches Beispiel dafür.
z.B. Für Menues auf einem Grafik Display, Meldungen auf einem LCD ,
übertragung von Text über die Serielle u.s.w.

l.G. Roberto

Ps.:

Was für einen Compiler benutzt Du? Keinen GCC oder? 'flash unsigned char*' ist kein Standart-C sondern anscheinend auf die AVRs angepasstes. Ich nehme an, es soll einen Zeiger auf ein char im Flash darstellen. Dann musst Du auch in der Funktion anstatt 'unsigned char*pstr' 'flash unsigned char*pstr' schreiben.

Habe gerade deinen Code auf dem GCC probiert und funktioniert :-)
(Zumindest kein Error)
Hab es dann beim CodeVison probiert mit:
void( LCD_puttext( flash unsigned char *pstr,unsigned char x_pos,... )

Dann geht es mit :
LCD_puttext ("test",1,1);

Zumindest der Compiler schreit nicht :-)
Den Rest werde ich morgen mal probieren. Jetzt gehe ich mal ins Bett :-$

Ps.:
Programmiert Ihr eigentlich alle mit WinAVR und makefile?

Sternthaler
04.08.2007, 04:04
Hallo zusammen.

@Roberto
Ich will mal versuchen die Strings in C doch noch mal klarzustellen.
izaseba hat ja schon angekündigt, dass gerade bei der Parameterübergabe nur 16 Bit benötigt werden. Warum aber?


Beispiel von izaseba:

#include<string,h>
char puffer[30]; /*Hier passen max 29 Zeichen*/
const char eintext[]="noch was";
char nocheinpuffer[10];

Ergibt:
Speicher- Speicher-
adresse inhalt
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 n
31 o
32 c
33 h
34
35 w
36 a
37 s
38 NULL
39
40
41
42
43
44
45
46
47
48

Wofür werden "puffer", "eintext" und "nocheinpuffer" benötigt?
In diesen Namen stehen 'nur' die Adressen der Speicherstellen in denen der eigendliche Inhalt vorhanden ist.
Um diese Adressen aber selbst zu speicher, benötigen wir noch mehr Speicherplätze:
49 0 puffer ist hier und --> zeigt <-- auf 0*255 + 0 = Adresse 0
50 0 da puffer mit '[30]' gemacht wurde, 'gehört' ihm noch Adresse 29
51 0 eintext ist hier und --> zeigt <-- auf 0*255 + 30 = Adresse 30
52 30 eintext wurde mit '[]="noch was"' gemacht, geht also bis Adresse 38
53 0 nocheinpuffer ist hier und --> zeigt <-- auf 0*255 + 39 = Adresse 39
54 39 wie bei puffer nun bis Adresse 48

Was macht "strcpy(puffer,"Hallo Roberto");"?
--> Erst mal müssen wir fragen wo steht "Hallo Roberto" im Speicher?
Natürlich auch wieder in unserem Speicher. Also weitere Adressen: (Dürfen auch Adressen im ROM oder EEPROM sein)
55 H
56 a
57 l
58 l
59 o
60
61 R
62 o
63 b
64 e
65 r
66 o
67 NULL Das ist bei C nun einmal so. Basic kann nur eine begrenzte Anzahl Zeichen
in einem String speichern, weil die Anzahl der Bytes vorne im Speicher
der Variablen steht. Das sieht du nur nicht.
Somit hat C schon wieder einen Vorteil, weil du BELIEBIG lange Strings
speichern kannst. Hinten ist halt das NULL-Zeichen.
Nun kann also die Funktion strcpy (??, ??) etwas machen.
Was passiert?
izaseba hat es schon gesagt:
Die Zeiger (man spricht auch von Pointern) auf Speicherstellen werden als Parameter in die Funktion
reingegeben.
Welche Zeiger sind das? Natürlich die Zeiger auf Adressen.
Hier also wird der Aufruf zu:
strcpy (0, 55) <-- 0, weil puffer den Zeiger auf Adresse 0 hat
<-- 55, weil "Hallo Roberto" den Zeiger auf Adress 55 hat.
Das weiss der Kompiler, weil es keine Variable ist.

Nun wird strcpy einfach folgendes machen:
merke 55 in quelle
merke 0 in ziel
loop
Nimm den Inhalt aus der Speicherstelle quelle und schreibe ihn nach ziel
Prüfe, ob in Speicherstelle quelle ein NULL steht
Wenn nein:
erhöhe quelle um 1
erhöhe ziel um 1
gehe wieder an den Anfang von loop
Wenn ja
verlasse die loop
ende loop

Und schon sieht unser Speicher so aus:
00 H
01 a
02 l
03 l
04 o
05
06 R
07 o
08 b
09 e
10 r
11 t
12 o
13 NULL
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 n
31 o
32 c
33 h
34
35 w
36 a
37 s
38 NULL
39
40
41
42
43
44
45
46
47
48
49 0 puffer
50 0
51 0 eintext
52 30
53 0 nocheinpuffer
54 39
55 H
56 a
57 l
58 l
59 o
60
61 R
62 o
63 b
64 e
65 r
66 o
67 NULL

(Beim nächsten Beispiel bitte Variablen mit weniger Speicher benutzen ;-) )

Nocheinmal: Es werden hier also keine Variablen verschoben/kopiert oder Sonstiges. Es werden nur Inhalte aus Speicherstellen von a nach b kopiert.
Von wo nach wo sagt man der Funktion. Und damit man sich als Programmierer nicht die Speicherstellen selber merken muss, nimmt man dafür Variablen, die selber NUR die Adressen speichern wo der Daten-Inhalt deiner Variablen im Speicher steht. Diese Variablen nennt man Pointer-Variablen. Ihr Inhalt zeigt auf die Daten um die es dir/dem Programmierer geht.
Alle String-Variablen in C arbeiten so.

Vorsicht: Eine Variable in der Form
char zeichen = 'x';
ist KEIN String. Dies ist nur ein einzelnes Zeichen, welches nur genau ein Byte benötigt, und auch NICHT mit NULL beendet wird.

Ich hoffe, dass dies etwas geholfen hat.

ehenkes
04.08.2007, 06:03
Strings in C:
http://de.wikibooks.org/wiki/C-Programmierung:_Arrays_und_Strings#Strings
http://ivs.cs.uni-magdeburg.de/bs/lehre/wise0102/usp/seminare/seminar3.shtml

Wenn Du eine einfachere String-Handhabung wünschst, wechselst Du am besten zu C++ und schreibst Dir eine eigene kleine String-Klasse mit dem operator= auf Basis char. Hier einige Vorbilder, da selbst gestrickte String-Klassen erstaunlicherweise nicht leicht zu finden sind:
http://www.c-plusplus.de/forum/viewtopic-var-t-is-150988-and-highlight-is-estring.html
http://www.c-plusplus.de/forum/viewtopic-var-t-is-141852-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-estring-and-start-is-10.html
http://forum.2lucky.de/archive/o_t__t_2925__templates-meine-stringklasse.html
Buch: Till Jeske, C++, Addison-Wesley, aus der Nitty Gritty Reihe (Klasse 'Text' siehe Anhang).

Hier ein bei avr-g++ funktionierendes ausbaufähiges Beispiel:


/*****************
* Stringklasse *
******************/

// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek
void* operator new (size_t size) { return malloc(size); }
void* operator new[] (size_t size) { return malloc(size); }
void operator delete (void* ptr) { free(ptr); }
void operator delete[] (void* ptr) { free(ptr); }

class MyString
{
private:
char * pData_;

public:
friend MyString operator+( const MyString &, const MyString & );
MyString() : pData_( NULL ) {} // inline ctor
MyString( const char * pText );
MyString( const MyString & text ); // Copy-Konstruktor
~MyString(); // dtor
const MyString & operator=( const MyString & text );

bool operator==( const MyString & text ) const;
char operator[]( int index ) const;
operator const char * () const; // cast zum C-String
operator char * () const; // cast zum C-String
int getLaenge() const;
void ausgeben() const;
};

MyString operator+( const MyString & leftstring, const MyString & rightstring );

/************************************************** ****************/

// ctor mit C-String als Argument
MyString::MyString( const char * pText ) : pData_( NULL )
{
if( pText )
{
pData_ = new char[ strlen( pText ) + 1 ];
strcpy( pData_, pText );
}
}

// copy-ctor
MyString::MyString( const MyString & text ) : pData_( NULL )
{
if( text.pData_ )
{
pData_ = new char[ strlen( text.pData_ ) + 1 ];
strcpy( pData_, text.pData_ );
}
}

// dtor
MyString::~MyString()
{
delete[] pData_;
}

// ==
bool MyString::operator==( const MyString & text ) const
{
if( pData_ == NULL || text.pData_ == NULL )
{
return ( pData_ == NULL && text.pData_ == NULL );
}
return ( strcmp( pData_, text.pData_ ) == 0 );
}

// []
char MyString::operator[]( int i ) const
{
if( i >= 0 && i < getLaenge() )
{
return pData_[i];
}
else
{
return '\0';
}
}

// Länge des Textes ermitteln
int MyString::getLaenge() const
{
if( pData_ == NULL )
{
return 0;
}
else
{
return strlen( pData_ );
}
}

// cast zu C-String
MyString::operator const char * () const
{
return pData_;
}

// cast zu C-String
MyString::operator char * () const
{
return pData_;
}

// Zuweisungs-Operator
const MyString & MyString::operator=( const MyString & text )
{
if( this == &text ) // Selbstzuweisung abfangen
{
return *this;
}
delete[] pData_;
if( text.pData_ )
{
pData_ = new char[ strlen( text.pData_ ) + 1 ];
strcpy( pData_, text.pData_ );
}
else
{
pData_ = NULL;
}
return *this;
}

void MyString::ausgeben() const
{
// TODO
}

/************************************************** ****************/

MyString operator+( const MyString & leftstring, const MyString & rightstring )
{
MyString result;
if( leftstring.pData_ != NULL && rightstring.pData_ != NULL )
{
result.pData_ = new char[ strlen( leftstring.pData_ ) +
strlen( rightstring.pData_ ) + 1 ];
strcpy( result.pData_, leftstring.pData_ );
strcat( result.pData_, rightstring.pData_ );
}
else if( rightstring.pData_ != NULL )
{
result = rightstring;
}
else if( leftstring.pData_ != NULL )
{
result = leftstring;
}
return result;
}

robocat
04.08.2007, 10:32
so eine stringklasse ist am rechner ja praktisch, aber in einem kleinen controller nimmt das zuviel speicher. ausserdem hat man sich damit des problems entledigt, ohne es verstanden zu haben. dabei ist es wirklich kein zauberwerk.

wenn die max. länge der zeichenkette zur compilezeit bekannt ist, kann man arrays nehmen, das wurde ja schon angesprochen.

wenn nicht, kann man dynamisch speicher allozieren:


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
char *p=malloc(7);
strcpy(p,"123456");
printf("%s\n",p);
p=realloc(p,13);
strcat(p,"789ABC");
printf("%s\n",p);
free(p);
return 0;
}

gruesse

ehenkes
04.08.2007, 11:10
aber in einem kleinen controller nimmt das zuviel speicher
Klasse lässt sich sicher noch optimieren. Ich verwende C++ beim ATmega32 oder ATmega128. Da gibt es damit bisher kein Problem.

izaseba
04.08.2007, 14:24
z.B. Für Menues auf einem Grafik Display, Meldungen auf einem LCD ,
übertragung von Text über die Serielle u.s.w

Überträngst Du nur konstante Texte ?
na gut was ist schwieriger an
strcpy(String,"text");
als String="text"
Das mußt Du mir jetzt erklären ](*,)

Und das ganze C++ mit Klassen, toll was hab ich davon mit C++ zu arbeiten, wenn ich die Vorteile dieser Sprache nicht nutzen kann, weil sie nicht unterstützt werden ?
@ehenkes,
Toll M32 und M128 ?
Es gibt auch Leute, die es etwas kleiner brauchen, wenn ich die großen AVRs nutzen will/muß kann ich auch ruhig mit Basic drangehen.
Programmiere mal einen T13 mit C++ und Deinen Klassen.
Es gab hier mal einen Fred, der wollte mal blinki blinki auf T13 mit Basic machen.
Daraufhin kam ein anderer Fred, der meinte, der Speicher reicht nich aus dafür, er möge bitte einen Kontroller nehmen, der 2 Nummer größer sei.
Ich habe ihm sein blinki blinki in asm geliefert, es blieben noch etwa 800 Bytes unbenutzt, es hat keiner mehr was gesagt, wie toll doch Basic wäre...(habe gerade keine Lust diesen Thread zu suchen)
Also immer schön abwegen was man auf welchem Kontroller machen will ;-)

Gruß Sebastian

ehenkes
04.08.2007, 15:23
Also immer schön abwegen was man auf welchem Kontroller machen will ZwinkernAkzeptiert! Für 8K und Lichtorgeln ist C++ sicher nicht der richtige Ansatz.

Wenn man in Richtung schwache KI will oder vorhandene C++-Klassen nutzen will, dann macht das absolut Sinn. Dafür brauche ich z.B. C++. Die Zukunft auf den AVR ist m.E. C++, java, ... Die Speichergrößen und Geschwindigkeiten laufen einem da entgegen, genau wie beim PC. Assembler ist für die kleine Elektronik aber ideal, vor allem für Serien.

izaseba
04.08.2007, 15:55
Vorhandene C++ Klassen ?
Welche klassen gibt es speziell für AVR ?
Zugegeben, ich habe noch nicht C++ auf µC gemacht, es würde mich aber interessieren.
Meine Erfahrung ist aber, daß C++ größeren Code produziert als C.
Damit ich hier was zu argumentieren habe, habe ich eben das berühmte "Hallo World!" einmal in C und einmal in C++ geschrieben.
Beide mit -O2 übersetzt und strip verwendet um Debuginformationen loszuwerden.
Ergebnis :
C 2932 Bytes
C++ 3896 Bytes
Ist der Unterschied bei avr-gcc <-> avr-cpp auch so groß ?
Wenn das so ist, wäre das ein K.O, kriterium für C++...

Versteh mich nicht falsch, ich habe nichts gegen C++, im Gegenteil ich schreibe gerne Programme mit, aber auf AVR bin ich eher Minimalist und wenn ich einen Kontroller > M8 verwende, dann nur weil ich mehr Pins brauche und nicht wegen Flashmangel ;-)

Gruß Sebastian

ehenkes
04.08.2007, 21:50
Versteh mich nicht falsch, ich habe nichts gegen C++, im Gegenteil ich schreibe gerne Programme mit ...
Nein, ich verstehe Dich richtig. Dein minimalistischer Ansatz ist in bestimmten Bereichen völlig überlegen, weil notwendig! Aber im Bereich der Robotik kommen die Fortschritte eher durch die OOP-Sprachen wie z.B. C++. Viele koppeln noch den PC per Funk, Kabel oder IR-Schnittstelle an den Roboter, aber durch die zunehmende Leistungsfähigkeit der µC wird sich da in den nächsten Jahren einiges ändern. Die Zukunft gehört leistungsfähigen, autonomen Systemen mit OOP. Da bin ich ganz sicher. Man sieht dies bereits im akademischen Bereich. Siehe z.B. Khepera, http://www.informatik.uni-leipzig.de/~pantec/khepera/libkhepera/ (C++-Bibliothek bereits vor 10 Jahren)


Vorhandene C++ Klassen ?
Welche klassen gibt es speziell für AVR ?
Spezielle C++-Klassen für AVR gibt es (STL, boost), aber leider nur kommerziell verfügbar! Die meisten AVR-C++-Entwickler basteln sich selbst eigene Klassen. Das muss ich z.B. für den Nibo auch machen. Echt schade, dass dies immer wieder mehrfach hinter vorgehaltener Hand entwickelt wird.


Mit vorhandenen Klassen meine ich die fast schon unüberschaubare Vielfalt an bereits vorhandenen C++-Klassen, die man offen zugänglich im Internet findet. Der Vorteil der C++-Klasse (gilt natürlich auch für java) ist doch gerade der modulare Einsatz und die Kapselung. Bei AVR muss man allerdings einiges anpassen, da viele C++-Features nicht im Sinne von Open Source unterstützt werden. Ich denke aber, dass hier der AVR-GCC sich mit zunehmenden Speichergrößen und Rechengeschwindigkeiten immer mehr in Richtung C++ entwickeln wird, da der objektorientierte Ansatz bezüglich des Entwicklungsaufwandes (nicht des Ergebnisses!) der überlegenere ist. C drängt in diesem Sinne im professionellen Bereich Assembler etwas zurück, weil es einfacher wiederverwendbar und besser lesbar ist. Für C++ gilt dies verstärkt.

Interessant sind z.B. Klassen im Bereich der schwachen KI, Beispiele: http://fbim.fh-regensburg.de/~saj39122/Diplomarbeiten/ReschReif/quellen/diplomarbeit.pdf und http://www.ai-junkie.com/ai-junkie.html (Finite State Machine, Neuronale Netze, genetische Algorithmen, Kohonen-Netze, etc.)

Mit dem ATmega128 mit immerhin schon 4096 Bytes SRAM (flankiert durch zwei ATtiny44 für die Motorensteuerung und IR-Abstandsmessung bzw. Empfang/Senden von RC5-Codes) des Nibo lässt sich mit C++ schon ordentlich programmieren. Bei 128 K Flash kommt es auf 1K Unterschied im Programm auch nicht mehr an! :) Das ist der entscheidene Punkt. Hier ändert sich etwas.

Roberto
05.08.2007, 13:30
Hallo

@Sternthaler
Danke für deine Mühe :-)
Habe das mal durchgekaut ;-)

Dazu ein paar Fragen :

Den Stern muss man ja nur beim deklarieren angeben (char *str;)
Nachher nicht mehr ? Stimmt das?

Kann man das dann nicht irgendwie leicht verwechseln?
Weil str ist ja dann eigentlich ein Zeiger.
naja, eigentlich ja nur eine Variable als Zeiger... :-k
Dachte mir nur, dass kann man dann später im Programme vielleicht irgendwie verwechseln....

-----
Sonstige Neuheiten

Stricke gerade wieder am Programm
Inzwischen ging die Werteüberweisung schon mit dem "flash unsigned char...)

Dann verwendete ist dazu das strcpy
Aber er meldete dann wieder Fehler ](*,) ](*,)

Ich lasse das mal einstweilen und schreibe mal weiter beim Stringumwandeln.

Dazu probiere ich gerade mit "atoi"
Irgendwie spinnt es da auch.. ](*,)

Eigentlich müsste es ja so funktionieren:

char Text[]= "test";
int String_asc;
String_asc = atoi (Text[1]);

Werde da noch weiter probieren und mich dann wieder melden.

l.G. Roberto

robocat
05.08.2007, 14:49
folgendes beispiel ist nicht ganz einfach zu verstehen, zeigt aber, wie man mit zeichenketten, zeigern (und atoi) arbeitet. es werden zahlen aus einer zeichenkette extrahiert und addiert. am ende wird das ergebnis (integer) wieder in eine zeichenkette gewandelt.

mit char *p wird der zeiger deklariert. später (das ist bissl verwirrend) ist *p aber der char-wert, auf den p gerade zeigt. p wandert hier (mit p++) durch die zeichenkette "array", bis er auf die 0 am ende der zeichenkette stösst.


#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int i=0,summe=0;
char array[]="Ein String mit der Zahl 123 und der Zahl 456 drin";
char buffer[8];

char *p; // ein char-zeiger
p=array; // der zeiger zeigt nun auf erstes element von array

printf("untersuche zeichenkette: %s\n",array);

while(*p) // wiederhole bis der wert des char´s, auf den p zeigt = 0 ist (dort endet der string)
{
if(*p>47&&*p<58) // wenn dieser wert eine ziffer ist (0-9)
{
buffer[i++]=*p; // dann füge sie dem array 'buffer' zu
}
else if(i>0) // andernfalls (wenn i>0 ist, wurden bereits ziffern gefunden, das aktuelle zeichen ist aber keine zahl mehr)
{
buffer[i]=0; // 0-terminieren

printf("zahl gefunden: %s\n",buffer); // die ascii-zeichen der zahl liegen nun in buffer

summe+=atoi(buffer); // in integer (ganzzahl-wert) wandeln und zu "summe" addieren

i=0; // weiter geht die suche nach weiteren zahlen
}
p++; // den zeiger in "array" weiterbewegen
}
printf("summe der zahlen: %d\n",summe);

itoa(summe,buffer,10);
printf("summe als zeichenkette: %s\n",buffer);

return 0;
}

buffer ist hier mit 8 zeichen sehr klein, und es wurden keine "sicherheitsmassnahmen" eingebaut. in der praxis müsste man unbedingt darauf achten, dass nicht über das ende von buffer hinausgeschrieben werden kann.

ich kann dir (wie izaseba bereits) nur empfehlen, solche fingerübungen am pc zu machen, die fehlersuche gestaltet sich dann viel einfacher.

gruesse

Roberto
06.08.2007, 01:41
Hallo Robocat

Danke für das Beispiel. Hat mir sehr geholfen \:D/

Wusste nicht, dass die Zeichen im Speicher, sowieso als ASCII vorliegen.
Habe da dann einen Zeiger deklariert, diesen auf mein Array zeigen lassen und den Zeiger nach jedem Zeichen eins rauf zählen lassen O:)
Mit *Zeiger dann den ASCII-Wert ausgelesen und verwertet :-b

Langsam fangen meine Neuronen ja in C zu denken an :Haue

Das alte Problem, gehe ich demnächst an ;-)

l.G. Roberto

Roberto
07.08.2007, 00:52
Hallo
Habe inzwischen Hilfe bekommen :-)
http://www.mikrocontroller.net/topic/15088#623380
Hier habe ich nach langen Suchen auch noch was gefunden:
http://www.embeddedrelated.com/usenet/embedded/show/41447-1.php

Jetzt ne blöde Frage:
Flash ist ja der Teil, wo der Programmcode reinkommt.
Da sehe ich im Datenblatt was von 10000 Read/Write's.
Wird da jetzt mit Flash bei jedem Aufruf der String in dieses Flash geschrieben? :-k

l.G. Roberto

ehenkes
07.08.2007, 05:59
Schau Dir mal noch diesen sehr gut bebilderten und erklärten Artikel an:
http://www.nongnu.org/avr-libc/user-manual/malloc.html

Roberto
07.08.2007, 09:05
Hallo
Leider kann ich nicht gut englisch.
Sehe auch nix von Flash.
Was willst Du mir damit sagen?.
l.G. Roberto

izaseba
07.08.2007, 10:17
Flash ist ja der Teil, wo der Programmcode reinkommt.
Da sehe ich im Datenblatt was von 10000 Read/Write's.
Wird da jetzt mit Flash bei jedem Aufruf der String in dieses Flash geschrieben?

Roberto, gleich gibt es was auf die 12...
Ich habe mir Codevision angeschaut, man muß hin und wieder über den Tellerrand schauen ;-)
Die Doku ist sehr gut, die string.h Bibliothek ist um ziemlich viele Funktionen zu Stringbehandlung erweitert worden.
und nein, der Qualifizierer "flash" gibt nur an, daß diese Konstante sich im Flash befindet und aus dem flash zu lesen ist
Es entspricht etwa diesem dim as byte in flash/progmem odr wie es bei Basic nochmal heißt.
Es wird also nichts im flash geschrieben sondern im Flash beim Programm übertragen abgelegt um RAM zu sparen.
Was Dir ehenkes allerdings sagen will weiß ich auch nicht :-k
Zu CodeVision,
Ich habe versucht ein kleines Programm zu schreiben, leider kann ich mit der demo Version keine Interrupts nutzen :-( (angeblich ist die demoversion uneingeschränkt nutzbar bis auf die 2 kB Codegröße)
Außerdem kennt es keine Bitbezeichnungen wie RXC TXC usw.(vielleicht muß man noch was einbinden)
Sonst ziemlich nett.

Gruß Sebastian[/quote]

Roberto
07.08.2007, 21:39
Hallo Izaseba

Roberto, gleich gibt es was auf die 12...
mhhh..... :-k , was heißt den das ?
Kenne ich in Österreich nicht


Es wird also nichts im flash geschrieben sondern im Flash beim Programm übertragen abgelegt um RAM zu sparen.
Ok, gut. Dann bin ich beruhigt ;-)
Arbeitet da Codevison besser als WinAVR oder ist das nur eine Eigenart von WinAVR?


Ich habe versucht ein kleines Programm zu schreiben, leider kann ich mit der demo Version keine Interrupts nutzen
Nach dem suchen zu meinem Problem, habe ich auch was über Interrupts aufgeschnappt:
http://www.mikrocontroller.net/topic/45324#new
http://www.mikrocontroller.net/topic/43524#new
Hier was allgemeines:
http://www.mikrocontroller.net/topic/21955#new

Aber mit Interrupts habe ich in C noch nix probiert.

Bin ja fast schon am überlegen, ob ich nicht zurück auf WInAVR umsteige.
Aber CodeVison ist recht benutzerfreundlich.. Also bleibe ich einstweilen mal da :-b

l.G. Roberto

izaseba
07.08.2007, 22:52
Danke für die Links,
ich wollte eben nur kurz mit dem Assistenten was zusammenklicken, naja der Assistent hat mich freundlich drauf hingewiesen, daß ich Interrupts in der Demoversion vergessen kann, auch egal ;-)
Für mich ich das nichts, sonst müßte ich mich da erstmal einarbeiten avr-gcc kenn ich schon ziemlich gut und bin damit mehr als zufrieden, warum soll ich mir dann CodeVision antun ?
Ich liebe Makefiles und meinen Emacs ;-)
Wenn Dir CodeVision mehr zusagt, dann bleib dabei, keine Frage, Du darfst aber nicht zu viele Fragen stellen(zumindest nicht in diesem Forum)
Wie weit bist Du mit Deinem Projekt ?
Ich würde an Deine Stelle vielleicht nicht so hoch anfangen, ein Blinki Licht basteln zum einarbeiten, oder sowas ?

Gruß Sebastian

Roberto
07.08.2007, 23:53
Hallo Izaseba

naja der Assistent hat mich freundlich drauf hingewiesen, daß ich Interrupts in der Demoversion vergessen kann, auch egal
Mit dem Assistenten habe ich mich noch nicht eingelassen.


Ich liebe Makefiles und meinen Emacs
Was ist Emacs?
(Makefiles)Dann weis ich ja , wen ich fragen kann ;-)


Wie weit bist Du mit Deinem Projekt ?
Danke der Nachfrage.
Geht jetzt alles super. \:D/
Habe heute das noch so umgeschrieben, dass ich mit einem Funktionsaufruf, den Text und auch gleich die Zeile und Spalte mitangeben kann (integer)
Zur Umsetzung:
Ich wollte das absichtlich ziemlich gleich in C schreiben, wie im Bascom, damit ich vergleichen kann, wieviel C weniger Speicher braucht.
Ist aber nur ein bisschen weniger.


Ich würde an Deine Stelle vielleicht nicht so hoch anfangen, ein Blinki Licht basteln zum einarbeiten, oder sowas ?
mmmhhh.... :-k
Bezieht sich das jetzt auf meine blöden Fragen??? :-k
Ich traue mich wenigstens fragen ;-)

Blinki Licht, kriege ich schon hin . :-$

l.G. Roberto

izaseba
08.08.2007, 10:27
Was ist Emacs?

Schau mal hier (http://de.wikipedia.org/wiki/Emacs)
Allerdings ist es nichts für Mausschubser.

mmmhhh....
Bezieht sich das jetzt auf meine blöden Fragen???
Ich traue mich wenigstens fragen

Blinki Licht, kriege ich schon hin .
Ich glaub Dir, daß Du Blinki auf die rehe kriegst, es geht sich eher darum mit der Sprache vertraut zu werden ;-)
Es lassen sich Sachen nicht immer 1:1 von anderen Sprachen übernehmen bzw. anders beschreiben/lösen.
Weißt Du was von Qualität der CV Übersetzung ?
Ich habe ja mein Testprogramm mit CV geschrieben um zu vergleichen, es fiel nicht besondest gut für CV aus, genaueres kann ich im Moment nicht sagen, ich sitze jetzt nicht am Winrechner, wenn interesse besteht schau ich genauer nach.
Wie dem auch sei, glückwunsch daß Du es geschaft hast, und denk daran, es gibt keine dummen Fragen :-#