C zufälligen Buchstaben generieren?

5 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Deine Frage ist gar nicht so leicht zu beantworten. Das liegt aber weniger am gestellten Problem selbst, sondern weil ich nicht einschätzen kann, auf welchem Lernstand du dich befindest, und welche Features der Programmiersprache für dich nachvollziehbar sind. :)

Außerdem gibt es gerade bei C unendlich viele Aspekte, die berücksichtigt werden wollen, vor allem den Stil, Entwurfsmuster und Paradigmen betreffend. (Soll dein Code auf einem eingebetteten System laufen, oder eher auf einer Workstation? Im Folgenden gehe ich mal realistischerweise von einem Desktop-Computer aus.)

Trotzdem versuche ich es mal, möchte allerdings noch auf etwas hinweisen: In der Standardbibliothek findest du zwar die Funktionen srand() und rand(), mit denen man angeblich (!) Pseudozufallszahlen erzeugen können soll, allerdings ist die im Standard seit jeher vorgeschriebene Implementierung eines deterministischen Pseudozufallszahlengenerators qualitativ äußerst dürftig und erzeugt ausgesprochen schlechte Zufallszahlen. (Die sind sogar so dermaßen schlecht, dass immer dieselbe Person gewinnen wird, falls du damit ein "Würfelspiel" schreiben würdest!)

Es ist aber total einfach, einen wirklich überdurchschnittlichen Zufallszahlen-Generator selbst zu schreiben, indem man auf gängige Xor-Shift-Implementierungen zurück greift. Deshalb implementiert folgender Code einen solchen Mini-Pseudo-Zufallszahlen-Generator, der exzellente Ergebnisse liefert. (Hinweis für Interessierte: Er besteht sogar die statistischen Tests der dieharder-Testsuite!)

Unter dem Code gibt es noch eine ganze Latte weiterer Anmerkungen, aber hier erst mal das Miniprogramm, welches zehn zufällige Strings ausgibt:

#include <stdio.h> /* printf() */
#include <stdlib.h> /* EXIT_SUCCESS, size_t */
#include <time.h> /* clock(), time() */

typedef unsigned prng;

prng prng_rand(prng state) {
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;

return state;
}

#define PRNG_INIT() \
prng_init((prng)(time(NULL) ^ clock()))

prng prng_init(const prng seed) {
const prng pi_hex = 0x40490FDB;

return prng_rand(pi_hex ^ seed);
}

#define PRNG_RAND(state, max) \
((state) = prng_rand(state), (state) % (max))

#define PRNG_CHAR(state) \
('a' + PRNG_RAND((state), 26))

prng prng_cstr(prng state, char * cstr, size_t len) {
if (cstr && len) {
--len;

for (size_t i = 0; i < len; ++i) {
cstr[i] = PRNG_CHAR(state);
}

cstr[len] = '\0';
}

return state;
}

#define PRNG_CSTR(state, cstr, len) \
(state) = prng_cstr((state), (cstr), (len))

#define BUFLEN 8

int main(void) {
char cstr[BUFLEN] = {'\0'};
prng state = PRNG_INIT();

for (size_t i = 0; i < 10; ++i) {
PRNG_CSTR(state, cstr, BUFLEN);

printf("#%lu: '%s'\n", i, cstr);
}

return EXIT_SUCCESS;
}

Wie gesagt, noch einige Anmerkungen und Disclaimer bzgl. des Codes:

  • EXIT_SUCCESS aus <stdlib.h> könntest du auch durch "0" ersetzen, aber ich denke, es verdeutlich die Intention des Entwicklers besser.
  • size_t sollte in Schleifen für den Index anstelle von "int" verwendet werden. Ich weiß nicht, ob du das schon gelesen hast, aber bei großen Arrays wäre mit einem normalen "int" bei knapp 2GB Schluss und dir würde dein Programm danach abstürzen. Mithilfe von size_t kannst du auf so viel RAM zugreifen, wie du niemals im Leben haben wirst. :)
  • "prng" zeigt die Absicht auf, die hinter einer Variablen steht, "unsigned" hingegen nur den Typen. Normalerweise würde ich bei nur wenig komplexeren Typen auch in C einen objektorientierten Ansatz wählen (Ja, das geht tatsächlich in C und nicht nur in C++!), aber hier geht es nur um einen "unsigned", also wollen wir mal nicht mit Kanonen auf Spatzen schießen. :)
  • Alle Funktionen für unseren "Pseudo Random Number Generator" beginnen mit dem Präfix "prng_", da C ja leider keine Namensräume kennt. In einem "richtigen" Projekt würde ich ein sprechenderes Präfix wählen, aber hier reicht das völlig aus. Wie gesagt, Kanonen und Spatzen und so ... :)
  • Viele Leute werden sagen "Makros sind böse", und damit haben sie tatächlich oft recht, aber eben nicht immer. Und im obigen Falle verhindern die Hilfsmakros, dass man vergisst den Status des Generators zu aktualisieren. Alternativ hätte man auch eine globale oder eine statische lokale Variable nehmen können, aber das würde ich in diesem Falle als noch ekliger als Makros erachten. Das ist ein bisschen wie die Wahl zwischen Pest und Cholera und unter anderen Umständen würde ich sicher eine Referenz per Zeiger, globale Variable oder im Idealfall gar ein vernünftiges opakes Objekt bevorzugen, aber wie ich eingangs schon erwähnt habe, muss man immer anhand der Anforderungen abwägen.
  • Parameter sollten normalerweise immer const sein, sofern sie nicht weiter verwendet werden, aber um unnötige lokale Variablen zu sparen, habe ich die Parameter an einigen Stellen "recycled".
  • Ich gehe mal davon aus, dass du deinen Code mit einem Compiler kompilierst, der halbwegs aktuelles C kennt, und Variablendeklarationen nicht am Funktionsanfang erwartet. Der obige Code lässt sich zwar auch sehr leicht an C89 anpassen, aber C99 bzw. C11 ist häufig schon angenehmer.
  • Die Funktion prng_cstr() ist so geschrieben, dass man möglichst nichts kaputt machen kann, es keine Überläufe gibt und das Ergebnis ordentlich nullterminiert ist. Vielleicht sieht die Funktion noch etwas kompliziert für dich aus, aber wenn du weiter übst, wirst du sie vermutlich spätestens in ein paar Wochen problemlos verstehen.
  • Der Code ist auf Einfachheit und nocht auf Portabilität ausgelegt. Das betrifft insbesondere den Teil im Makro PRNG_CHAR(), welches einen einzigen zufälligen Buchstaben erzeugt. Der Code aus den anderen Antworten mit dem langen Stringliteral "abcdefghijklmnopqrstuvwxyz" ist hier deutlich Portabler! Aber da man heutzutage kaum noch auf eine Nicht-ASCII-Plattform stoßen wird, ist die Berechnung mit Offset von 'a' aus vermutlich auch akzeptabel. Merke dir aber bitte, dass Annahmen zum Zeichensatz laut C-Standard niemals portabel sein werden!
  • Ich weiß, dass der obige Code-Schnipsel nicht dein Problem erschlägt, aber es ist auch nicht meine Absicht, dir deine Ideen zu entwickeln. Programmieren lernen musst du selbst und der Quelltext von oben wird dich hoffentlich etwas weiter bringen, inspirieren, anregen oder interessieren.

Naja, es gibt noch weitere Kleinigkeiten, aber ich glaube, das reicht jetzt so langsam. Vermutlich überfordert dich der obige Code und die Anmerkungen etwas, aber mach dir da nichts draus! Einfach immer schön weiter lernen, dann verstehst du automatisch irgendwann alles! :)

Schönen Abend noch! :)

PS: Die Ausgabe des Programms sollte bei (fast) jedem Start anders aussehen, zum Beispiel so:

#0: 'hpxtzzp'
#1: 'fpyrrgi'
#2: 'zlruzpl'
#3: 'geskudw'
#4: 'jhqqdeq'
#5: 'teueodt'
#6: 'lwgjoqw'
#7: 'npdgkij'
#8: 'fvkfegq'
#9: 'bvtaqnk'

