[C] variablen String an Pointer übergeben

Hallo Forum,

ich hab jetzt nach ner zeit wieder angefangen programme für den PC zu schreiben und stehe jetzt vor einem Problem:

ich wollte mal ein programm schreiben bei dem man einen Dateinamen von einer datei die im selben ordner ist wie das programm eingeben muss. von dieser datei werden dann ein paar daten abgerufen.

hier mal das Programm:

Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

char b[5];
char i[21];
int cntr, cntr2;
struct stat dateiInfo;
int retWert;

int readname (void)
{       
         fflush(stdin);
         system ("cls");
         printf("Dateinamen eingeben: ");
         gets(i);
         for(cntr=0; i[cntr] != '\0'; cntr=cntr+1){}
         char a[cntr];
         for(cntr2=0; cntr2<=cntr; cntr2=cntr2+1)
         {
                a[cntr2]=i[cntr2];                   
         }
         char * pfad = "[COLOR="Red"]Hier muss der String aus dem Array a rein[/COLOR]";
         retWert = stat (pfad, &dateiInfo);
         system("pause");
         check();
}

int check (void)
{        
         if (retWert < 0)
         {
            fflush(stdin);
            system("cls");
            printf ("Datei nicht vorhanden\n");
            printf ("erneut Versuchen ? (ja/nein) ");
            gets(b);
            if (b[0] == 'n' && b[1] == 'e' && b[2] == 'i' && b[3] == 'n') {return 0;}
            else if (b[0] == 'j' && b[1] == 'a') {readname();}
            else {printf("Ungueltige Eingabe: Programm wird beendet"); sleep(1000); return 0;}
         }
         else {writedata();}
}

int writedata (void)
{
    printf("Erstellt am:\t%s\n", dateiInfo.st_ctime);
    printf("Letzte Änderung:\t%\n", ctime(&dateiInfo.st_mtime));
    printf("Groesse:\t%ld\ Bytes\n\n", dateiInfo.st_size);
    system("pause");
}

int main (void)
{    
    readname();
    return 0;   
}

ich hab die Stelle Rot markiert wo der string rein muss. aber ich will nicht den pointer auf 'a' richten sonder wirklich nur den string übergeben, da der pointer ja dann auf die datei zeigen soll...

MfG Julian ! :D
 
Zuletzt bearbeitet:
o_O

aaaaalso, damit ich das richtig verstehe:

du hast ein char array fixer größe (i) und läst dahin mit gets() einen null-terminierten string einlesen (punkt1: gets() == sqrt(evil) ... stell dir mal vor ich gebe mehr zeichen ein als dein char array groß ist ... eieiei)

danach zählst du manuell nach wie lang dein string nun wirklich ist (punkt2: jetzt neu: "Das Rad"... wie??? gibts schon?)

danach holst du dir ein char array der gerade ermittelten größe und kopierst da zeichen für zeichen deinen string rein, aber nicht den null-terminator...

nun möchtest du den "string"(es ist keiner mehr, da der null terminator fehlt) aus "a" als pfad für die stat() funktion verwenden, aber willst keinen pointer auf "a"


ein pointer auf das erste element von "a" würde hier sowieso nicht funktionieren, da dein string nicht null-terminiert ist ... folglich würde die stat() funktion ab dem ersten zeichen in "a" lesen, bis die nächste null kommt, also vermutlich weit über die grenzen deines arrays hinaus ... das kann gut gehen (im sinne von "kein direkter crash"), oder aber auch in einer access-violation enden (crash) ... jedenfalls tut das vermutlich nicht das was du dir erhoffst...

ich frage mich weswegen du "a" überhaupt anlegst, also was du mit einem string ohne null-terminator willst...

"i" sollte einen null-terminierten string enthalten (mal davon ausgehend dass nicht der puffer überläuft, und irgendwas anderes zwischenzeitlich drüber schreibt ...), demnach sollte ein pointer auf das erste element von "i" das sein was du suchst ...

zudem fällt auf, dass du funktionsparameter scheinbar nicht magst, und lieber globale variablen nimmst ...
 
ich hab halt schon lange nichts mehr für den PC programmiert, nur für microcontroller und da auch in eine etwas andere richtung...

ich hab da aus meinem c-buch ein beispiel genommen und so verändert, dass man den dateinamen erst eingeben muss, und nicht wie vorher im programm festlegen musste.

zu dem dass \0 dann fehlt: das soll ja so sein, der soll nicht mit übergeben werden (so wie ich das verstanden habe funktioniert das dann nicht mehr)

