Forum: Mikrocontroller und Digitale Elektronik Lib Roland Riegel, Dateinamen hochzählen lassen


von Anna (Gast)


Lesenswert?

Hallo,

ich arbeite schon ein paar Wochen mit der Lib von Roland Riegel, bisher 
habe ich für alle Probleme Threads gefunden, die mir geholfen haben, 
aber diesmal nicht.

Wenn ich eine Datei erstelle muss ich den Dateinamen als ein const char 
übergeben
1
uint8_t fat_create_file(struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry)

Ich möchte den Dateinamen hochzählen lassen.

Name_0
Name_1
Name_2...

Mit den Funktionen itoa, strcpy und strcat komme ich auch zu einen char, 
der den gewünschten Dateinnamen enthält.
Weil der Übergabeparameter aber ein const char ist bekomme ich meinen 
Dateinamen (Name_0,...) nicht in den const char.

Laut Google gibt es wohl noch const_cast aber das nur für C++. Ich 
programmiere in C.

Ich bin doch bestimmt nicht die erste, die mit der Lib von Roland Riegel 
fortlaufende Dateinamen erstellen möchte. Wie habt ihr das gelöst?
Ich hoffe Ihr könnt mir helfen.

Gruß
Anna

von Peter II (Gast)


Lesenswert?

Anna schrieb:
> Mit den Funktionen itoa, strcpy und strcat komme ich auch zu einen char,
> der den gewünschten Dateinnamen enthält.
> Weil der Übergabeparameter aber ein const char ist bekomme ich meinen
> Dateinamen (Name_0,...) nicht in den const char.

dann zeig mal wie du es gemacht hast, denn ein char* kann immer in ein 
const char* verwandlet werden.

von holger (Gast)


Lesenswert?

>Wie habt ihr das gelöst?

Mach doch einfach das const weg.

von Peter II (Gast)


Lesenswert?

holger schrieb:
> Mach doch einfach das const weg.

das macht nun überhaupt keinen sinn.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Anna schrieb:
> const char* file
Das bedeutet nur, dass der Inhalt vom String, worauf file zeigt, von 
der Funktion nicht geändert wird.

> Ich programmiere in C.
Und welchen Fehler bekommst du? Wie sieht deine Deklaration und wie 
sieht deine funktion aus?

von Rolf M. (rmagnus)


Lesenswert?

Anna schrieb:
> Weil der Übergabeparameter aber ein const char ist bekomme ich meinen
> Dateinamen (Name_0,...) nicht in den const char.

Warum nicht? Welche Fehlermeldung kommt denn?

> Laut Google gibt es wohl noch const_cast aber das nur für C++.

Das ist für die umgekehrte Richtung, also wenn man ein const wegcasten 
möchte.

von Anna (Gast)


Lesenswert?

Der Autor wird sich bei dem const was gedacht haben, deswegen würde ich 
das ungern einfach weglassen.

Mein Code
1
int main(void)
2
{
3
    uint8_t a = 1;
4
    char dateiname[6] = "Name_";
5
    char dn_hochzaehlen[4];
6
  
7
    const char filename[11];
8
  
9
    itoa(a,dn_hochzaehlen,10);
10
    strcpy(filename, dateiname);
11
    strcat(filename, dn_hochzaehlen);
12
  
13
}

a ist die Variable die ich hochzählen lassen möchte. das hochzählen ist 
hier nicht mit dabei.

Fehler:
strcpy und strcat meckern, dass statt einem "char*" ein "const char*" 
kommt

Laut Bib sind beide Funktionen so definiert:
1
extern char *strcpy(char *, const char *);
2
extern char *strcat(char *, const char *);

Lasse ich bei Varibale
1
 const char filename[11];
das const weg funktioniert es.

Es ist auch logisch, dass es nicht funktioniert. Ein const char sollte 
nunmal konstant sein und sich nicht verändenr lassen. Ich würde nur 
ungern alle Dateinamen per hand eingeben.

Gruß
Anna

von Anna (Gast)


Lesenswert?

@ Peter II
Das ist mir klar. Mir geht es darum, dass ich keinen string in einen 
const char kopieren kann. Zumindest nicht so wie ich es probiere:)

von ga st (Gast)


Lesenswert?