Allerdings sind time() und clock() auch keine zuferlässigen Entropiequellen, aber für einen Hangman-Klon reicht es allemal! Fang aber bitte nicht an, damit die Schlüsselgenerierung für eine RSA-Bibliothek zu entwickeln! Danke im Voraus! :)

0

Das Wort solltest du als Array mit definierter Länge speichern (denk ans Endezeichen \0).

char randomletter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[random () % 26];

Das wäre eine Möglichkeit zufällige Buchstaben zu generieren.

Nun kannst du überprüfen, ob randomletter dem Zeichen an der entspr. Stelle des Wortes entspricht, bzw mit einer weiteren Schleife, ob randomletter im gesamten Wort vorkommt.

Schwieriger wird es einzubasteln, ob der PC bereits z.B. "D" "erraten" hat.

Dann könntest du noch ein int erstellen für 11 Galgenelemente, was bei flaschem Buchstaben um eins erhöht wird und bei Galgen = 11 -> x.x .

Willst du den Code so verwenden, solltest du alle Buchstaben des Wortes "uppern"

Du solltest auch einen Exception Fall einbauen, falls User ein Sonderzeichen eingegeben hat. 

Joa das war's von meiner Seite erstmal.

Viel Spaß :)

du kannst char und int ineinander konvertieren. wenn du mit rand() eine zahl generiert hast, caste sie in einen char. Schau dir die ASCII Tabelle an. Kleinbuchstaben beginnen ab 65. Also generiere ne Zahl zwischen 65 und 90 (Großbuchstaben) sowie 97 und 122 (Kleinbuchstaben) und wandle sie in einen char um.

In C sind Konvertierungen überflüssig. Ein char ist nichts weiter als ein 8-Bit-Integer. Ob es als Buchstabe oder Zahl ausgegeben wird, entscheidet die Ausgaberoutine.

3
@PWolff

Sehr guter und wichtiger Kommentar!

Das ist einer der Gründe, warum ich denke, dass Einsteiger eher früher als später mit der Assemblerprogrammierung in Berührung kommen sollten!

Dann wird einem nämlich erst mal so richtig klar, dass beliebig definierte Speicherabschnitte entweder ein Zeichen, eine Ganzzahl, ein Bitfeld, ein Zeiger, eine Gleitpunktzahl oder im Falle von SIMD-Erweiterungen gerne auch mal alles zusammen sein können / dürfen / sollen / müssen.

Oder wenn man sich anguckt, wie so die gängigen ABIs über Stack und / oder Register funktionieren.

C ist zwar sehr "low-level", aber mit Assembler versteht der gemeine Einsteiger hier normalerweise deutlich schneller, dass eigentlich alles nur "Ansichtssache" ist. :)

1

Bei ASCII gilt sogar:

  • 'a' ^ 0x20 == 'A'

... und daraus resultierend ...

  • 'A' ^ 0x20 == 'a'

... lustig, oder? Wenn man also weiß, dass es sich um einen (Groß- oder Klein-) Buchstaben handelt, kann man mit einem XOR die Größe ändern:

char swap_case(const char c) { return c ^ 0x20; }

Ist zwar nicht portabel und ein Kandidat für ernste Sicherheitslücken, aber schön um Leute zum Grübeln zu bringen. :)

0

Zufall in Digitalrechnern?

In einem Computer ist die Informationsverarbeitung doch deterministisch, wie müsste dann ein Algorithmus aussehen, bzw. welche befehle würde er der AlU geben, um beispielsweise eine scheinbar, zufällige Zahlenfolge zu generieren. Kann mir nur schwer vorstellen wie sich, Zufall in einem PC manifestieren soll.

Danke im Voraus.

...zur Frage

Gibt es die Möglichkeit in ein Bash Skript einen Zufallsgenerator einzubauen, der aus festgelegten Variablen eine Zufällige ausgibt?

