mikrocontroller.net

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


Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

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

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


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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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:
  std::string Sel1 = "abc";
  std::string Sel2 = "def";
  std::string Sel3 = "ghi";

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

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

    std::cout << "test=" << test << std::endl;
  }

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andi schrieb:
> Kann man da irgendwie über Macros arbeiten?

es geht (fast) immer eleganter als mit Makros.

Autor: -schumi- (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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-

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
  }

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

PS: Scheint doch zu gehen?!?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:

> PS: Scheint doch zu gehen?!?

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

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Also das hier ist nicht legal:
>
>     std::string &test = ( (std::string &[]){ Sel1, Sel2, Sel3 } )[i];
> 
> 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
string Sel1; 
string Sel2; 
string Sel3; 

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

   mach was mit test
} 

wird
string Sel1; 
string Sel2; 
string Sel3; 

  foo( Sel1 );
  foo( Sel2 );
  foo( Sel3 );

...

void foo( std::string& test )
{
  mach was mit test
}

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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? :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

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

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

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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.