Kriegt jemand diese C#-Übung hin?

3 Antworten

Ich versuche es mal mit Pseudo-Code, vielleicht hilft dir das auf die Sprünge:

  1. String in char-Array umwandeln
  2. Leeres Dictionary anlegen
  3. Nächsten (ersten) Buchstaben des Strings finden
  4. Aktuelle Zahl (oder 0) aus dem Dictionary anhand des Buchstabens holen
  5. Zahl um eins erhöhen
  6. Veränderte Zahl zusammen mit dem Buchstaben wieder in das Dictionary einfügen
  7. Bei 3 weiter machen, bis alle Buchstaben abgearbeitet sind
Woher ich das weiß:Berufserfahrung – Software-Entwicklung (Java Enterprise)

JimmyNUTron 
Beitragsersteller
 05.02.2019, 17:41

Danke dir, jz versteh ich was man machen muss aber wie man das macht weiss ich noch nicht ganz 😌

(Bin noob)

1
   public static Dictionary<char, int> CountCharacters(string s)
        {
            
            Dictionary<char, int> buffer = new Dictionary<char, int>();
            char[] array = s.ToUpper().ToCharArray();
            for (int i = 0; i < array.Length; i++)
            {
                char c = array[i];
                if (!buffer.ContainsKey(c))
                    buffer.Add(c, 1);
                else buffer[c]++;
            }

            return buffer;
        }

Und Gott alleine weiß es am allerbesten und besser.


JimmyNUTron 
Beitragsersteller
 05.02.2019, 17:31

Hallo, danke für deine hilfe, hättest du vielleicht lust mir den code ein bisschen zu erläutern? :)

0
DieMimose  05.02.2019, 17:32
@JimmyNUTron

Ja, gerne:

Wir deklarieren ein lokales Dictionary-Objekt: Diesen geben wir zurück.

Wir konvertieren das String-Objekt in ein Array von char: Dann iteriere wir durch das Char-Array und fügen jedes nicht in der Dictionary existente Char in die Dictionary. Falls einer existiert, wird der Wert inkrementiert.

Und Gott alleine weiß es am allerbesten und besser.

1
Mikkey  05.02.2019, 20:11
@DieMimose
Und Gott alleine weiß es am allerbesten und besser.

Der wüsste wahrscheinlich, dass die Array-Umwandlung nicht erforderlich ist:

foreach (char c in s)...
0
DieMimose  05.02.2019, 21:19
@Mikkey
foreach (char c in s)...

Es ist didaktisch näherliegender for-Schleifen zu benutzen, unter anderem weil diese in diesem Sinne intuitiv nachvollziehbarer sind.

2.) Foreach-Schleifen intern sind nichts weiter als for-Schleifen mit einer - in deinem Fall- lokalen Variable c: Du hast also weder den Code lesbarer gemacht, noch in irgendeiner Weise zum Positiven modifiziert.

Im Gegenteil: For-Each-Schleifen sind perfomance-technisch nicht so effizient wie for-Schleifen: http://mdfarragher.com/2017/11/22/for-versus-foreach-in-csharp/

_

0
DieMimose  05.02.2019, 21:27
@Mikkey

Addendum: foreach konvertiert imo den String implizit auch in ein Char-Array.. müsste den IL-Code _ inspizieren.

Und Gott alleine weiß es am allerbesten und besser.

0
Mikkey  05.02.2019, 21:30
@DieMimose

Man erwartet von einem zeitgemäßen Compiler, dass er unabhängig von dem verwendeten Sprachkonstrukt optimalen Code generiert.

Im C++-Bereich ist die Verwendung von expliziten Zählschleifen total verpönt, deshalb gibt es sogar Ersetzungen , wenn man tatsächlich einen Index benötigt:

for (const auto index : boost::irange(anfang, ende))
{
    // machwas mit index
}

Was ist daran auszusetzen, einen "natürlichen Vorgang, nämlich das Durchlaufen eines Strings vom Anfang zum Ende genauso zu verwenden? Gegenüber dem "for i" würde sogar das uralte Verfahren noch mehr einleuchten:

for (char* pCh = s; *pCh; pCh++)
{
    // machwas mit *pCH
}
0
DieMimose  05.02.2019, 21:45
@Mikkey

Der IL-Code bezüglich foreach:

   IL_0000: nop
    IL_0001: ldstr"LOLOLOAAAL"
    IL_0006: stloc.0
    IL_0007: nop
    IL_0008: ldloc.0
    IL_0009: stloc.1
    IL_000a: ldc.i4.0
    IL_000b: stloc.2
    IL_000c: br.s IL_001c
