strings mit i einem anderen string zuweisen?

Gast #1875145
Lesenswert?

Hi,

hab ein kleines C++ Problem; vielleicht könnt ihr mir ja weiterhelfen 
:-)
1
string Sel1; 
2
string Sel2; 
3
string Sel3; 
4

5
for(int i=1; i<=3; i++) 
6
{ 
7
   string test = Sel[i]; 
8
}

Ich möchte, dass der String test abhängig vom i-Wert den Wert von Sel1, 
Sel2, Sel3 in der for-Schleife zugewiesen wird. Möchte aber kein 
String-Array verwenden, sondern wirklich drei individuelle Strings. Ist 
das möglich?

Gruß
Andi
Gast #1875152
Lesenswert?

>Ich möchte, dass der String test abhängig vom i-Wert den Wert von Sel1,
>Sel2, Sel3 in der for-Schleife zugewiesen wird. Möchte aber kein

Was für ein Quatsch!
Selbst wenn es funktionieren würde, hätte test am Ende der
Schleife den Inhalt von Sel3.
Gast #1875160
Lesenswert?

hab das Beispiel sehr stark vereinfacht, im normalen Beispiel kann ich 
es nicht als Array deklarieren.

holger schrieb:
> Selbst wenn es funktionieren würde, hätte test am Ende der
> Schleife den Inhalt von Sel3.

das ist in diesem Fall richtig, soll aber auch nur eine Demo sein, mehr 
nicht.

Kann man da irgendwie über Macros arbeiten?
#1875162
Lesenswert?

Mal vorausgesetzt, es macht prinzipiell Sinn, und das obige
Beispiel ist sinnentstellend auf ein Minimum reduziert, um
uns nicht unnötig zu belasten (das ist wirklich positiv
gemeint), geht so etwas über einen kleinen Umweg mit Zeigern:
1
  std::string Sel1 = "abc";
2
  std::string Sel2 = "def";
3
  std::string Sel3 = "ghi";
4

5
  for(int i=0; i<3; i++)
6
  {
7
    std::string *p_strarr[] = { &Sel1, &Sel2, &Sel3 };
8

9
    std::string test = *(p_strarr[i]);
10

11
    std::cout << "test=" << test << std::endl;
12
  }
Gast #1875170
Lesenswert?

Hi :-)

So lang sich die Zahl der einzellnen Strings in grenzen hält würde ich 
die select case - Funktionsweise benutzen, also:

select case i
{
case 1
text = sel1;
break;
case 2
text = sel2
break;
... usw.

ansonsten nimm ein zweidimensionales Array, also z.b.
strings[2][0] bis strings[2][15] währe ein 14 Zeichen String in der 2. 
Zeile
strings[4][0] bis strings[4][28] währe ein 25 Zeichen String in der 4. 
Zeile

Nachteil:
Wenn du einen langen String und sonst lauter kurze hast wird jede Menge 
Speicherplatz verschwendet

Was besseres fällt mir gerade nicht ein...

MfG
-schumi-
#1875188
Lesenswert?

Klaus Wachtler schrieb:
> Nachtrag zu meinem Vorschlag:
> Der g++ lässt schändlicherweise auch folgendes zu:
>
1
>     std::string test = *( (std::string *[]){ &Sel1, &Sel2, &Sel3 } )[i];
2
>

:-)
Prinzipiell ist die Idee gut. Anstelle von Pointern würde ich allerdings 
Referenzen vorschlagen um die Syntax zu vereinfachen
1
    std::string test = (std::string &[]){ Sel1, Sel2, Sel3 } )[i];
#1875199
Lesenswert?

Als temporäre Variable scheint es tatsächlich zugehen.
Ein Feld von Referenzen als normale Variable geht dagegen nicht:
t.cpp:40: error: declaration of ‘strarr’ as array of references

Daß es in dem freifliegenden Konstrukt ohne Variable geht, erschüttert 
mich doch etwas.
Naja, man lernt nie aus.
#1875212
Lesenswert?

Klaus Wachtler schrieb:
> Also das hier ist nicht legal:
>
1
>     std::string &test = ( (std::string &[]){ Sel1, Sel2, Sel3 } )[i];
2
>
> t.cpp:44: error: creating array of references

Schade :-(

trotzdem werde ich das Gefühl nicht los, dass wir hier nach einer 
trickreichen Lösung für das falsche Problem suchen.
Insgeheim denke ich mir, die Lösung besteht darin ganz einfach eine 
Funktion zu bauen:

Aus
1
string Sel1; 
2
string Sel2; 
3
string Sel3; 
4

5
for(int i=1; i<=3; i++) 
6
{ 
7
   string test = Sel[i]; 
8

9
   mach was mit test
10
}

wird
1
string Sel1; 
2
string Sel2; 
3
string Sel3; 
4

5
  foo( Sel1 );
6
  foo( Sel2 );
7
  foo( Sel3 );
8

9
...
10

11
void foo( std::string& test )
12
{
13
  mach was mit test
14
}

simpel, einfach, leicht zu durchschauen und doch geschmacklos :-)
Was soll es für einen Sinn haben, erst kompliziert ein Array 
einzuführen, nur damit man innerhalb der Schleife dann ein Element 
auswählen kann? Durch das Array gewinnt man hier nichts. Nicht an 
Einfachheit, nicht an Wartbarkeit. Es sieht einfach nur kompliziert aus, 
und das kanns ja wohl nicht sein.

