Forum: PC-Programmierung 2D array if statement


von Peter (Gast)


Lesenswert?

Hi

Ich habe folgendes Array definiert:
1
char compare[5][2]={
2
  {'a', '1'},
3
  {'e', '2'},
4
  {'i', '3'},
5
  {'o', '4'},
6
  {'u', '5'}
7
}

ich möchte nun die Variabel x überprüfen of sie a,e,i,o oder u beträgt, 
und den entsprechenden in der 2. Spalte im array Wert zuweisen.

momentan habe ich es so gelöst:
1
for (int i=0; i<5; i++)
2
{
3
  if (x== compare[i][0])
4
  {
5
      x = compare[i][1];
6
  }
7
}


geht dies auch einfacher zu lösen ohne jedesmal mit einer for Schleife 
das ganze array zu durchforsten?

von leo (Gast)


Lesenswert?

Peter schrieb:
> geht dies auch einfacher zu lösen ohne jedesmal mit einer for Schleife
> das ganze array zu durchforsten?

$ man bsearch

leo

von A. S. (Gast)


Lesenswert?

Wenn der erste wert beliebig angeordnet ist, dann nicht.

Sonst ja.

Und alles kann man für Speed oder size optimieren.

Beitrag #5960159 wurde von einem Moderator gelöscht.
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Die Klasse std::map ist genau dafür gemacht:
1
#include <map>
2
#include <iostream>
3
4
int main () {
5
  std::map<char, char> compare {  {'a', '1'},
6
                  {'e', '2'},
7
                  {'i', '3'},
8
                  {'o', '4'},
9
                  {'u', '5'}};
10
  
11
  int x = 'e';
12
  auto iter = compare.find (x);
13
  if (iter != compare.end ()) {
14
    x = iter->second;
15
  }
16
  
17
  std::cout << static_cast<char>(x) << std::endl;
18
}

sie enthält eine Menge an Schlüssel-Wert-Zuweisungen. Man kann prüfen ob 
ein Wert enthalten ist und den abgebildeten Wert abfragen. Das 
Abfragen/Prüfen hat eine logarithmische Laufzeit, und ist damit 
schneller als die lineare Suche im Ausgangspost. Bei nur 5 Einträgen ist 
aber vermutlich der Overhead noch zu groß als dass das sinnvoll wäre.
Es gibt auch noch std::unordered_map mit durchschnittlich konstanter 
Laufzeit.

https://en.cppreference.com/w/cpp/container/map
https://en.cppreference.com/w/cpp/container/unordered_map

von Dirk B. (dirkb2)


Lesenswert?

Peter schrieb:
> geht dies auch einfacher zu lösen ohne jedesmal mit einer for Schleife
> das ganze array zu durchforsten?

du kannst bei einem Match (die Bedingung vom if ist wahr) die Schleife 
abbrechen.

von KeinMathematiker (Gast)


Lesenswert?

Niklas G. schrieb:
> Die Klasse std::map ist genau dafür gemacht:#include <map>
> #include <iostream>
>
> int main () {
>   std::map<char, char> compare {  {'a', '1'},
>                   {'e', '2'},
>                   {'i', '3'},
>                   {'o', '4'},
>                   {'u', '5'}};
>
>   int x = 'e';
>   auto iter = compare.find (x);
>   if (iter != compare.end ()) {
>     x = iter->second;
>   }
>
>   std::cout << static_cast<char>(x) << std::endl;
> }


Bekommt man sowas auch auf einem uC zum laufen oder ist die Lib nur für 
x86?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

KeinMathematiker schrieb:
> Bekommt man sowas auch auf einem uC zum laufen oder ist die Lib nur für
> x86?

Die C++ Standard Library ist an sich portabel, aber z.B. der AVR-G++ 
liefert sie nicht mit. Die dynamischen Standard-Container wie std::map 
sind vom Speicherverbrauch her aber nicht so für Mikrocontroller 
geeignet. Es war aber auch gar nicht nach uC gefragt, und das hier ist 
das PC-Programmieren-Forum...

