Array zufällig ausgeben; Array mit 8 Bit als Byte speichern



  • Hallo,
    vorweg erstmal: Ich bin erst seit einiger Zeit dabei, mit C zu programmieren und habe daher noch nicht viel Wissen oder Fertigkeit ansammeln können. Vielleicht benötigt es also das ein oder andere Wort mehr, um mir was zu erklären :).

    Meine aktuellen Probleme sind die folgenden:
    Erstens möchte ich ein Array ausgeben, das nur Nullen und Einsen enthält. Das Array hat genau 8 Elemente, die ich nun gern zu einem Byte (im ASCII-Code) zusammenfügen würde.
    Beispiel:
    |0|1|1|0|0|0|1|1| --> c
    Mein bisher einziger Einfall war der Umweg über eine Datei-Ausgabe mit anschließendem Einlesen der Datei in 8er-Blöcken. Aber das kostet Zeit und ist ziemlich hässlich - ich hoffe mal, da gibt es einen besseren Weg.

    Mein zweites Problem betrifft ebenfalls ein Array: Ich habe ein Array beliebiger Länge und mit beliebigem Inhalt (sehr wahrscheinlich Zahlen 😉 ). Ich würde das Array nun gern in eine Datei schreiben, jedoch sollte der Zufall dabei mitspielen:
    Ich möchte kein Element des Arrays zweimal auslesen, sondern jedes genau einmal. Die Reihenfolge des Auslesens sollte allerdings vollkommen zufällig sein.
    Sinn der letzten Sache ist es sozusagen, das Array "gut durchzumischen". Falls das geht oder ein anderer Weg möglich ist, wäre ich für Vorschläge sehr dankbar.



  • Stiefel2000 schrieb:

    Mein bisher einziger Einfall war der Umweg über eine Datei-Ausgabe mit anschließendem Einlesen der Datei in 8er-Blöcken.

    Falls du vorhast, einzelne Bits in die Datei zu schreiben und sie als Byte wieder auszulesen: Das geht so nicht. Man kann nur ganze Bytes (chars) oder größeres in Dateien schreiben.

    Bits zusammensetzen macht man am besten, indem man die einzelnen Bits an die richtige Stelle shiftet und verodert:

    unsigned int array[8] = {0,1,1,0,0,0,1,1};
    unsigned char c = 0;
    for (int i = 0; i < 8; i++)
        c |= array[i] << i;
    

    Aber aufpassen, dass die Reihenfolge nicht gerade andersrum ist als du denkts.

    Sinn der letzten Sache ist es sozusagen, das Array "gut durchzumischen". Falls das geht oder ein anderer Weg möglich ist, wäre ich für Vorschläge sehr dankbar.

    Mischen geht per Fisher-Yates-Shuffle. Du bestimmst mit rand() % laenge einen zufälligen Array-Index, verwendest das Element dort, füllst die entstandene Lücke mit dem letzten Element des Arrays, und verringerst die Arraylänge um eins.



  • Ich werd's gleich testen, ich hoffe aber, dass das "<<" kein C++-Befehl ist, ich nutze nämlich momentan nur C.
    Das mit dem Mischen des Arrays klingt auch noch etwas "nebulös": Ich kenne nämlich bisher nur den realloc()-Befehl, um die Größe eines dynamischen Arrays zu ändern. Den kann ich allerdings hier nicht nutzen, da er ja einfach ein Array der gewünschten Größe irgendwo im Speicher erstellt und den Pointer auf Element 1 ändert. Damit wäre ja der Inhalt des gesamten Arrays verloren.

    Auf jeden Fall erstmal vielen Dank für die Hilfe, hoffentlich klappt es :).

    EDIT: Nach ein wenig lesen finde ich die Binär-Operatoren doch sehr interessant, davon hatte ich vorher leider keine Ahnung. Ich frage mich nur gerade, ob das Verschieben eines Bits in der Variable nicht auch alle anderen verschiebt? (ich musste gerade feststellen, dass auf diesem PC noch keine Programmierumgebung installiert ist, es dauert also noch ein wenig, bis ich testen kann) Oder wird das Bit erst "in Position gebracht" und dann addiert?



  • Stiefel2000 schrieb:

    Ich werd's gleich testen, ich hoffe aber, dass das "<<" kein C++-Befehl ist, ich nutze nämlich momentan nur C.

    das ist ein astreiner C-befehl. a<<b heisst 'schiebe a um b bitpositionen nach links'. unter C++ dagegen kann << alles mögliche heissen.
    🙂



  • Hab's eben beim Suchen rausgefunden. Ich kannte die Pfeile nämlich auch nur aus C++, die Arbeit damit konnte um einiges leichter sein, als die C-Syntax zu nutzen :). Aber jetzt nutze ich C, schon aus Prinzip 🙂



  • Stiefel2000 schrieb:

    Ich kannte die Pfeile nämlich auch nur aus C++, die Arbeit damit konnte um einiges leichter sein, als die C-Syntax zu nutzen

    meinst du cout << blah? das ist nur in einfachen fällen so. c++ coder nehmen auch lieber 'boost:format' als cout
    🙂



  • Wo ich gerade mal dabei bin, letztens hatte ich folgendes Problem:
    Ich wollte einen Variablen Dateinamen als Speicherort für Ausgaben angeben wollen. Also ähnlich diesem:

    FILE * Datei=("C:\Irgendwas\Ziel"+x+".txt", "w");
    

    Ich habe meine Software leider noch nicht zur Verfügung, kann also nicht nachschauen - aber so in etwa sollte es gewesen sein. Gibt es für dieses Problem eine Lösung? Ich habe unzählige Methoden ausprobiert, diverse Operatoren durchgetestet. Leider hat aber nichts gefruchtet.

    EDIT: Ich habe jetzt noch Gelegenheit gehabt, den Tipp von namespace invader auszuprobieren, leider scheint bei der Konvertierung in Byte irgendetwas schief zu laufen. Mir bleibt wohl nichts anderes übrig, als mal den Quelltext zu posten:

    Eingabewort ist: "Zack!", von Hand in Binärcode umgewandelt und vom Array aufsammeln lassen (das sieht so aus: 0101101001100001011000110110101100100001)

    short Binärfeld[40]; /*Hier sind schon die Bits gespeichert*/
    short Ausgabe[8]={0};
    int AusgabePuffer=0;
    FILE * Ziel = fopen("C:/Ziel.txt" , "w");
    
    int i,k=0;
    for(i=0;i<40;i++)
    {
    	if(k==8)
    	{
    		for(k=0;k<8;k++)
    		{
    			AusgabePuffer = AusgabePuffer | Ausgabe[k] << k;
    		}
    		fprintf(Ziel,"%c",AusgabePuffer);
    		k=0;
    	}
    	Ausgabe[k]=Binärfeld[i];
    	k++;
    }
    fclose(Ziel);
    

    Als Ausgabe bekomme ich jetzt nicht "Ziel!", sondern "ZÞÞÞ" - scheinbar sind alle weiteren Binär-Chars durch ASCII 222 ersetzt wurden.
    Ich vermute mal, dass da ein Logikfehler drin ist - vielleicht beim Laufindex k. Falls jemand was sieht, wäre es nett, wenn er mir auf die Sprünge hilft.

    Ergänzung: Ich habe vergessen zu erwähnen: Wenn ich den Inhalt des Binärfeldes ausgeben lasse, dann sind alle 40 Bits an ihrem Platz. Das Problem tritt also später auf. Noch ist mir nichts aufgefallen. 😞



  • Stiefel2000 schrieb:

    Wenn ich den Inhalt des Binärfeldes ausgeben lasse, dann sind alle 40 Bits an ihrem Platz. Das Problem tritt also später auf. Noch ist mir nichts aufgefallen.

    probier mal dies:

    void main()
    {
      char bin[] = "0101101001100001011000110110101100100001";
      int s;
      char c = 0;
    
      for (s=0; s<sizeof(bin); s++)
      {
        c = (c<<1) + bin[s] - '0';  // -'0' weglassen, wenn du keine ascii-werte, sondern echte zahlen hast
        if ((s+1)%8 == 0)
        {
          putchar(c);
          c = 0;
        }
      }
    }
    

    🙂



  • Ausgabe ist in diesem Fall "Š‘“›Q". Aber zumindest kommt kein Zeichen mehr doppelt vor, ich werde mal noch weiter probieren.

    EDIT: Sowas aber auch! Ich habe mal die "- '0'" weggelassen, jetzt wird endlich "Zack!" ausgegeben. Allerdings muss ich gestehen, dass ich durch den Quelltext jetzt nicht mehr ganz durchblicke... Kann mal jemand die Zeile erklären, in der die Bits geschoben werden?



  • Stiefel2000 schrieb:

    Kann mal jemand die Zeile erklären, in der die Bits geschoben werden?

    erst wird das ergebnis eins nach links geschoben und dann kommt das entsprechende bit aus dem array an die niederwertigste stelle (weil's nur 0 oder 1 sein kann, kann man + nehmen, ohne einen überlauf in andere bits zu riskieren). das ganze 8 mal und ein zeichen ist vollständig.
    🙂



  • Danke für die schnelle Erklärung :).

    Ich setz' mich gleich mal an die "Umkehrfunktion"...

    Falls übrigens noch jemand bei der Sache mit den variablen-abhängigen Dateinamen helfen kann, wäre das auch super. Darauf bin ich zwar gerade nicht angewiesen, aber das wäre sicher nützlich.


Log in to reply