Und das ein Array von vorneherein nicht möglich ist: Das glaub ich erst 
wenn ich es sehe. Wenn jemand nach einer Makrolösung für dieses Problem 
fragt, dann trau ich ihm nicht weiter, als mein Compiler Fehlermeldungen 
werfen kann :-)
#1875216
Lesenswert?

Karl heinz Buchegger schrieb:
> simpel, einfach, leicht zu durchschauen und doch geschmacklos :-)

Über das geschmacklos will ich mich nicht äußern, aber es
trifft -glaube ich- nicht die Fragestellung.
Er will doch irgendwie über die Strings iterieren und nicht die drei
foo() untereinander schreiben.
Wie willst du jetzt for( ... ) foo( ... ) schreiben?

Wer war das noch, der neulich bei einem BASIC-Freund angemäkelt hat,
daß er alles untereinander schreibt, statt eine Schleife zu nehmen?
Hieß der nicht auch Buchegger? :-)
#1875228
Lesenswert?

Karl heinz Buchegger schrieb:
> Und das ein Array von vorneherein nicht möglich ist: Das glaub ich erst
> wenn ich es sehe.
1
#include <iostream>
2
#include <string>
3
int main( int nargs, char **args )
4
{
5
  std::string Sel1 = "abc";
6
  std::string Sel2 = "def";
7
  std::string Sel3 = "ghi";
8

9
  for(int i=0; i<3; i++)
10
  {
11
    std::string &test = ( (std::string &[]){ Sel1, Sel2, Sel3 } )[i];
12
    std::cout << "test=" << test << std::endl;
13
  }
14
}
1
klaus@vdr2:~ > g++ -Wall t.cpp && ./a.out
2
t.cpp: In function ‘int main(int, char**)’:
3
t.cpp:11: error: creating array of references
4
...

Es erscheint mir auch logisch, mit etwas Nachdenken.
Ein Feld ist eine Folge von Elementen, die im Speicher
hintereinander liegen.

Die drei Strings liegen aber nicht hintereinander, höchstens zufällig.
Wenn jedes Feldelement aber eine Referenz ist, kann man die
Elemente, die im Regelfall irgendwo liegen, nicht mehr in das Feld
zwingen.

Das war mir auch nicht bewußt, aber ich finde es nachvollziehbar.
#1875229
Lesenswert?

Klaus Wachtler schrieb:

> Über das geschmacklos will ich mich nicht äußern, aber es
> trifft -glaube ich- nicht die Fragestellung.
> Er will doch irgendwie über die Strings iterieren und nicht die drei
> foo() untereinander schreiben.

Schon.
Aber was bringt es ihm, wenn er die Iteration krampfhaft in eine 
Schleife packt. Wenn ein neues Element dazukommt, muss er Hand anlegen, 
automatisch geht da nichts.

> Wer war das noch, der neulich bei einem BASIC-Freund angemäkelt hat,
> daß er alles untereinander schreibt, statt eine Schleife zu nehmen?
> Hieß der nicht auch Buchegger? :-)

Tuschee :-)

Ist aber eine andere Situation.
Die Lösung die ich als erstes präferieren würde, wäre:
keine Einzelvariablen sondern von vorne herein gleich Arrays.

Wenn das wirklich nicht möglich wäre, dann bei kleinen Anzahlen ein Loop 
Unrolling machen und die Funktion für jede Einzelvariable einzeln 
aufrufen. Bei größerem i dann ein Pointer-Array und ev. Funktionsaufruf
#1875234
Lesenswert?

Ja, aber dazu müsste man mehr vom Programm wissen.
Ich fürchte, wir haben ihn jetzt eh schon verjagt :-)

(Mit meiner Erklärung von eben, warum es nicht mit Referenzen geht, ist 
natürlich auch der Vorschlag mit std::vector< std::string & > gestorben;
für den gilt dasselbe.
Ich habe es eben probiert, das passt dem g++ auch nicht.)
#1875238
Lesenswert?

Klaus Wachtler schrieb:
> Ja, aber dazu müsste man mehr vom Programm wissen.
> Ich fürchte, wir haben ihn jetzt eh schon verjagt :-)

Yep.
Ich denke immer noch, das hier eigentlich das falsche Problem gelöst 
wird.

> (Mit meiner Erklärung von eben, warum es nicht mit Referenzen geht, ist
> natürlich auch der Vorschlag mit std::vector< std::string & > gestorben;
> für den gilt dasselbe.
> Ich habe es eben probiert, das passt dem g++ auch nicht.)

Das ist klar, das kann nicht gehen. Weil Referenzen ja initialisiert 
werden müssen. Und das bringt man nicht an std::vector durch.
#1875244
Lesenswert?

Aber nochmal zu dem temporären Feld:
Die aktuellen Implementationen von std::string verwenden
meines Wissens doch sowieso "copy on write", d.h. das
Initialisieren von neuen Strings mit vorhandenen geht schnell
und billig. Eine echte Kopie würde erst angelegt werden, wenn
man einen String ändert (könnte man mit einem const sogar
zuverlässig verhindern).

D.h. man kann den Vorschlag von oben nehmen, und auf die
Referenz verzichten, ohne daß es langsamer wird.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren