Dynamischer String in C



  • C** schrieb:

    Stört es dich, dass ich mir die Mühe nicht machen will, die IDE umzustellen???

    an der ide musste nix rumschrauben. einfach nur deine quelltexte mit der endung .c versehen. dann brauchste auch keine unsinnigen casts mehr.
    🙂



  • +fricky schrieb:

    C** schrieb:

    Stört es dich, dass ich mir die Mühe nicht machen will, die IDE umzustellen???

    an der ide musste nix rumschrauben. einfach nur deine quelltexte mit der endung .c versehen. dann brauchste auch keine unsinnigen casts mehr.
    🙂

    Danke!

    P.S.: Einen Gruss an Tim, dessen Post ich immernoch nicht "checke"?



  • Wenn du mit malloc()/realloc() verkehrst, dann vergess nicht mit free() zu schlafen!



  • abgesehen davon, dass du auf funktionen wie _kbhit() etc. verzichten kannst, das bekommst du auch mitm standard hin, eine frage: warum reservierst du immer nur ein byte?

    wäre vielleicht besser, wenn du das feld um einen faktor (z.b. 1.5) erweiterst?

    ich glaube (!) mal was gelesen zu haben, dass in java die strings auch so intern erweitert werden. korrigiert mich, wenn ich falsch liege 🙂



  • hando schrieb:

    ich glaube (!) mal was gelesen zu haben, dass in java die strings auch so intern erweitert werden. korrigiert mich, wenn ich falsch liege

    strings on Java sind 'fest', die können nicht erweitert werden. sowas wie "hallo" + "doof" z.b. erzeugt einen dritten string.
    🙂



  • Ist das hier eine annehmbare Lösung um einen eingegebenen String in ein von der Grösse her zugeschnittenes Array zu speichern? Oder geht das auch anders und eleganter?
    Ich wollte eig. gerade einen eigenen Tread aufmachen.

    Bei meinen Ideen musste ich die eingabe bevor ich den Speicher alloziiere dann immer doch erst in einem ausreichend großen statischen Array zwischenspeichern!



  • Nein, der Code ist nicht gut

    1. die Verwendung von realloc ist gefährlich und man sollte den Rückgabewert nicht casten! http://www.c-plusplus.net/forum/viewtopic.php?t=206606
    2. byteweise Speicher zu allozieren ist langsam und ungeschickt
    3. conio.h, _kbhit und _getch, sytem("CLS") sind kein Teil von ANSI C und [u]nicht[/c] portabel!
    4. sizeof(char) ist sowieso immer 1, daher ist es unnötig



  • Hallo Rüdiger

    Zu 1,2 und 4 muss ich sagen: Ich wusste das entweder bereits, oder dein Einwand leuchtet mir immerhin ein.

    Wie ich allerdings Zeichenweise in ANSI-C einlesen könnte (3) ist mir ein Rätsel. Ich denke ohne getch() und kbhit() geht das gar nicht, oder?



  • als hilfestellung:

    int c = 0, n = 0;
    char buf[100];
    
    while( ( c = fgetc( stdin ) ) != EOF ) {
       /* kopiere c nach b an indexstelle n, erhoehe n um 1 */
    }
    

    jetzt kannst du das ganze mit malloc / realloc halt noch dynamischen machen. such dir nen faktor, allokiere speicher mit dem faktor. ist der speicherbereich aufgebraucht, realloc array erneut um faktor etc.

    aber nicht byte für byte. das ist zu aufwändig wie rüdiger schon sagte 🙂

    @fricky: okay dann sind die strings in java wohl scheinbar doch fest, danke für den hinweis 🙂



  • Also muss man dann doch immer realloc benutzen wenn man dea Array direkt passend groß machen will!?

    Ehh Hando? Meinst du mit b in deinem Codebeispiel Buffer?



  • Balu Jr. schrieb:

    Also muss man dann doch immer realloc benutzen wenn man dea Array direkt passend groß machen will!?

    Nicht unbedingt, auch malloc/free Kombinationen sind denkbar.
    Zur Eingabe fällt mir folgendes ein:
    Soviel ich weiß, sind die Konsolenpuffer für die Eingabe begrenzt. Die Größe des Puffers ist mit BUFSIZ in stdio.h definiert.
    Du kannst dir die Größe anzeigen lassen:

    printf("%d", BUFSIZ);
    

    Da es i.d.R. keine großen Speicherbereiche sind, ist das meiner Meinung nach einfachste Vorgehen, diesen Speicherbereich zu reservieren und dann per realloc auf die tatsächliche Größe anzupassen:

    char* coninput()
    {
    	char *t = NULL,  *s = malloc(BUFSIZ);
    	if ( s == NULL)
    		return NULL;
    	if ( NULL == fgets(s, BUFSIZ, stdin))
    		return NULL;
    	if( NULL == (t = realloc(s, strlen(s)+1)))
    		return s;
    	return t;
    }
    

    Gruß,
    Mr. C



  • Balu Jr. schrieb:

    Also muss man dann doch immer realloc benutzen wenn man dea Array direkt passend groß machen will!?

    Ehh Hando? Meinst du mit b in deinem Codebeispiel Buffer?

    ähem ja sorry ... ersetze b durch buf oder umgekehrt 🙂

    und ja, wenn du dynamisch mit speicher arbeiten willst (malloc/realloc), dann musst das feld jedes mal dann vergrößern wenn es für deine eingelesenen zeichen zu knapp wird; also mitzählen wieviel du schon verbraucht hast - und bedenke am schluss noch ein zeichen für \0 anzufügen.

    es ging hier nur um das realloc um jeweils ein byte. das ist ungeschickt. wie gesagt...nimm dir dafür immer einen faktor um den du das feld vergrößerst 🙂



  • Dann könnten bei einem 100er Buffer aber immer noch 99 Byte verschenkt werden, oder!? Nur vom Prinzip her... dann hab ich das durch euch nämlich echt gut verstanden! 👍 🙂

    while( ( c = fgetc( stdin ) ) != EOF )
    

    Da ersetze ich das EOF durch '\n'. Dann wird hallt bis zu dem Enter, was am Ende der Eingabe für fgetc eh gedrückt werden muss eingelesen. Wo wäre hier denn der EndofFile?



  • Balu Jr. schrieb:

    Dann könnten bei einem 100er Buffer aber immer noch 99 Byte verschenkt werden, oder!? Nur vom Prinzip her... dann hab ich das durch euch nämlich echt gut verstanden! 👍 🙂

    also mal angenommen du hast ein feld char* buf = malloc( 10 ); , das befüllst du jetzt mit werten und wenn es eng wird mitm platz: erweitern um faktor 1.5 (beispielsweise; hier einfach mal nach unten gerundet auf ganze zahlen). zum verständnis:

    10 * 1.5 = 15 -> buf = realloc( buf, 15 )
    15 * 1.5 = 22 -> buf = realloc( buf, 22 ) etc.
    22 * 1.5 = 33
    33 * 1.5 = 49
    49 * 1.5 = 73
    73 * 1.5 = 109
    109 * 1.5 = 163
    ...
    

    (wenn ich mich jetzt nicht verrechnet hab)
    also du erweiterst deinen 100er buffer nicht immer um 100; auch möglich, aber ich bevorzuge die andere methode 🙂

    Balu Jr. schrieb:

    Da ersetze ich das EOF durch '\n'. Dann wird hallt bis zu dem Enter, was am Ende der Eingabe für fgetc eh gedrückt werden muss eingelesen. Wo wäre hier denn der EndofFile?

    du kannst auch direkt innerhalb der while-schleife testen:

    if( c == '\n' ) {
       /* mache was, wenn enter gedrueckt wurde */
    }
    

    eof wäre in dem fall z.b. ein stream-ende oder ein fehlerfall.


Anmelden zum Antworten