Anna schrieb:
> Lasse ich bei Varibale
>
1
>  const char filename[11];
2
>
> das const weg funktioniert es.
Dann lass es so. Ob die Funktion jetzt einen char oder einen const char 
will ist egal, notfalls wird halt automatisch konvertiert (char -->const 
char).

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Anna schrieb:
> Lasse ich bei Varibale
>   const char filename[11];
> das const weg funktioniert es.
Dann lass es weg, denn der filename ist nicht konstant!
Du bastelst ja dran herum (fortlaufende Nummer)...  :-o

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Also:

Einer Funktion, die "const char*" erwartet, kann man sowohl "const 
char*" als auch "char*" übergeben.

Beides ist vollkommen legal und provoziert keine Warnungen.

Das "const" bedeutet hier nur, daß die Funktion das Argument nicht 
verändert.

Andererseits kann man einer Funktion, die "char *" erwartet, nicht 
"const char*" übergeben.

Das nämlich ist nicht zulässig und wird mit entsprechenden 
Fehlermeldungen quittiert.

Das Nichtvorhandensein von "const" bedeutet hier, daß die Funktion das 
Argument verändern kann.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Codepad hat da erst beim Umschalten auf C++ Probleme mit dem const:
http://codepad.org/ihqV2luf

von Anna (Gast)


Lesenswert?

Also weglassen funktioniert nicht einfach so. dann bekomme ich den 
Fehler, dass fat_create_file ein "char*" erwartet aber ein "const char*" 
bekommt. Das muss ich jetzt nicht verstehen:)

Danke für die Antworten, besonders von Rufus. Ich werde mich nochmal 
genauer mit dem const beschäftigen (bin ja noch Anfänger:) )und mich bei 
Fragen nochnal melden.

von Anna (Gast)


Lesenswert?

So nochmal Danke.

Es funktioniert wenn ich bei der Deklaration des "filename" das const 
einfach wegglassen wie mehrere geschrieben haben.

Ich habe die DEfinition von const wohl missverstanden.

von Martin H. (marrtn)


Lesenswert?

Nachdem Dein Dateiname nicht konstant ist ("raufzählen"), darf er auch 
nicht const deklariert werden:
1
char* filename[11];

Deine Lib erwartet allerdings einen konstanten String, also casten:
1
fat_create_file(&parent, (const char*) filename, &dir_entry);

In diese Richtung char* --> const char* darf man ruhig casten.

Einfach immer vor Augen halten, was der Compiler/Linker damit macht.
 - "Deklaration mit const" --> Flash
     --> nicht (ohne weiteres) veränderbar.
 - "Deklaration ohne const" --> RAM
     --> veränderbar.

Lustig wird's dann erst, wenn das const nicht ganz vorne steht...

von Anna (Gast)


Lesenswert?

Danke dür die Erklärung.

Dann hoffe ich mal, dass es bei mir traurig bleibt... ;)

von Peter II (Gast)


Lesenswert?

Martin H. schrieb:
> Deine Lib erwartet allerdings einen konstanten String, also 
casten:fat_create_file(&parent, (const char*) filename, &dir_entry);
> In diese Richtung char* --> const char* darf man ruhig casten.

darf ja, aber man muss nicht. Das macht der compiler schon selber. Der 
Cast ist nicht notwendig und sogar fehlerhaft wenn sich mal der type von 
filename ändert. (z.b. Wchar)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Martin H. schrieb:
> Einfach immer vor Augen halten, was der Compiler/Linker damit macht.
>  - "Deklaration mit const" --> Flash
>      --> nicht (ohne weiteres) veränderbar.
>  - "Deklaration ohne const" --> RAM
>      --> veränderbar.

Naja, gerade beim hier so beliebten AVR ist das nicht so, da muss man 
erheblichen Aufwand treiben, um was ins Flash zu bekommen, ohne daß es 
im RAM gespiegelt wird.

von Karl H. (kbuchegg)


Lesenswert?

Martin H. schrieb:

> Deine Lib erwartet allerdings einen konstanten String

NEIN!


Bitte, bitte, bitte.

Lernt mit const umzugehen.

Das const an dieser Stelle
1
uint8_t fat_create_file(struct fat_dir_struct* parent,
2
                        const char* file,
3
                        struct fat_dir_entry_struct* dir_entry)

bedeutet:

Junge, ich will von dir an dieser Stelle einen Pointer auf Charcater 
haben. Aber: Ich mache dir die Zusicherung, dass ich diese Character als 
nicht veränderlich ansehe. Das heißt: ich werde mich nicht an den 
Charactern vergreifen und sie verändern. Du kannst also von der Annahme 
ausgehen, was immer mir du mir hier als String fütterst, der String wird 
nach dem Funktionsaufruf immer noch der gleiche sein wie vorher. Ich 
werde noch nicht einmal den Versuch einer Änderung unternehmen. Das 
heißt: ich werde auch nicht hergehen und den String mal kurz verändern 
und dann wieder in die Ursprungszustand zurückversetzen. Ich benutze den 
String wirklich und in jedem einzelnen Fall nur lesend.