das mit kein pointer auf a war so gemeint, dass der nicht auf die adresse von a zeigen soll sondern auf die datei, dessen name in a steht.


[EDIT]
hab jetzt mal readname() so verändert:
Code:
int readname (void)
{       
         fflush(stdin);
         system ("cls");
         printf("Dateinamen eingeben: ");
         gets(i);
         char * pfad = "%s", i;
         retWert = stat (pfad, &dateiInfo);
         system("pause");
         check();
}
funktioniert aber auch nicht (vll weil das array komplett übergeben wird aber der string nicht so lang ist ? )

MfG Julian
 
Zuletzt bearbeitet:
Ich würde dir empfehlen dich nochmal mit den Grundlagen von C zu beschäftigen, das, was du da versuchst sieht sehr wüst aus

Code:
char *filename = (char*)malloc(_MAX_PATH);
if(NULL == filename) return 1;

fgets(filename, _MAX_PATH, stdin);

struct _stat fileStat;
if( _stat(filename, &fileStat) != 0 )
{
    printf("Fehler %d: %s", errno, strerror(errno));
    return 2;
}

return 0;
 
Zuletzt bearbeitet von einem Moderator:
also die kleinen grundlagen, also das formaleund die grundfunktionen, sind eigentlich drinnen aber mit strukturen, unionen und so (auch Malloc, das du verwendet hast, hab ich zwar gehört, weis aber nicht was das sein soll) kenn ich mich nicht aus.
 
zu dem dass \0 dann fehlt: das soll ja so sein, der soll nicht mit übergeben werden (so wie ich das verstanden habe funktioniert das dann nicht mehr)
wo steht das?
das mit kein pointer auf a war so gemeint, dass der nicht auf die adresse von a zeigen soll sondern auf die datei, dessen name in a steht.
die datei, oder besser gesagt ihr inhalt liegt zum fraglichen zeitpunkt nicht im addressraum (sie ist nicht im RAM, und auch nicht gemapped) ... das ändert erst ein fopen() call oder ähnliches
funktioniert aber auch nicht (vll weil das array komplett übergeben wird aber der string nicht so lang ist ? )
ein kleiner exkurs zum thema c strings ...

ein string in diesem sinne ist eine reihe von zeichen, daher auch der name zeichenkette, die nacheinander im speicher stehen.

Die sequenz wird immer durch \0 terminiert, um das ende des strings zu markieren.

"array of char" und "pointer auf einen string" sind daher beides pointer auf das erste element, also das erste zeichen

beim lesen eines strings, wird gelesen bis man auf den \0 terminator trifft ... fehlt der, wird üblicherweise munter weitergelesen bis ein null byte kommt, dass für den terminator gehalten wird... das hat zur folge, dass ein fehlender null terminator einen string erheblich verlängern kann...
unteranderem auch mal so um das eine oder andere GB an daten die zufälligerweise hinter dem string stehen

für das bestimmen der länge eines strings gilt selbiges ... es wird der null terminator gesucht

es ist daher unerheblich ob du für ein "Hallo Welt!" die bei ASCII minimalen 12 chars an speicher dafür geholt hast, oder 100 ... ob da hinter dem \0 noch platz ist, oder direkt andere daten stehen ist egal, in der regel haben funktionen wie srtlen() oder stat() keinerlei ahnung davon... die interessiert es nichtmal wenn du nur 10 chars alloziert hättest, also du schon 2 zeichen über die puffergrenze geschrieben hast ...


wenn du einer funktion ein array übergibst, dann weiß diese funktion nicht wie groß das array ist ... sofern du ihr die größe nicht auch als parameter mitteilst, oder in deinen datenstrukturen sowas als metadaten mitführst ... nativ gibts das nicht. genau das ist auch das problem bei gets():

Code:
char buffer[100];
gets(buffer);
sieht ok aus? ... was ist wenn ich 100 zeichen eingebe? ... mit null-terminator sinds dann 101 ... brauchst du das was da möglicherweise hinter dem buffer steht noch? ... falls das auf dem stack liegt, wäre dann da auch irgendwo deine rücksprungadresse ... du willst nicht, dass benutzereingaben da drüber schreiben können ... gets() hat keine ahnung wie groß der puffer speicher ist, auf den es schreibt ... es würde auch munter flockig 1000 zeichen da hin schreiben ...

fgets() ist eine alternative die dieses problem nicht hat (siehe beispiel von Thunderb0lt), da du angeben musst wieviele zeichen maximal in den puffer kopiert werden dürfen ... hier würde zwar die benutzereingabe abgeschnitten, aber es gibt keinen bufferoverflow
 
Zurück
Oben