Autor |
Beitrag |
ChrisHa
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 10:04
Hallo liebe Gemeinde,
ich glaube nicht mal, dass es an meinem Code liegt, trotzdem habe ich Ihn mal hinten mit angefügt.
Zum Thema:
Mein Programm wenn ich es ausführe, soll einfach ein Passwort generieren, welches Groß, Klein und Sonderzeichen per Zufall einbindet.
Das Problem:
Wenn ich das Programm ausführe in VS mit F5 gibt er mir immer 8-15 Zeichen aus. Und zwar immer wieder das selbe Zeichen. z.B.: AAAAAAAAAAAA
Wenn ich das Problem aber jetzt per Einzelschritt (F10) durchklicke bekomme ich eine RandomLänge zwischen 8 - 15 und komplett verschiedene Symbole --> so sollte es auch sein.
Die Frage:
Liegt das nun am Code oder was mache ich falsch?
Grüße und allen einen schönen Tag.
Chris
P.s: Mir ist leider kein passender Titel hierfür eingefallen. Für Verbesserungsvorschläge bin ich natürlich offen.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104:
| namespace PasswordGenerator { class Program { static void Main(string[] args) { int iAuswahl = 0, iPwLänge = 0; string sPasswort = ""; char cRückgabe = ' '; Random rnd = new Random();
iPwLänge = rnd.Next(8, 15);
do { Random rand = new Random(); iAuswahl = rand.Next(1, 4);
cRückgabe = Menu(iAuswahl);
sPasswort = sPasswort + cRückgabe;
iPwLänge--; } while (iPwLänge != 0);
Console.WriteLine(sPasswort);
Console.ReadKey(); }
static char Menu(int iAuswahl) { char cZeichen = ' ';
switch (iAuswahl) { case 1: cZeichen = GenBuchstabe(); break;
case 2: cZeichen = GenBuchstabe(); cZeichen = Char.ToLower(cZeichen); break;
case 3: cZeichen = GenSonderzeichen(); break;
default: Console.WriteLine("Fehler in der Zufallsberechnung"); break; }
return cZeichen; }
static char GenBuchstabe() { string sBuchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int iZufallszahl = 0;
iZufallszahl = GenZufallszahl();
return sBuchstaben[iZufallszahl]; }
static int GenZufallszahl() { int iZahl = 0;
Random rnd = new Random(); iZahl = rnd.Next(0, 26);
return iZahl; }
static char GenSonderzeichen() { string sSonderzeichen = "!§$%&/()=?*#"; int iSonderzeichen = 0;
Random rnd = new Random(); iSonderzeichen = rnd.Next(0, 12);
return sSonderzeichen[iSonderzeichen]; } } } |
Moderiert von Christian S.: Topic aus C# - Die Sprache verschoben am Mi 28.05.2014 um 10:38
Moderiert von Th69: Titel geändert.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mi 28.05.14 10:37
Hallo!
Du darfst den Zufallszahlengenerator nur einmal erzeugen und nicht in jedem Schleifendurchlauf. Sonst wird der, weil das alles innerhalb kürzester Zeit passiert, immer mit demselben Wert geseedet und erzeugt immer dieselben Zahlen. Wenn Du per Einzelschritt durchgehst, sind die Zeiten anders und es wird anders geseedet, deswegen geht es dann.
Grüße
Christian
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Für diesen Beitrag haben gedankt: ChrisHa
|
|
ChrisHa 
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 10:48
Hallo Christian,
zunächst einmal danke für deine Antwort. Es ist tatsächlich die Lösung für mein Problem.
Weiß nicht ob es die eleganteste Lösung ist, aber ich habe in der do-while schleife nun etwas eingebaut:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
| static void Main(string[] args) { int iAuswahl = 0, iPwLänge = 0; string sPasswort = ""; char cRückgabe = ' '; Random rnd = new Random();
iPwLänge = rnd.Next(8, 15);
do {
System.Threading.Thread.Sleep(15); iAuswahl = rnd.Next(1, 4);
cRückgabe = Menu(iAuswahl);
sPasswort = sPasswort + cRückgabe;
iPwLänge--; } while (iPwLänge != 0);
Console.WriteLine(sPasswort);
Console.ReadKey(); } |
Habe die Zeit ausprobiert bei kürzeren Wartezeiten gibt er trotzdem oftmals zwei mal den selben Buchstaben hintereinander aus.
Hatte mir noch gedacht, dass man vielleicht die Werte irgendwie übergeben kann, aber damit hab ich mich grade noch nicht weiter befasst.
Grüße
Chris
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 28.05.14 11:03
Hallo ChrisHa,
das Thread.Sleep() ist hier aber völlig überflüssig, denn nur die Erzeugung der Random-Instanz mittels des Standardkonstruktors benutzt die Systemzeit (und hier wiederum nur auf Sekundenbasis). Die Random.Next()-Aufrufe beruhen nur auf dem letzten erzeugten Zufallswert.
Wie sieht denn deine Menu-Methode aus? Erzeugst du darin dann wieder ein neues Random-Objekt?
|
|
ChrisHa 
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 11:05
Hallo Th69,
an der Menu Methode habe ich nicht verändert. Sie ist noch immer genauso wie oben abgebildet. Hier nochmal mein Komplett - Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104:
| namespace PasswordGenerator { class Program { static void Main(string[] args) { int iAuswahl = 0, iPwLänge = 0; string sPasswort = ""; char cRückgabe = ' '; Random rnd = new Random();
iPwLänge = rnd.Next(8, 15);
do {
System.Threading.Thread.Sleep(15); iAuswahl = rnd.Next(1, 4);
cRückgabe = Menu(iAuswahl);
sPasswort = sPasswort + cRückgabe;
iPwLänge--; } while (iPwLänge != 0);
Console.WriteLine(sPasswort);
Console.ReadKey(); }
static char Menu(int iAuswahl) { char cZeichen = ' ';
switch (iAuswahl) { case 1: cZeichen = GenBuchstabe(); break;
case 2: cZeichen = GenBuchstabe(); cZeichen = Char.ToLower(cZeichen); break;
case 3: cZeichen = GenSonderzeichen(); break;
default: Console.WriteLine("Fehler in der Zufallsberechnung"); break; }
return cZeichen; }
static char GenBuchstabe() { string sBuchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int iZufallszahl = 0;
iZufallszahl = GenZufallszahl();
return sBuchstaben[iZufallszahl]; }
static int GenZufallszahl() { int iZahl = 0;
Random rnd = new Random(); iZahl = rnd.Next(0, 26);
return iZahl; }
static char GenSonderzeichen() { string sSonderzeichen = "!§$%&/()=?*#"; int iSonderzeichen = 0;
Random rnd = new Random(); iSonderzeichen = rnd.Next(0, 12);
return sSonderzeichen[iSonderzeichen]; } } |
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 28.05.14 11:13
Sorry, hatte deinen ersten Code nicht weiter runtergescrollt gehabt.
Aber jetzt bedenke noch mal Th69 hat folgendes geschrieben: | Erzeugst du darin dann wieder ein neues Random-Objekt? |
|
|
ChrisHa 
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 11:17
Ist kein Problem. Nobody is perfect.
Soweit ich dass jetzt sehe, wird in meiner Menu Methode direkt kein Random Wert mehr erzeugt.
Nur eben hier nochmal:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| static int GenZufallszahl() { int iZahl = 0;
Random rnd = new Random(); iZahl = rnd.Next(0, 26);
return iZahl; }
static char GenSonderzeichen() { string sSonderzeichen = "!§$%&/()=?*#"; int iSonderzeichen = 0;
Random rnd = new Random(); iSonderzeichen = rnd.Next(0, 12);
return sSonderzeichen[iSonderzeichen]; } |
Soll ich die Werte am besten schon in der Main erzeugen und dann einfach an die Methode mit übergeben? Falls ich dich falsch verstehe bitte ich um Berichtigung
Grüßé
Chris
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 28.05.14 11:21
Ob direkt in der Menu()-Methode oder indirekt in den Untermethoden spielt dabei ja keine Rolle, solange diese eben aufgerufen werden - und in den Zeilen 5 und 18 (deines letzten Codes) erzeugst du ja wiederum ein neues Random-Objekt (welches wiederum mit der Systemzeit initialisiert wird).
Übergib entweder das Random-Objekt an die entsprechenden Methoden oder noch besser erzeuge dir eine Klasse, welche das Random-Objekt als Member beinhaltet und packe dort dann deine Generierungsmethoden rein (so daß diese dann auf das Random-Objekt zugreifen können).
Für diesen Beitrag haben gedankt: ChrisHa
|
|
ChrisHa 
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 11:29
Also quasi dann entweder so:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105:
| using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace PasswordGenerator { class Program { static void Main(string[] args) { int iAuswahl = 0, iPwLänge = 0; string sPasswort = ""; char cRückgabe = ' '; Random rnd = new Random();
iPwLänge = rnd.Next(8, 15);
do { iAuswahl = rnd.Next(1, 4);
cRückgabe = Menu(iAuswahl, rnd);
sPasswort = sPasswort + cRückgabe;
iPwLänge--; } while (iPwLänge != 0);
Console.WriteLine(sPasswort);
Console.ReadKey(); }
static char Menu(int iAuswahl, Random rnd) { char cZeichen = ' ';
switch (iAuswahl) { case 1: cZeichen = GenBuchstabe(rnd); break;
case 2: cZeichen = GenBuchstabe(rnd); cZeichen = Char.ToLower(cZeichen); break;
case 3: cZeichen = GenSonderzeichen(rnd); break;
default: Console.WriteLine("Fehler in der Zufallsberechnung"); break; }
return cZeichen; }
static char GenBuchstabe(Random rnd) { string sBuchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int iZufallszahl = 0;
iZufallszahl = GenZufallszahl(rnd);
return sBuchstaben[iZufallszahl]; }
static int GenZufallszahl(Random rnd) { int iZahl = 0;
iZahl = rnd.Next(0, 26);
return iZahl; }
static char GenSonderzeichen(Random rnd) { string sSonderzeichen = "!§$%&/()=?*#"; int iSonderzeichen = 0;
iSonderzeichen = rnd.Next(0, 12);
return sSonderzeichen[iSonderzeichen]; } } } |
Oder ich mach es dann mit Klassen. Oder?
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 28.05.14 11:52
Ja, genau so habe ich es gemeint 
|
|
ChrisHa 
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 11:55
Gut ein Danke an Th69 und Christian für die Hilfe. Das Programm funktioniert jetzt einwandfrei.
Bzgl. der Klassen mache ich mir mal heute Nachmittag Gedanken.
In diesem Sinne einen schönen Tag allen noch.
Grüße
chris
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 28.05.14 13:29
Für so einen Fall mache ich dann gerne Folgendes:
C#-Quelltext 1:
| private readonly Random _random = new Random(); |
Oder statisch:
C#-Quelltext 1:
| private static readonly Random _random = new Random(); |
Oder gleich als Singleton:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| public static class StaticRandom { private static readonly Random _instance;
public static Random Instance { get { if (_instance== null) _instance= new Random();
return _instance; } } } |
So habe ich immer und überall die selbe Random-Instanz.
|
|
ChrisHa 
      
Beiträge: 30
Win 7 x64
VS 2010, 2008
|
Verfasst: Mi 28.05.14 14:59
Hallo Palladin007,
verstehe nicht ganz was du da machst?
Wäre ein kurze Erklärung möglich?
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 28.05.14 15:29
Zu was genau?
Der Hintergrund ist, dass ich möglichst wenige Instanzen von Random haben möchte, weshalb ich die irgendwo zentral ablege und immer wieder verwende.
Ich meine auch gelesen zu haben, dass Random intern dafür Sorge trägt, dass nicht die gleichen Werte nacheinander auf treten, das funktioniert aber nur, wenn es auch die gleiche Instanz ist.
So im Sourcecode habe ich das nicht auf die Schnelle raus lesen können.
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 28.05.14 15:39
Dann wäre es aber nicht mehr gleichverteilt zufällig. 
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 28.05.14 16:25
Wie verhindert es denn dann, dass keine gleichen Werte heraus kommen, wenn Next 100 mal die Sekunde aufgerufen werden?
Irgendwie wird das ja in der Instanz verhindert, sonst wäre es ja egal, ob es die gleiche Instanz ist, oder nicht.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 28.05.14 16:47
Da wird nix verhindert. Jeder Wert ist gleich wahrscheinlich. Wäre es nicht so wäre Random kaputt.
Edit: Zitat: | Wie verhindert es denn dann, dass keine gleichen Werte heraus kommen, wenn Next 100 mal die Sekunde aufgerufen werden? |
Random spult je Seed die immer gleiche Zahlenfolge ab egal wann der nächste Abruf einer ~Zufallszahl~ erfolgt.
Zitat: | Irgendwie wird das ja in der Instanz verhindert, sonst wäre es ja egal, ob es die gleiche Instanz ist, oder nicht. |
Du kannst auch mehrere Random Klassen mit unterschiedlichem Seed nehmen. Es sollte halt nur nicht immer eine neue Random Klasse mit dem selben Seed sein weil da immer wieder die gleiche Zahlenfolge kommt. Wenn ich immer nur den ersten Wert von dieser Random Instanz nehme kommt dann halt immer das gleiche.
|
|
BlackMatrix
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Fr 13.06.14 13:05
Je nachdem wie zufällig die erzeugten Passwörter sein sollten, würde ich dir lieber eine fertige Bibliothek empfehlen. Einfach mal googlen. Ansonsten würde ich für schnelle, einfache Implementierungen Path.GetRandomFileName missbrauchen.
Edit: Ups, sehr alt.
|
|