Hallo zusammen,
Ich darf die Arbeit eines Kollegen fortsetzen.
Leider funktioniert das was er gemacht hat nicht wie gewuenscht.
Er hat Kommandos als globale Strings definiert. Dieses "verbiegt" er
dann in ein Array von char Zeigern.
Dann ueberschreibt er Kommandos, indem er zweidimensional auf das char*
Array zugreift.
Geht das gut? Zumal die globalen Strings unterschiedliche Groessen
haben.
Ich freue mich ueber jeden (vernuenftigen ;) Hinweis!
Hier mal sinngemaess, was er sich ausgedacht hat. (Originale darf ich
hier nicht posten!)
AVR Noob schrieb im Beitrag #3506913:
> Hier mal sinngemaess, was er sich ausgedacht hat.
Da du seinen Code nicht verstehst, kannst du ihn nicht sinngemaess
wiedergeben. Das bringt so nichts. 2-Dimensionale Arrays kommen in
deiner Wiedergabe auch gar nicht vor.
Hallo Quack,
vielen Dank fuer Deinen vernuenftigen Hinweis. :(
Auch vielen Dank fuer Deien Einschaetzung, dass ich das nicht verstehe.
Ja, zweidimensionale Arrays kommen nicht vor. Wohl aber der
zweidimensionale Zugriff:
1
for(i=0;i<=strlen(replacement),i++)
2
{
3
Commands[index][i]=replacement[i];
4
}
Wenn Du mir das erklaeren kannst wuerde ich mich freuen. Auf Hinweise
das ich das nicht verstehe kann ich verzichten. Wenn ich genau wuesste
was das Problem ist, braeuchte ich dieses Forum nicht.
MfG
balze aka AVR Noob
AVR Noob schrieb im Beitrag #3506913:
> Leider funktioniert das was er gemacht hat nicht wie gewuenscht.
Woran hast du denn erkannt, daß es genau das ist, was nicht
funktioniert? Wie äußert sich das nicht-Funktionieren? Am besten gehst
du das Problem an, indem du aus dem Code oben ein minimales, aber
komplettes und compilierbares Programm machst, das den Fehler zeigt. Ein
"sinngemäßes" Codefragment ist meist nicht wirklich geeignet, um es auf
Fehler zu analysieren.
> Dann ueberschreibt er Kommandos, indem er zweidimensional auf das char*> Array zugreift.>> Geht das gut?
Ich sehe da so erstmal kein Problem, mal abgesehen davon:
> Zumal die globalen Strings unterschiedliche Groessen haben.
Du mußt halt höllisch aufpassen, daß du beim "replacen" niemals etwas
reinschreibt, für das nicht genug Platz ist. In deinem Beispiel tust du
das aber nicht, also hätte das so funktionieren müssen.
AVR Noob schrieb im Beitrag #3506913:
> Commands[0] = (char*) &Command_1;
Es würde sich anbieten, den Adressoperator wegzulassen. Dann ist die
Adresse gleich vom richtigen Typ und man braucht diesen Cast nicht.
Commands[0] = Command_1;
...
> /* replace function */> Set_Command(uint8_t index, char *replacement)> {> uint8_t i;>> for (i=0; i<=strlen(replacement),i++)> {> Commands[index][i] = replacement[i];> }> }
Das könnte man auch gleich durch strcpy ersetzen:
1
/* replace function */
2
voidSet_Command(uint8_tindex,char*replacement)
3
{
4
strcpy(Commands[index],replacement);
5
}
AVR Noob schrieb im Beitrag #3506935:
> Auf Hinweise das ich das nicht verstehe kann ich verzichten.
Was denn nun? Kurz vorher hast du dich noch dafür bedankt.
Verzichten kann man übrigens auch auf eine Fehlerbeschreibung, die nicht
über ein "funktioniert nicht" hinausgeht.
Hallo Rolf Magnus,
vielen Dank fuer Deine Antwort.
Rolf Magnus schrieb:> AVR Noob schrieb im Beitrag #3506913:>> Leider funktioniert das was er gemacht hat nicht wie gewuenscht.>> Woran hast du denn erkannt, daß es genau das ist, was nicht> funktioniert? Wie äußert sich das nicht-Funktionieren? Am besten gehst> du das Problem an, indem du aus dem Code oben ein minimales, aber> komplettes und compilierbares Programm machst, das den Fehler zeigt. Ein> "sinngemäßes" Codefragment ist meist nicht wirklich geeignet, um es auf> Fehler zu analysieren.
Das Program besteht zu 90% aus CAN Kommunikation.
Alle Funktionen laufen einwandfrei, bis auf das Ersetzen von Kommandos.
Das Ruecklesen der Kommandos funktioniert, das UEberschreiben nicht.
Der wesentliche Unterschied ist der schreibende Zugriff wie
"sinngemaess" wiedergegeben.
> Du mußt halt höllisch aufpassen, daß du beim "replacen" niemals etwas> reinschreibt, für das nicht genug Platz ist. In deinem Beispiel tust du> das aber nicht, also hätte das so funktionieren müssen.
Dann werde ich das vor dem UEberschreiben ueberpruefen.
> Es würde sich anbieten, den Adressoperator wegzulassen. Dann ist die> Adresse gleich vom richtigen Typ und man braucht diesen Cast nicht.
Guter Hinweis, werde ich machen.
> Das könnte man auch gleich durch strcpy ersetzen:/* replace function */> void Set_Command(uint8_t index, char *replacement)> {> strcpy(Commands[index], replacement);> }
Stimmt, danke!
> AVR Noob schrieb im Beitrag #3506935:>> Auf Hinweise das ich das nicht verstehe kann ich verzichten.>> Was denn nun? Kurz vorher hast du dich noch dafür bedankt.
Sorry, war zynisch. Ich aergere mich immer wieder ueber Antworten, die
keinerlei Nutzen bringen, dafuer die Frage aber die erste Antwort hat.
Quacks Kommentar hilft mir nicht und wird niemandem helfen, der
aehnliche Verstaendnisprobleme hat. Anders sieht es mit Deiner Antwort
aus.
Deshalb Vielen Dank.
> Verzichten kann man übrigens auch auf eine Fehlerbeschreibung, die nicht> über ein "funktioniert nicht" hinausgeht.
Ja, tut mir leid. Damit hast Du voellig Recht. Keiner von uns besitzt
eine (funktionierende) Glaskugel. Leider kann man nicht in den
Mikrocontroller hinein sehen, um zu erkennen, was genau zu welchem
Zeitpunkt "in die Hose" geht. In diesem Fall habe ich den Unterschied zu
den funktionierenden Teilen dargestellt.
MfG,
balze aka AVR Noob
AVR Noob schrieb im Beitrag #3506913:
> Geht das gut? Zumal die globalen Strings unterschiedliche Groessen> haben.
Je nun, das geht halt so lange gut, bis du was überschreibst. In deinem
Beispiel ist das replacment-Commando genauso lang wie das ursprüngliche.
Das passt dann, aber wenns länger gewesen wäre, wäre Command3 kaputt.
Und wenn du über das letzte Kommando hinausschreibst, gibt es eh
Ram-salat.
Ergo: das funktioniert, wenn man keine Fehler macht. Die Chancen, da was
zu versemmeln, liegen aber nur wenig unter 100%.
Ach ja, da CAN Bus: Um welches Sorte Gerät geht es denn? (nur damit ich
darum einen großen Bogen machen kann)
Wenn man schon solche Spielereien macht, sollte es da wenigstens
Datenstrukturen geben, die die Länge des zur Verfügung stehenden Platzes
kennen, und dann per Zugriffsfunktion und strncpy sichergestellt sein,
daß der Platz nicht überschrieben wird. Da das ganze ja anscheinend mit
zur Compilezeit bekannte Konstanten passiert, können ein paar ASSERTS
dann noch zusätzlich dafür sorgen, daß da nichts schief geht.
Oliver
Hallo,
wenn ich den Code sehe bekomme ich Fussnagelkreuseln!
Teilweise ineffizient (Kopierschleife) und im ganzen kaum wartbar. Die
impliziten Einschränkungen hat man blitzartig vergessen.
Wenn das replacement selten vorkommt, würde ich mit malloc arbeiten,
wenn es häufig auftritt festen Platz reservieren. Und dann ganz
geradeaus programmieren :-). Also strcpy/strncpy... verwenden.
Grüße, Kurt
AVR Noob schrieb im Beitrag #3507022:
> eine (funktionierende) Glaskugel. Leider kann man nicht in den> Mikrocontroller hinein sehen, um zu erkennen, was genau zu welchem> Zeitpunkt "in die Hose" geht.
Dann muss man da eben Abhilfe schaffen!
Oder was glaubst du, wie Profis das machen?
Commands[5]=(char*)&Command_6;// Fehler: Array-Überlauf bei Commands[5].
28
// Command_6 existiert nicht.
29
....
30
Set_Command(index,command_replacement);// Unsauber: Prototyp zu Set_Command fehlt
31
....
32
}
33
34
/* replace function */
35
Set_Command(uint8_tindex,char*replacement)
36
{
37
uint8_ti;
38
39
for(i=0;i<=strlen(replacement),i++)// Ineffizient: Bei einem älteren C-Compiler würde
40
// strlen in jedem Schleifendurchlauf aufgerufen werden.
41
// Fehler: Das Komma sollte wohl ein Semikolon sein.
42
{
43
Commands[index][i]=replacement[i];// Gefährlich: Was passiert, wenn replacement länger als
44
// Command[index] ist?
45
}
46
}
Da es so scheint, als wären die Command- und die Replacement-Strings
jeweils fest und zur Compile-Zeit bekannt, wäre folgendes eine
übersichtlichere, effizientere und sicherere Variante:
1
#include<stdint.h>
2
3
constchar*Commands[5]=
4
{
5
"Example_123",
6
"Examp",
7
"Example;",
8
"Example",
9
"Example"
10
};
11
12
voidSet_Command(uint8_tindex,char*replacement)
13
{
14
Commands[index]=replacement;
15
}
16
17
intmain()
18
{
19
char*command_replacement="Replace";
20
uint8_tindex=2;
21
22
Set_Command(index,command_replacement);
23
return0;
24
}
Dabei muss aber darauf geachtet werden, dass der String, der an
Set_Command übergeben wird, dauerhaft existent ist. In diesem Beispiel
ist das der Fall.
Kann dies nicht sichergestellt werden, muss die Funktion Set_Command
dahingehend erweitert werden, dass sie eine mit malloc und strcpy
erzeugte Kopie des übergebenen Strings in Commands einträgt. Vorher muss
das bisherige char-Array mit free freigegeben werden. Da dies aber mit
den in der Initialisierung von Commands verwendeten statischen Strings
nicht möglich ist, müssen diese ebenfalls durch dynamisch erzeugte
char-Arrays ersetzt werden, was die Intialisierung etwas umständlich
macht. Zudem wird der Code durch die free- malloc- und strcpy-Aufrufe
weniger effizient, was aber nur dann eine Rolle spielt, wenn Set_Command
sehr oft aufgerufen wird.
Yalu X. schrieb:> Da es so scheint, als wären die Command- und die Replacement-Strings> jeweils fest und zur Compile-Zeit bekannt, wäre folgendes eine> übersichtlichere, effizientere und sicherere Variante:
Noch wesentlich sicherer wäre es, die Replacement-Kommandos auch noch
mit in das Array zu packen, und nur noch die Pointer auf die jeweils
benötigten Strings umzuhängen. Damit wird man das "herzerfrischend
bescheuerte" String-Kopieren ganz los.
Aber ganz ehrlich, ich fürchte, der Rest des Programms sieht ähnlich
aus.
Komplett in die Tonne damit, und neu schreiben.
Oliver
Hallo zusammen,
vielen Dank fuer die vielen Antworten und die guten Hinweise.
Oliver schrieb:> Ergo: das funktioniert, wenn man keine Fehler macht. Die Chancen, da was> zu versemmeln, liegen aber nur wenig unter 100%.
Da die Replacement Commandos von Extern (ueber CAN) kommen, kann ich das
nicht garantieren und ich muss hier besonders gruendlich sein.
> Ach ja, da CAN Bus: Um welches Sorte Gerät geht es denn? (nur damit ich> darum einen großen Bogen machen kann)
:) Keine Sorge. Du brauchst keinen Bogen darum machen, da das Geraet die
Abteilung nie verlassen wird. Versprochen!
> Wenn man schon solche Spielereien macht, sollte es da wenigstens> Datenstrukturen geben, die die Länge des zur Verfügung stehenden Platzes> kennen, und dann per Zugriffsfunktion und strncpy sichergestellt sein,> daß der Platz nicht überschrieben wird. ...
So werde ich es machen.
Kurt Harders schrieb:> Hallo,> wenn ich den Code sehe bekomme ich Fussnagelkreuseln!
ging mir auch so, obwohl ich garantiert kein C Profi bin. (Ich moechte
aber noch was lernen und besser werden!)
Karl Heinz schrieb:> Dann muss man da eben Abhilfe schaffen!>> Oder was glaubst du, wie Profis das machen?
Das wuerde ich sehr gerne wissen. Damit ich es das naechste Mal besser
machen kann.
Yalu X. schrieb:> Hier sind ein paar Kommentare zu deinem Code:
Danke fuer die Kommentare und Fehlerberichtigungen
> Da es so scheint, als wären die Command- und die Replacement-Strings> jeweils fest und zur Compile-Zeit bekannt, wäre folgendes eine> übersichtlichere, effizientere und sicherere Variante:
Das ist, wie oben beschrieben, leider nicht der Fall
> weniger effizient, was aber nur dann eine Rolle spielt, wenn Set_Command> sehr oft aufgerufen wird.
Effizienz sollte in meinem Fall kein Problem sein.
Oliver schrieb:> Komplett in die Tonne damit, und neu schreiben.
Ja, das waere auch mein Wunsch gewesen. Der Grund warum ich es
fortsetzen darf ist aber leider (wie sooft) fehlende Zeit. Obwohl mir
durchaus klar ist, dass man mit dem Beseitigen von Problemen mindestens
genauso viel Zeit "verbraten" kann.
Vielen Dank Euch allen!
MfG
balze aka AVR Noob
Avr Noob schrieb:>> Oder was glaubst du, wie Profis das machen?>> Das wuerde ich sehr gerne wissen.
Debug Code!
Dazu muss man sich eine Ausgabefläche schaffen, auf der man vom Programm
aus Ausgaben machen kann. Zb eine UART, zb ein LCD. irgendwas.
Hauptsache man kriegt Werte raus.
Und dann kommen in den Code eben Ausgabe-Anweisungen rein, mit denen man
sich die aktuellen Werte ausgeben lässt.
D.h. Sofern man keinen Debugger hat, mit dem man dem Programm zur
Laufzeit über die Schulter schauen kann.
> Damit ich es das naechste Mal besser> machen kann.
Auf einem µC kann man auch so vorgehen:
Es gibt in jedem Programm Teile, die sind in keinster Weise vom µC
selber abhängig. Eine String-Verwaltung und String Austausch in einer
Datenstruktur ist nicht davon abhängig, wo der String herkommt.
Ergo: Das kann man sich alles auf einem PC mit seinen im Vergleich zum
µC weit überlegenen Debug-Möglichkeiten problemlos ansehen, entwickeln
und testen.
> Ja, das waere auch mein Wunsch gewesen. Der Grund warum ich es> fortsetzen darf ist aber leider (wie sooft) fehlende Zeit. Obwohl mir> durchaus klar ist, dass man mit dem Beseitigen von Problemen mindestens> genauso viel Zeit "verbraten" kann.
Ab einem gewissen Level der verbuggt-heit, kannst du das 'kann' durch
ein 'wird' ersetzen.
Die erste Frage, die sich stellt lautet: Warum sind die einzelnen
char-Arrays unterschiedlich lang?
Wenn im Code darauf sowieso keine Rücksicht genommen wird UND von vorne
herein nicht bekannt ist, welcher Command-String zugewiesen wird, dann
kann das konzeptmässig schon mal nicht funktionieren.
Es gibt natürlich Mittel und Wege, wie man sich selbst sowas wie eine
rudimentäre Speicherverwaltung auf einem einzigen char Array baut,
welches man zur Laufzeit für die einzelnen Strings aufteilt. Die Frage
ist aber: lohnt sich das?
Der Code, den du hast, wäre für mich allerdings ein Hinweis darauf, dass
der Originalprogrammierer nicht viel von String-Verarbeitung verstanden
hat. Er hat so ziemlich jedes C-'Fettnäpfchen' mitgenommen, das er
finden konnte. Der ganze Code schreit förmlich "Mein Programmierer hatte
von Stringverarbeitung nach den Regeln der Kunst keine Ahnung".
Hallo Karl Heinz,
Karl Heinz schrieb:> Avr Noob schrieb:>>>> Oder was glaubst du, wie Profis das machen?>>>> Das wuerde ich sehr gerne wissen.>> Debug Code!
Den gibt es bei mir schon. Allerdings geht das nur ueber CAN. (Beide
seriellen Schnittstellen des AT90CAN128 sind belegt, ein LCD steht mir
nicht zur Verfuegung.) Ich debugge auch schon ueber PORT Pins mit einem
Logic Analyzer.
> D.h. Sofern man keinen Debugger hat, mit dem man dem Programm zur> Laufzeit über die Schulter schauen kann.
Leider nicht.
> ....Das kann man sich alles auf einem PC mit seinen im Vergleich zum> µC weit überlegenen Debug-Möglichkeiten problemlos ansehen, entwickeln> und testen.
Das ist eine sehr gute Idee. Mit der Entwicklung fuer PC in GCC muss ich
mich wohl naeher beschaeftigen.
> Ab einem gewissen Level der verbuggt-heit, kannst du das 'kann' durch> ein 'wird' ersetzen.
Ja, habe ich schon selbst leidvoll erfahren. Leider sehen das die
Vorgesetzten nicht immer ein. Hinterher beschweren Sie sich dann aber
doch.
>> Die erste Frage, die sich stellt lautet: Warum sind die einzelnen> char-Arrays unterschiedlich lang?> Wenn im Code darauf sowieso keine Rücksicht genommen wird UND von vorne> herein nicht bekannt ist, welcher Command-String zugewiesen wird, dann> kann das konzeptmässig schon mal nicht funktionieren.
Ich stimme Dir zu. Ich werde alle auf die maximal moegliche Laenge
setzen und vor dem Kopieren diese maximale Laenge ueberpruefen.
> Es gibt natürlich Mittel und Wege, wie man sich selbst sowas wie eine> rudimentäre Speicherverwaltung auf einem einzigen char Array baut,> welches man zur Laufzeit für die einzelnen Strings aufteilt. Die Frage> ist aber: lohnt sich das?
In meinem Fall eindeutig: NEIN!
> Der Code, den du hast, wäre für mich allerdings ein Hinweis darauf, dass> der Originalprogrammierer nicht viel von String-Verarbeitung verstanden> hat. Er hat so ziemlich jedes C-'Fettnäpfchen' mitgenommen, das er> finden konnte. Der ganze Code schreit förmlich "Mein Programmierer hatte> von Stringverarbeitung nach den Regeln der Kunst keine Ahnung".
Damit hast Du vermutlich Recht. Mein Problem ist nur, dass mein
Verstaendnis auch nicht viel weiter reicht. :(
Aber Dank Eurer (und Deiner) Hilfe bin ich mir jetzt immerhin einigen
Gefahren und Schwierigkeiten bewusst und bekomme es sicherlich besser
hin.
Vielen Dank!
MfG
balze aka AVR Noob
PS:
dein 2-dimensionales String Arrays ist schon mal etwas, das ich in Frage
stelle.
Denn mit dem Kommando String alleine ist es ja nicht getan. Da hängt ja
noch mehr drann. Wird ein eingegebenes Kommando erkannt (wo auch immer
dann die Eingabe herkommt), muss ja eine zugehörige Aktion ausgeführt
werden, bzw. es wird noch andere Informationen geben, die zum Kommando
mit dazu gehören.
Da frage ich mich aber sofort: Warum reden wir die ganze Zeit von
Kommando Strings und nicht von einem Kommando in seiner Gesamtheit? Also
der Zusammenfassung von Kommando und zum Kommando gehörender
Information? Also von einem struct, der ein Kommando beschreibt?
Womit sich die Frage nach einem 2-dimensionalen char-Array insofern in
Luft auflöst, weil es das gar nicht mehr gibt. Es gibt ein Array von
'Kommandos' und Teil eines jeden Kommandos ist ein char-Array, in dem
der Kommando-Text steht.
Nach wie vor verstehe ich den Sinn der ganzen String-Kopiererei nicht.
Selbst wenn da Kommandos als Strings über den CAN-Bus reinkommen, die
später wieder ausgegeben werden sollen, müssen die ja zunächst mal
irgednwie im Speicher abgelegt werden. Das geht halt über malloc() oder
eine eigene Speicherverwaltung in einem Array.
Sobald die erst einmal im Speicher liegen, muß aber nichts mehr kopiert
werden. Da braucht es nur eine Zeigerverwaltung, die die Zeiger auf alle
vorhandenen Kommandos kennt, und den jeweils gewünschten liefert.
Dann noch dafür sorgen, daß ersetzte Kommandos gelöscht werden, und
alles wird gut.
Oliver
Hallo zusammen,
Karl Heinz schrieb:> PS:>> dein 2-dimensionales String Arrays ist schon mal etwas, das ich in Frage> stelle.>> Denn mit dem Kommando String alleine ist es ja nicht getan. Da hängt ja> noch mehr drann. Wird ein eingegebenes Kommando erkannt (wo auch immer> dann die Eingabe herkommt), muss ja eine zugehörige Aktion ausgeführt> werden, bzw. es wird noch andere Informationen geben, die zum Kommando> mit dazu gehören.> Da frage ich mich aber sofort: Warum reden wir die ganze Zeit von> Kommando Strings und nicht von einem Kommando in seiner Gesamtheit? Also> der Zusammenfassung von Kommando und zum Kommando gehörender> Information? Also von einem struct, der ein Kommando beschreibt?> Womit sich die Frage nach einem 2-dimensionalen char-Array insofern in> Luft auflöst, weil es das gar nicht mehr gibt. Es gibt ein Array von> 'Kommandos' und Teil eines jeden Kommandos ist ein char-Array, in dem> der Kommando-Text steht.
Das bringt es auf den Punkt!
Ich werde es auf ein Array von structs umstellen. Teil des structs ist
dann der Kommandotext. Das macht es dann zukuenftig auch leicher wart-
und erweiterbar.
Leider ist dieses 2 dimensionale char Array sehr tief in der Software
verwurzelt. Was auf der einen Seite viel Aufwand bedeutet, diese
AEnderung aber auf der anderen Seite unverzichtbar macht.
Oliver schrieb:> Nach wie vor verstehe ich den Sinn der ganzen String-Kopiererei> nicht.>> Selbst wenn da Kommandos als Strings über den CAN-Bus reinkommen, die> später wieder ausgegeben werden sollen, müssen die ja zunächst mal> irgednwie im Speicher abgelegt werden. Das geht halt über malloc() oder> eine eigene Speicherverwaltung in einem Array.>> Sobald die erst einmal im Speicher liegen, muß aber nichts mehr kopiert> werden. Da braucht es nur eine Zeigerverwaltung, die die Zeiger auf alle> vorhandenen Kommandos kennt, und den jeweils gewünschten liefert.>> Dann noch dafür sorgen, daß ersetzte Kommandos gelöscht werden, und> alles wird gut.>> Oliver
es gibt eine feste Anzahl von vorher definierten Kommandos. Man soll
aber von Aussen die Moeglichkeit haben, einzelne Kommandos zu
manipulieren. Also dieses eine Kommando zu ersetzen. Der Zugriff auf
dieses manipulierte Kommando soll aber wie gewohnt stattfinden.
Es gibt also keine zusaetzlichen Kommandos von Aussen, sondern nur
Ersetzungen bereits vorhandener (und unter bestimmten Voraussetzungen
verwendeter) Kommandos.
MfG
balze aka AVR Noob
Avr Noob schrieb:> Leider ist dieses 2 dimensionale char Array sehr tief in der Software> verwurzelt. Was auf der einen Seite viel Aufwand bedeutet, diese> AEnderung aber auf der anderen Seite unverzichtbar macht.
Welches?
1
char*Commands[5]
???
Das kein zweidimensonales Array, sondern schlicht ein Array von char*.
Die einzelnen Pointer können frei irgendwo in den Speicher zeigen, wo
auch immer der zugehörige String gerade abgelegt ist.
Das kann ja als "Interface" (zur Not) so bleiben, auch wenn du auf
Structs umstellst. Du musst halt in der Kommandoverwaltung die einzelnen
Pointer in dem Array so setzen, daß die fünf gewünschten
Kommando-Strings damit referenziert werden.
Diese Kommandoverwaltung, die die Strings ersetzt und die Pointer
umsetzt, usw. die gehört neu geschrieben, und möglichst mit
Zugriffsfunktionen als Modul gekapselt. Die Stellen im Restcode, die an
den Kommandos rumfummeln, musst du halt anpassen. Mit etwas Glück sind
das aber nicht viele.
Oliver
Avr Noob schrieb:> verwurzelt. Was auf der einen Seite viel Aufwand bedeutet,
wenn mich meine Intuition und Erfahrung nicht trügt, wirst du
feststellen, dass mit einem sauberen Aufbau gleich mal rund 30% des
Codes wegfallen und der übrig gebliebene Code übersichtlicher, einfacher
und besser wartbar ist, sobald das unstrukturierte Chaos erst mal
verschwunden ist. Das er dann auch noch besser funktioniert und
eventuell sogar noch mehr kann, ist dann noch das Sahnehäubchen oben
drauf :-)
Ich wuenscht ich haette Eure Erfahrung. :)
Ich werde Eure Hinweise beherzigen und die Kommandos vernuenftig
kapseln.
Das mit den Zeigern auf geaenderte Kommandos hoert sich eigentlich gut
an. Es ist aber moeglich das die Kommandos sehr oft (nicht schnell aber
oft) ersetzt werden. Mir fehlen hier Erfahrungen im Umgang mit malloc
und free. Nicht das ich den speicher damit fragmentiere und es
irgendwann nicht mehr funktioniert.
Um das kopieren komme ich sowieso nicht herum. Ich muss es ja wenigstens
aus dem CAN-Buffe in den String kopieren. Dann kann ich auch gleich den
Zielstring nehmen.
Danke Euch!
MfG
balze aka AVR Noob
Avr Noob schrieb:> Um das kopieren komme ich sowieso nicht herum. Ich muss es ja wenigstens> aus dem CAN-Buffe in den String kopieren. Dann kann ich auch gleich den> Zielstring nehmen.
Da würde ich mir jetzt erst mal keine Sorgen machen.
Wenn das vernünftig aufgebaut ist, UND sich in weiterer Folge das
Kopieren als Problem darstellt, dann kann man das immer noch ändern. Ein
sauberer Aufbau zeichnet sich dadurch aus, dass Änderungen leicht
möglich sind, ohne dass gleich der komplette Code über den Haufen
geworfen werden muss.
Einfach ein (diesmal wirklich) 2-dimensionales Array benutzen und
strncpy nehmen. Neu schreiben sollte man nur, wenn man es wirklich
besser kann. Sonst kommt nur ein anderer Murks raus.
Quack schrieb:> Einfach ein (diesmal wirklich) 2-dimensionales Array benutzen
Ah ja. Erkläre doch mal, was in C ein zweidimensionales Array wirklich
ist.. (Tip: Array aus Pointern auf Arrays..)
Karl Heinz schrieb:> ohne dass gleich der komplette Code über den Haufen> geworfen werden muss.
Ach, Karlheinz, in diesem Falle wäre ich genau _dafür_: Den ganzen Code
komplett rauszuwerfen und das Ganze grundsätzlich anders anzugehen. Ich
sehe überhaupt keinen Sinn darin, irgendwelche eigentlich konstanten
Zeichenketten irgendwo anders hinzukopieren. Dann schon eher mit Handles
arbeiten, die nur bei Bedarf einen entsprechenden String liefern.
W.S.
W.S. schrieb:> Quack schrieb:>> Einfach ein (diesmal wirklich) 2-dimensionales Array benutzen>> Ah ja. Erkläre doch mal, was in C ein zweidimensionales Array _wirklich_> ist.. (Tip: Array aus Pointern auf Arrays..)
Auch in C gibt es 2-dimensionale Arrays.
Ein Array aus Pointern auf Arrays ist zwar in der verwendenden Syntax
gleich, ist aber intern anders aufgebaut.
> Ach, Karlheinz, in diesem Falle wäre ich genau _dafür_: Den ganzen Code> komplett rauszuwerfen und das Ganze grundsätzlich anders anzugehen. Ich> sehe überhaupt keinen Sinn darin, irgendwelche eigentlich konstanten> Zeichenketten irgendwo anders hinzukopieren. Dann schon eher mit Handles> arbeiten, die nur bei Bedarf einen entsprechenden String liefern.
Wenn ich mir so ansehe, woran es beim TO hapert, dann denke ich nicht,
dass er das hinkriegt.
So oft wird er schon kein neues Kommando definieren, dass die Kopiererei
gross ins Gewicht fällt.
Eleganter wärs natürlich sich aus einem String-Pool bedienen zu können.
Das kriegst du hin, das krieg ich hin, aber ob jemand den man daran
erinnern muss, das es struct gibt und der mit Pointern auf Kriegsfuss
steht, das hin kriegt ....