Und zwar sitze ich momentan an einem Skript, das mir und meinen Kollegen sagen soll, wo wir in der Mittagspause essen gehen sollen. Mein Problem ist jetzt das ich nicht weiß wie ich aus den 4 Variablen = Ikea, Döner, Chinetzen (also Asiamann) oder Bäcker eine zufällige ausgeben lassen kann. Desweiteren hab ich einen Arbeitskollegen der kein Ikea mag und einen der keinen Döner mag. Aber das lässt sich doch problemlos über if und then lösen denke ich? Ich muss zugeben das ich da noch recht neu bin, Ausbildung und so.. :) Danke

...zur Frage

Python Ageben wie oft Buchstabe im String gefunden?

Hallo zusammen,

Ich bin dem Verzweifeln nahe. Ich möchte in folgenden Code ausgeben wie oft der vom Benutzer definierte Buchstabe im vom Benutzer definierten String enthalten ist? Allerdings weiß ich nicht wie dies funktioniert und mir gehen nun nach langem Herumexperimentieren langsam die Ideen aus. Ich freue mich auf Hilfreiche Antworten. Kireznieh while(True): string = input("Gib ein Wort ein:") letter = input("Gib nun einen Buchstaben ein") index = 0 ergebnis = ("") Anzahl = ???

 while(True):
string = input("Gib ein Wort ein:")
letter = input("Gib nun einen Buchstaben ein")
index = 0
ergebnis = ("")
Anzahl = ???

 while(index < len(string)):
    if(string[index] == letter):
        ergebnis = ergebnis,str(index +1)
    index = index +1
  
else:
    if(len(ergebnis) == 0):
        print("Das Zeichen ist im eigegebenen Wort nicht enthalten")
        break
    else:
        print("Eingegebenen Buchstaben an folgenden Stellen",Anzahl, "mal gefunden",ergebnis)
        break   
...zur Frage

Was ist mein securecode wenn ich die S-ID-Check App heruntergeladen habe?

Hallo, ich verzweifel. Bevor ich irgendetwas falsches bei einer Internet Bestellung angebe frage ich lieber hier,

ich habe eine mastercard bei der Sparkasse und habe einen securecode angefordert daraufhin musste ich die S-ID-Check app herunterladen dort einen 4stelligen pin erstellen und das wars. es hies die Registrierung ist abgeschlossen aber ich finde nirgends den eigentlichen securecode. in dieser app steht nur "einmal-Passwort generieren" und dann kommt nur Buchstaben mit zahlen, welche ein paar Sekunden lang angezeigt werden und dann eine neue Kombination aus zahlen und Buchstaben. ist das der Code für meine Bestellung? oder der 4 stellige pin den ich mir ausdenken musste? hilfe!

...zur Frage

Random PHP?

Ich weiß, dass ich zufällige Zahlen mit PHP generieren kann, ich brauche aber einen Random Text aus zahlen, Buchstaben, Großbuchstaben (vill. Sonderzeichen) bestehend aus 64 Zeichen der Generiert wird.

...zur Frage

In C# Namen alphabetisch ordnen?

Hey,

Ich programmiere mit C# und Visual Studio 2017, also ich habe eine Liste mit Namen, und ich will bei der Ausgabe haben, dass mir das ganze Alphabet angezeigt wird und bei dem jeweiligen Buchstaben die passenden Namen. also quasi so:

A

Auerbach Simone

B

C

Chrombacher Hans

D

Detlef Jakob

Dobmann Dana

E

F

usw.

mein Code ist bis jetzt der hier:

        for (char letter = 'A'; letter <= 'Z'; letter++) 
        { 
            Console.WriteLine(letter); //Schreibt alle Buchstaben von A bis Z
            Console.ReadKey();

            foreach (var studentName in _student)
            {
                if (studentName.Nachname.StartsWith() + " " + studentName.Vorname)
                {

                } 
            }

Ich weiß, dass ich dieses StartsWith brauche, aber was schreib ich denn da in die Klammer? Ich komm einfach nicht mehr weiter, habt ihr eine Idee? Weiß auch gar nicht sicher ob ich eine IF-Abfrage brauche.

Danke schon mal.

...zur Frage

Was möchtest Du wissen?