Hallo
Wie könnte ich mir diese Anzahl offen lassen und soviele
Strings verketten, wie über scanf während der Laufzeit
eingelesen werden?
Das sind ja zwei verschiedene Sachen.
- beliebige String-Anzahl über scanf einlesen
- gelesene Strings verketten
Einlesen über scanf ist so eine Sache,
Nicos hat richtig angemrkt, dass man das
nicht in richtigem Code macht - allerdings
bin ich der Meinung, dass man es trotzdem
können können sollte
Scanf liefert jedes „gescannte“ Feld zurück,
indem es dieses auf einen (bereitgestellten)
Zeiger kopiert, also:
char \*str1, \*str2, \*str3;
scanf( "%s %s %s", str1, str2, str3 );
Letzendlich werden die zeiger „von rechts nach links“
auf den Stack gelegt (C-Konvention), so dass str1 „oben“
und str3 „unten“ steht.
Wenn man jetzt ein Feld von Zeigern
char \*vielezeiger[SEHRVIELE]
genauso auf den stack bekommen würde:
scanf( "%s %s %s", vielezeiger );
könnte man hinterher die gescannten Felder
in vielezeiger[0], vielezeiger[1] usw.
erhalten. Das geht in C/C++ nicht, weil
Arrays [] grundsätzlich nur per Startadresse
übergeben werden, scanf(…) würde also
scheitern, da lediglich ein Zeiger auf den
Stack gelegt wird, die Variable „vielezeiger“.
Wir wollen aber SEHRVIELE Zeiger auf dem
Stack haben, also müssen wir das Array in
eine Struct kapseln, da diese „by value“,
also komplett auf den Stack geht:
struct { char \*vielezeiger[SEHRVIELE]; } kapsel;
scanf( "%s %s %s", kapsel );
Natürlich muss man die konkreten Zeiger,
in die etwas kopiert werden soll, entsprechend
mit Speicher ausreichender Größe versehen.
Ich hab mal ein lauffähiges Beispiel gebastelt,
welches unter Win/Dos gehen sollte (unter Unix-shell
nicht, so lange F6 aka CTRL-Z aka „end of stream“
bereits von der Shell belegt ist.
Da scanf so viele Elemente konvertieren möchte,
wie es Formatzeichen findet, muss man es hier
explizit auffordern, damit aufzuhören (F6 ENTER):
#include "assert.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define MAXARGS 128
#define MAXARGLEN 128
typedef struct { char \*zeile[MAXARGS]; } PTSTRUCT;
// - - - - - - - - - - - - - - - - - - - - - - - - - - //
void prepare\_scanf\_ride(PTSTRUCT\* pztab, char\*\* format, char item[])
{
int i;
\*format = malloc( (strlen(item)+1) \* MAXARGS \* sizeof(char) );
assert(\*format != 0);
(\*format)[0] = '\0';
for(i=0; izeile[i] = malloc( (MAXARGLEN+1) \* sizeof(char) );
assert( pztab-\>zeile[i] != 0 );
}
}
void cleanup\_scanf\_mess(PTSTRUCT\* pztab, char\*\* format)
{
int i;
for(i=0; izeile[i] );
free( \*format );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - //
int main(int argc, char\*argv[])
{
int i, nfelder;
char\* format;
PTSTRUCT zeilenzeigerer;
prepare\_scanf\_ride(&zeilenzeigerer, &format, "%s");
printf("Worte eingeben, (Abschluss mit F6 [CTRL-Z] - ENTER)\n$\> ", MAXARGS);
nfelder = scanf(format, zeilenzeigerer);
printf("ok, das waren %d Dinge\n", nfelder);
for(i=0; i %s\n", i+1, zeilenzeigerer.zeile[i]);
cleanup\_scanf\_mess(&zeilenzeigerer, &format);
return 0;
}
Grüße
CMБ