// loop start (head: IL_001c)
        IL_000e: ldloc.1
        IL_000f: ldloc.2
        // ----> IL_0010: callvirtinstancechar [mscorlib]System.String::get_Chars(int32)
        IL_0015: stloc.3
        IL_0016: nop
        IL_0017: nop
        IL_0018: ldloc.2
        IL_0019: ldc.i4.1
        IL_001a: add
        IL_001b: stloc.2

Intern wird im Grunde also auch ein char-Array generiert: Es hat keinerlei Vorteile.

Die Methode .ToCharArray() generiert das Array ziemlich effizient:

   int length = Length;
        char[] array = new char[length];
        if (length > 0)
        {
            fixed (char* smem = &m_firstChar)
            {
                char[] array2 = array;
                fixed (char* dmem = array2)
                {
                    wstrcpy(dmem, smem, length);
                }
            }
        }

Es macht also keinerlei Unterschied: Was genau also möchtest du mit deinem Beitrag bezwecken?

Im C++-Bereich ist die Verwendung von expliziten Zählschleifen total verpönt, deshalb gibt es sogar Ersetzungen , wenn man tatsächlich einen Index benötigt[...]

Wie kommst du auch darauf eine unmanaged Programmiersprache mit einer managed zu parallelisieren? Du setzt völlig willkürlich Prämissen und beanstanden ausgehend davon meinen Ansatz.

for (char* pCh = s; *pCh; pCh++)
{
    // machwas mit *pCH
}

Glückwunsch: Was bringt es dem Fragesteller der neu zu sein scheint, direkt mit Pointer-Arithmetik zu konfrontieren? Und überhaupt: Pointer funktionieren in C-Sharp nur unter Verwendung des unsafe-Bezeichners, welcher Vorteil ergibt sich hierbei? Kaum, zumindest nicht für diese spezifische Problemstellung.

_

0
DieMimose  05.02.2019, 21:47
@Mikkey

Nein: Das macht keinen Sinn: Du beanstandest irgendetwas was gar nicht zu bestanden ist.

Und Gott alleine weiß es am allerbesten und besser.

0
Mikkey  05.02.2019, 21:51
@DieMimose

Dann beschränke die Beanstandung auf folgendes:

Die Aufgabe besteht darin, die Zeichen eines Strings zu verarbeiten.

Dafür ist in C# das foreach-Konstrukt vorgeehen. Es ist völlig sinnlos, einen Index zu konstruieren und mit dessen Hilfe aus dem extrahierten Array das Zeichen herauszuholen und in der lokalen variablen zu speichern, die Dir foreach ohnehin liefern würde.

Ende des Dialogs.

0
DieMimose  05.02.2019, 21:52
@Mikkey
Dafür ist in C# das foreach-Konstrukt vorgeehen. Es ist völlig sinnlos, einen Index zu konstruieren und mit dessen Hilfe aus dem extrahierten Array das Zeichen herauszuholen und in der lokalen variablen zu speichern, die Dir foreach ohnehin liefern würde.

Intern macht Foreach nahezu dasselbe (schau dir den IL-Code, oder noch spezifischer die asm Anweisung von foreach'es an): Nochmal: Was beanstandest du?

_

0
Reyha24  07.02.2019, 06:41

Ich muss Mikkey recht geben. foreach ist hier einfach eleganter und noch lesbarer.

0
DieMimose  07.02.2019, 14:54
@Reyha24

Nein und nein. Der Eindruck ist relativ. Der Vorteil bei for Schleifen ist, dass sie nahezu jede Programmiersprache in dieser Form implementiert wird. Das heißt: Sollte jemand aus anderen Programmiersprachen auf den Beitrag stoßen, wird ihm _ die Idee hinter Funktionalität direkt klar.

Wenn es um Eleganz ginge würde man das ohnehin über Linq lösen.

_

0
Woher ich das weiß:Berufserfahrung – Studium der Informatik + Softwareentwickler seit 25 Jahren.

DieMimose  05.02.2019, 17:37

Linq ist zwar schön, für didaktische Zwecke sollte man aber meines Erachtens zunächst auf "konventionelle" Erklärungsansätze zurückgreifen... fürs Erste natürlich.

So versteht man im Grunde eher, was linq im Hintergrund macht.

_

1