Engeschlichener Indexteufel [Fehler gefunden]



  • Hallo!

    Im Zuge eines Softwarepraktikums für die Uni soll ich ein Programm schreiben, das die Vigenerechiffre knackt.

    Ich hänge bei dem Punkt im Programm, wo ich annehme, ich kenne bereits die Schlüssellänge. Nun zerlege ich den Text in die 'Schlüssellänge'-viele Streifen und ermittle den häufigsten Buchstaben in jedem Streifen (dabei zuerst die häufigkeit jedes einzelnen Buchstaben, die ich dann zur Kontrolle ausgebe).

    Nun muss sich irgendwo einen Indexteufel eingeschlichen habe, den ich partout nicht finde. Und zwar stimmen die Buchstabenhäufigkeiten des letzten Streifens (i = keylength - 1) bei jedem Zeichen mit denen des vorletzten Streifens überein. Zumindest gaukelt mir das meine Ausgabe vor.
    Vlt. sieht jemand auf den ersten Blick den Fehler?

    Ich poste der Übersicht halber nur die Funktion, von der ich spreche.

    Ich bin jedem dankbar, der Zeit, Lust und Nerven hat, sich meinen dilettantischen Programmierversuch anzusehen und entschuldige mich im Voraus für verursachte Augenkrebsleiden.

    void caesar( string text, int keylength)
    {
    
        int i, j, k, max, ind, count;                  // 'max' = Vergleichswert zur Maximumsfindung in Frequency, count dient zum Überspringen von 'keylength'-Buchstaben
        char c;
        int intkey[keylength];                  // Speicher Rückverschiebeindizes, um den Text anschließend mit der Fkt crypt zu dechiffrieren
        char key[keylength];
        vector<int> frequency(26);
    
    /* Count zählt hier 'keylength' "Buchstaben" ab, da alle anderen Zeichen nicht verschoben wurden.
       Nur so lässt sich hier der Text in jene Streifen zerlegen, die auch mit dem selben Schlüssel verschoben wurden */
    
        for ( i = 0; i < keylength; i++)
        {
    
            for(k = 0; k < 26; k++)
                frequency[k] = 0;
    
            j = i;
    
            while( j < text.length() )
            {
                c = text.at(j);
                if('a' <= c && c <= 'z')
                {
                    frequency[int(c) - 97] = frequency[int(c) - 97] + 1;
                }
    
                else if('A' <= c && c <= 'Z')
                {
                    frequency[int(c) - 65] = frequency[int(c) - 65] + 1;
                }
    
                count = 0;
    
                while ( count < keylength)
                {
                    if( ('a' <= text.at(j) && text.at(j) <= 'z') || ('A' <= text.at(j) && text.at(j) <= 'Z'))
                        count++;
                    j++;
    
                    if(j >= text.length())
                        break;
                }
    
            }
    
            max = 0;
    
            for( j = 0; j < 26 ; j++)
            {
                cout << i <<" f " << j << " = " << frequency[j] << endl;
                if (frequency[j] > max)
                {   max = frequency[j];
                    ind = j;
                }
            }
    
    }
    


  • #include <locale>
    #include <vector>
    
    namespace detail
    {
      template<std::size_t a_z_diff, std::size_t A_Z_diff>
      std::size_t get_index_for_char(char value)
      {
        switch(value)
        {
          case 'a':
          case 'A':
            return 0;
          /*...*/
    
          case 'z':
          case 'Z':
          default:
            return 25;
        }
      }
    
      template< >
      std::size_t get_index_for_char<25, 25>(char value)
      {
        if('a' <= value && value <= 'z')
          return value-'a';
    
        return value-'A';
      }
    
    }
    
    std::size_t get_index_for_char(char value)
    {
      return detail::get_index_for_char<'z'-'a', 'Z'-'A'>(value);
    }
    
    std::vector< std::vector<std::size_t> > get_frequency( const std::string& text, std::size_t keylength)
    {
      std::vector< std::vector<std::size_t> > frequency(keylength, std::vector<std::size_t>(26));
      std::size_t at = 0;
    
      for(std::size_t i=0; i != text.size(); ++i)
      {
        char c = text[i];
        if(!::isalpha(c))
          continue;
    
        if(at == keylength)
          at = 0;
        ++frequency[at][get_index_for_char(c)];
        ++at;
      }
    
      return frequency;
    }
    
    #include <iostream>
    
    int main()
    {
    	std::size_t keylength = 3;
    	std::vector< std::vector<std::size_t> > f = get_frequency("asdasdfghsdf", keylength);
    
    	for(std::size_t i(0); i != keylength; ++i)
    	{
    		std::cout << i << ':' << std::endl;
    		for(std::size_t j(0); j != 26; ++j)
    		{
    			std::cout << f[i][j];
    			if((j+1)%4)
    				std::cout << '\t';
    			else
    				std::cout << std::endl;
    		}
    		std::cout << std::endl;
    	}
    
    	system("PAUSE");
    }
    

    deine lsg. hat nicht mal kompiliert - als ich dann aber endlich die fehlende klammer gefunden hatte, hatte es auch die erwartete ausgabe:

    #include <string>
    #include <vector>
    #include <iostream>
    
    using namespace std;
    
    void caesar( string text, int keylength)
    {
    
        int i, j, k, max, ind, count;                  // 'max' = Vergleichswert zur Maximumsfindung in Frequency, count dient zum Überspringen von 'keylength'-Buchstaben
        char c;
    #if 0 /*geht nicht, weil nicht konstant - vrmtl eine gcc-erweiterung*/
    	int intkey[keylength];                  // Speicher Rückverschiebeindizes, um den Text anschließend mit der Fkt crypt zu dechiffrieren
        char key[keylength];
    #endif
        vector<int> frequency(26);
    
    /* Count zählt hier 'keylength' "Buchstaben" ab, da alle anderen Zeichen nicht verschoben wurden.
       Nur so lässt sich hier der Text in jene Streifen zerlegen, die auch mit dem selben Schlüssel verschoben wurden */
    
        for ( i = 0; i < keylength; i++)
        {
    
            for(k = 0; k < 26; k++)
                frequency[k] = 0;
    
            j = i;
    
            while( j < text.length() )
            {
                c = text.at(j);
                if('a' <= c && c <= 'z')
                {
                    frequency[int(c) - 97] = frequency[int(c) - 97] + 1;
                }
                if('A' <= c && c <= 'Z')
                {
                    frequency[int(c) - 65] = frequency[int(c) - 65] + 1;
                }
    
                count = 0;
    
                while ( count < keylength)
                {
                    if(('a' <= text.at(j) && text.at(j) <= 'z') || ('A' <= text.at(j) && text.at(j) <= 'Z'))
                        count++;
                    j++;
    
                    if(j >= text.length())
                        break;
                }
    
            }
    
            max = 0;
    
            for( j = 0; j < 26 ; j++)
            {
                cout << i <<" f " << j << " = " << frequency[j] << endl;
                if (frequency[j] > max)
                {
    				max = frequency[j];
                    ind = j;
                }
            }
    	} //!
    } 
    
    int main()
    {
    	caesar("asdasd", 3);
    
    	system("PAUSE");
    }
    

    funktionierte so, wie ich mir das dachte...

    bb



  • Hallo! 🙂

    Ich danke dir für deine Mühen!
    Die Funktion 'isalpha' muss ich mir merken - mensch, wenn ich die vorher gekannt hätte. ^^

    Seltsam, dass es nicht übersetzbar war - hatte ich wohl zu viel rausgestrichen.

    In der Zwischenzeit habe ich auch einen Fehler gefunden und alles nochmal umgeschrieben. Bei mir haute es nicht hin, wenn zwei Nicht-Buchstaben am Anfang des Textes aufeinanderfolgten, da somit 'j' in die selbe Spur rutschte und folglich die selbe Ausgabefolge erzeugte.

    Vielen Dank nochmal! 🙂


Log in to reply