PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Array <-> Pointerfrage


beos
2006-05-29, 13:27:37
Ich hab da ein ganz stranges Problem

Der Code schneidet das ".c" ab.

int main(void)
{
char string[] = "datei.c";
char *ptr;
printf("\n%s\n",string);

ptr = strtok(string, ".c");
printf("\n%s\n",ptr);
return EXIT_SUCCESS;
}

Wenn ich

char string[] = "datei.c"; durch
char *string = "datei.c"; ersetzte gibt beim Aufruf der strtok Funktion einen S. Fault..

Jetzt frage ich mich warum ?
Hat einer von Euch eine Idee?

Beos

mithrandir
2006-05-29, 14:07:52
Dere!

Guckst du hier:

char *strtok(char *s1,const char *s2);

Zerlegt String s1 in 'Token', die durch Zeichen aus s2 voneinander getrennt sind. Beim 1. Aufruf muss s1 angegeben werden, bei jedem weiteren dagegen 0. An jedes Token wird das Stringende-Zeichen '\0' angehängt (s1 wird verändert!). s2 kann bei jedem Aufruf verändert werden

C ist auch schon lange her. Ich bin mir nicht mehr sicher, ob man da nicht ohnehin immer selbst das Stringendezeichen bei der Variablendeklaration mitsetzen muss.

Coda
2006-05-29, 14:08:29
beos[/POST]']Der Code schneidet das ".c" ab.
Tut er nicht. Zumindest nicht im allgemeinen Fall.

Ließ mal nochmal die Dokumentation von strtok genau. Was dein eigentliches Problem angeht weiß ich im Moment aber auch keinen Rat.

Trap
2006-05-29, 14:12:30
beos[/POST]']
char string[] = "datei.c"; durch
char *string = "datei.c"; ersetzte gibt beim Aufruf der strtok Funktion einen S. Fault..
Ein char* = literal gibt eine Konstante an und die wird dann normalerweise vom Kompiler so erzeugt, dass sie in Speicher liegt den man nicht beschreiben kann.

char[] = literal gibt ein Array mit Initialwert an.

beos
2006-05-29, 15:11:14
Coda[/POST]']Tut er nicht. Zumindest nicht im allgemeinen Fall.

Ließ mal nochmal die Dokumentation von strtok genau. Was dein eigentliches Problem angeht weiß ich im Moment aber auch keinen Rat.

In diesen einen Fall enthält ptr den Filenamen ohne ".c"
Nur dieses eine Token interessiert mich.

beos
2006-05-29, 15:13:48
Trap[/POST]']Ein char* = literal gibt eine Konstante an und die wird dann normalerweise vom Kompiler so erzeugt, dass sie in Speicher liegt den man nicht beschreiben kann.

char[] = literal gibt ein Array mit Initialwert an.

Hmmm...in sämtlichen C Büchern steht, dass ein Array nichts anderes als ein eindimensionaler Pointer ist.

Desweitern kann ich ja den char * Pointer zur Laufzeit umbiegen, sodass (meiner Meinung nach) nicht von einer Konstanten geredet werden kann...?!

Coda
2006-05-29, 15:57:43
beos[/POST]']Hmmm...in sämtlichen C Büchern steht, dass ein Array nichts anderes als ein eindimensionaler Pointer ist.
Es gibt aber sehr wohl Unterschiede wie du gerade bemerkst ;)

Trap
2006-05-29, 16:38:27
beos[/POST]']Desweitern kann ich ja den char * Pointer zur Laufzeit umbiegen, sodass (meiner Meinung nach) nicht von einer Konstanten geredet werden kann...?!
Ein Zeichenkettenliteral ist eine Konstante und wird vom Compiler im nur-lesen-Speicher abgelegt. Wenn man schreibt char* x=literal bekommt man einen Pointer auf diese Konstante (den Pointer selbst kann man natürlich umbiegen). Wenn man schreibt char x[]=literal bekommt man ein neues auf dem Stack erzeugtes Array das mit dem Literal initialisiert wird.

beos
2006-05-29, 19:14:06
Erst mal danke für Eure Antworten.

Leider helfen sie mir gar nicht weiter.....

Ist ja auch ne tolle Sache...die Deklaration der Funktion erwartet expliziet einen
char Pointer.......dass man dann aber effektiv nur ein Array nehmen kann ist echter Unsinn (wer arbeitet denn mit Array's und nicht mir Pointern)?

Aqualon
2006-05-29, 19:29:49
Du kannst einen char* nehmen, nur musst du auch für strtok beschreibbaren Speicher allokieren.


int len = 31337; //oder wielange die Dateinamen auch immer sein mögen
char* foo = (char *)malloc(len*sizeof(char));
char* ptr = strtok(foo, ".c");
So sollte das auch gehen.

Aqua

Xmas
2006-05-29, 19:47:25
beos[/POST]']Ist ja auch ne tolle Sache...die Deklaration der Funktion erwartet expliziet einen
char Pointer.......dass man dann aber effektiv nur ein Array nehmen kann ist echter Unsinn (wer arbeitet denn mit Array's und nicht mir Pointern)?
Da hast du etwas falsch verstanden, natürlich kann man einen Pointer nehmen, nur muss dieser auf einen veränderbaren Speicherbereich zeigen.

// Die folgenden beiden Zeilen sind identisch
// und erzeugen jeweils einen uninitialisierten Pointer auf char
char * text1;
char text1[];

// Lässt man den Pointer dann auf ein Stringliteral zeigen...
text1 = "text";

// ...sollte man den String nicht verändern, das führt in der
// Regel zu einer Speicherschutzverletzung. Denn Literale befinden
// sich im Datensegment, und das ist gewöhnlich nicht zum
// Schreiben freigegeben.
text1[0] = 'T'; // FEHLER!

// Die folgenden beiden Zeilen sind identisch
// und erzeugen jeweils ein initialisiertes Array
// von 5 char auf dem Stack
char text2[5] = "text";
char text2[] = "text;

// Verändern ist erlaubt, da sich das Array auf dem Stack befindet
text2[0] = 'T'; // OK


// Die folgenden Zeilen sind NICHT identisch
char text3[] = "text";
char * text3 = "text";


Aber du verwendest strtok auch falsch.
char dateiname[] = "abc.c";
strtok(dateiname, ".c");
Ersetzt nämlich das c in abc.c durch \0. Der zweite Parameter ist nämlich eine Liste von Trennzeichen, die im String gesucht werden sollen. Es wird also nach dem ersten Vorkommen von '.' oder 'c' in abc.c gesucht.