Das ist die Bedeutung von const an dieser Stelle:

Die Funktion macht eine Zusicherung!

Und das ist immer so in Argumentlisten: Mit einem const macht die 
Funktion eine Zusage an den Aufrufer: Ich werde das Angegebene nicht 
verändern.
Ein const in einer Arumgentliste fordert niemals eine Eigenschaft vom 
Aufrufer ein, sondern die Funktion sichert damit eine bestimmtes 
Verhalten zu!


Und daher ist es völlig legitim, wenn ich an dieser Stelle der Funktion 
ein char Array übergebe. Denn die Funktion versucht nicht das Argument 
zu verändern. Es ist auch völlig legitim, wenn ich an dieser Stelle ein 
Stringliteral angebe. Denn auch hier: Die Funktion versucht nicht den 
String zu verändern.

   char fileName[20];
   ...
   fat_create_file(..., fileName, ... );

ist also gültig.
Aber auch


   fat_create_file(..., "meinFile.txt", ... );

ist gültig.

Wenn die Funktion, die Zusicherung nicht machen würde:

1
uint8_t fat_create_file(struct fat_dir_struct* parent,
2
                        char* file,
3
                        struct fat_dir_entry_struct* dir_entry)

dann wäre letzteres
1
   fat_create_file(..., "meinFile.txt", ... );

nämlich nicht zulässig! Das es das trotzdem ist, liegt nicht an Logik, 
sondern daran, dass dafür in C bei der Einführung von const explizit 
eine Ausnahme für char* - const char*  zugelassen wurde.


Das ganze ist ein bischen wie:
Mein Kumpel sichert mir zu, dass er in dem Buch dass ich ihm leihe, 
nicht herumkritzeln wird.
Also kann ich ihm bedenkenlos sowohl mein Malbuch als auch meine 
Gutenbergbibel geben. Bei meinem Malbuch ist es mir egal, ob er drinn 
rumkritzelt, bei der Gutenbergbibel aber nicht.
Macht er mir aber diese Zusicherung nicht, dass er das Buch als const 
betrachten wird, dann werd ich einen Teufel tun und ihm die 
Guttenbergbibel geben.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Guttenbergbibel
Kein Problem. Er macht vor dem Kritzeln eine Kopie davon, aber sagt es 
keinem...   :-o

von Rolf M. (rmagnus)


Lesenswert?

Anna schrieb:
> So nochmal Danke.
>
> Es funktioniert wenn ich bei der Deklaration des "filename" das const
> einfach wegglassen wie mehrere geschrieben haben.
>
> Ich habe die DEfinition von const wohl missverstanden.

Ja. Bei einem const char* bedeutet das const erstmal nur, daß über 
diesen Zeiger der Wert nicht verändert wird. Es bedeutet nicht, daß 
der Wert ursprünglich schon konstant sein muß.

Martin H. schrieb:
> Nachdem Dein Dateiname nicht konstant ist ("raufzählen"), darf er auch
> nicht const deklariert werden:char* filename[11];

Richtig.

> Deine Lib erwartet allerdings einen konstanten String, also casten:

Unsinn. Ein cast ist da völlig überflüssig.

von Anna (Gast)


Lesenswert?

Ich hatte const auch so verstanden, dass meine Funktion einen 
konstanten/nicht veränderlichen char möchte.

Nach den teils sehr eindrucksvollen Erklärungen bin ich wieder mal ein 
ganzes Stückchen schlauer:)

von Karl H. (kbuchegg)


Lesenswert?

Der Fairness halber muss man auch sagen, dass es AVR-Compiler gibt, die 
ihr eigenes Süppchen mit 'const' kochen. Und das ist schade, denn es 
bedeutet, dass sie damit in diesem Punkt ein vom C-Standard abweichendes 
Verhalten haben.
Besser wäre es gewesen, wenn sie für die angestrebte Funktionalität 
einen eigenen Modifier, zb ala 'flash' oder 'rom' eingeführt hätten. So 
aber, und das muss man leider so nennen, haben sie aus keinem guten 
Grund heraus eine ganz klare Fehlentscheidung getroffen.

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.