Wenn es aber wirklich nur 5 Bytes sind ist die lineare Suche, oder 
einfach 5 Vergleiche, oder ein switch-case vermutlich schneller. Dank 
Cache ist der Arrayzugriff viel schneller als eine Baumstruktur in 
std::map.

Vielleicht lässt sich auch eine lustige bitweise Berechnung machen, die 
die 5 Vergleiche auf einmal macht. Die 5 Werte zu einem 64bit-Integer 
zusammenbauen, das x 5x hintereinander in einen Integer packen, XOR auf 
beide Werte, und dann das 0-Byte finden.

von A. S. (Gast)


Lesenswert?

Peter, Du müsstest schon etwas über Kontext und Anwendung schreiben. 
Sonst geht z.B. auch sowas:
1
char *vokale="aeiou";
2
char *p =strchar(vokale, x);
3
 
4
    if(p)
5
    {
6
        x=(vokale-p)+'1';
7
    }
Macht für Dich aber höchstwahrscheinlich wenig Sinn.

von Wilhelm M. (wimalopaan)


Lesenswert?

Peter schrieb:
> Hi
>
> Ich habe folgendes Array definiert:
>
1
> char compare[5][2]={
2
>   {'a', '1'},
3
>   {'e', '2'},
4
>   {'i', '3'},
5
>   {'o', '4'},
6
>   {'u', '5'}
7
> }
8
>
>
> ich möchte nun die Variabel x überprüfen of sie a,e,i,o oder u beträgt,
> und den entsprechenden in der 2. Spalte im array Wert zuweisen.
>
> momentan habe ich es so gelöst:
>
1
> for (int i=0; i<5; i++)
2
> {
3
>   if (x== compare[i][0])
4
>   {
5
>       x = compare[i][1];
6
>   }
7
> }
8
>
>
>
> geht dies auch einfacher zu lösen ohne jedesmal mit einer for Schleife
> das ganze array zu durchforsten?

Das iterative Suchen kannst Du mit einer vollständigen LUT vermeiden 
(s.a. Variante1).

Statt einer Iteration über eine Teilbereichs-LUT kann Du auch eine Folge 
von Alternativen (if-statements) verwenden. Mit etwas TMP ist diese 
Folge von if-statements auch automatisch abhängig von der Größe Deine 
LUT (s.a. Variante 2).

1
#include <iostream>
2
#include <array>
3
#include <numeric>
4
#include <algorithm>
5
6
struct Converter1 {
7
    inline static auto transformVowel(const char c) {
8
        return lut[c];
9
    }
10
private:
11
    inline static const auto lut = []{
12
        std::array<char, 256> lut{};
13
        std::iota(std::begin(lut), std::end(lut), char{0});
14
        lut['a'] = '1';
15
        lut['e'] = '2';
16
        lut['i'] = '3';
17
        lut['o'] = '4';
18
        lut['u'] = '5';
19
        return lut;
20
    }();
21
};
22
23
struct Converter2 {
24
    inline static char constexpr transformVowel(const char c) {
25
        return [&]<auto... II>(std::index_sequence<II...>){
26
            char r{c};
27
            (((c == lut[II].first) ? (r = lut[II].second) : c), ...);
28
            return r;
29
        }(std::make_index_sequence<std::size(lut)>{});
30
    }
31
private:
32
    inline static constexpr std::array<std::pair<char, char>, 5> lut{{{'a', '1'}, {'e', '2'}, {'i', '3'}, {'o', '4'}, {'u', '5'}}};
33
};
34
35
36
int main(){
37
    std::string result;
38
    std::string text{"Dies ist ein Test.\n"};
39
    
40
    // Variante 1
41
    std::transform(std::begin(text), std::end(text), std::back_inserter(result), Converter1::transformVowel);
42
43
    // Variante 2
44
    std::transform(std::begin(text), std::end(text), std::back_inserter(result), Converter2::transformVowel);
45
46
    std::cout << result;
47
}

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.