Forum: Mikrocontroller und Digitale Elektronik strings mit i einem anderen string zuweisen?


von Andi (Gast)


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

von holger (Gast)


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.

von Karl H. (kbuchegg)


Lesenswert?

Andi schrieb:

> 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,

warum nicht?
Genau dafür sind Arrays gemacht worden!

von Andi (Gast)


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?

von Klaus W. (mfgkw)


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
  }

von Klaus W. (mfgkw)


Lesenswert?

Andi schrieb:
> Kann man da irgendwie über Macros arbeiten?

es geht (fast) immer eleganter als mit Makros.

von -schumi- (Gast)


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-

von holger (Gast)


Lesenswert?

Hmmm, geht das nicht auch?

  string Sel1 = "abc";
  string Sel2 = "def";
  string Sel3 = "ghi";
  string test

  for(int i=0; i<3; i++)
  {
   if(i==1) test = Sel1;
   if(i==2) test = Sel2;
   if(i==3) test = Sel3;
  }

von Klaus W. (mfgkw)


Lesenswert?

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

von Karl H. (kbuchegg)


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];

von Klaus W. (mfgkw)


Lesenswert?

Vorschlagen kannst du das, gehen wird es nicht :-)

PS: Scheint doch zu gehen?!?

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Vorschlagen kannst du das, gehen wird es nicht :-)

Was hab ich übersehen?

Macht der gcc bei derartigen Arrays mit Referenzen nicht mit?

von Klaus W. (mfgkw)


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.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:

> PS: Scheint doch zu gehen?!?

Was ist mit
1
  for( i = 0; i < 3; ++i ) {
2
    std::string & test = (std::string &[]){ Sel1, Sel2, Sel3 } )[i];
3
    ...
4
  }

also test selber acuh noch als Referenz auszuführen und somit jegliches 
Stringkopieren zu umgehen :-)

von Klaus W. (mfgkw)


Lesenswert?

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

von Karl H. (kbuchegg)


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 :-)

von Klaus W. (mfgkw)


Lesenswert?

Ich bin irgendwie nicht ganz in der Spur; daß es lt. meinem PS von
oben doch gehen sollte, kann ich nicht mehr nachvollziehen.
Vielleicht hatte ich da doch versehentlich noch die Zeigerversion 
kompiliert?

von Klaus W. (mfgkw)


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? :-)

von Klaus W. (mfgkw)


Lesenswert?

C++-gemäß könnte man natürlich auch einen std::vector von Referenzen
auf die Strings nehmen, aber das wäre vielleicht auch etwas Overkill.

von Klaus W. (mfgkw)


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.

von Karl H. (kbuchegg)


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

von Klaus W. (mfgkw)


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.)

von Karl H. (kbuchegg)


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.

von Klaus W. (mfgkw)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.