Autor Beitrag
ChrisHa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: 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.

ausblenden volle Höhe C#-Quelltext
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();

            //Zufallszahl generien um die Passwortlänge zu ermitteln
            iPwLänge = rnd.Next(815);

            do
            {
                Random rand = new Random();
                //Zufallzahl generieren, um eine Methode im Menu aufzurufen
                iAuswahl = rand.Next(14);

                //Ruft per Zufall eine Methode auf
                cRückgabe = Menu(iAuswahl);

                sPasswort = sPasswort + cRückgabe;

                //Runterzählen lassen -- Passwortlänge
                iPwLänge--;
            } while (iPwLänge != 0);

            Console.WriteLine(sPasswort);

            //Hält die Konsole nach generien an
            Console.ReadKey();
        }

        static char Menu(int iAuswahl)
        {
            char cZeichen = ' ';

            switch (iAuswahl)
            {
                case 1:
                    //Großbuchstaben 
                    cZeichen = GenBuchstabe();
                    break;

                case 2:
                    //Kleinbuchstaben
                    cZeichen = GenBuchstabe();
                    //Konvertiert den generierten Großbuchstaben in einen Kleinbuchstaben
                    cZeichen = Char.ToLower(cZeichen);
                    break;

                case 3:
                    //Sonderzeichen
                    cZeichen = GenSonderzeichen();
                    break;

                default:
                    //Falls Fehler der Zufallzahl auftritt
                    Console.WriteLine("Fehler in der Zufallsberechnung");
                    break;
            }

            return cZeichen;
        }

        //Generiert einen Buchstaben und gibt diesen zurück
        static char GenBuchstabe()
        {
            //Alle Buchstaben in einen String gepackt und per Zufall einen Wert davon ausgewählt
            string sBuchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int iZufallszahl = 0;

            iZufallszahl = GenZufallszahl();

            return sBuchstaben[iZufallszahl];
        }

        //Generiert eine Zufallszahl und gibt Sie zurück,
        //um einen zufälligen String Wert aufzurufen
        static int GenZufallszahl()
        {
            int iZahl = 0;

            Random rnd = new Random();
            iZahl = rnd.Next(026);

            return iZahl;
        }

        static char GenSonderzeichen()
        {
            string sSonderzeichen = "!§$%&/()=?*#";
            int iSonderzeichen = 0;


            Random rnd = new Random();
            iSonderzeichen = rnd.Next(012);

            return sSonderzeichen[iSonderzeichen];
        }
    }
}



Moderiert von user profile iconChristian S.: Topic aus C# - Die Sprache verschoben am Mi 28.05.2014 um 10:38
Moderiert von user profile iconTh69: Titel geändert.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: 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:

ausblenden volle Höhe C#-Quelltext
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();

            //Zufallszahl generien um die Passwortlänge zu ermitteln
            iPwLänge = rnd.Next(815);

            do
            {

                System.Threading.Thread.Sleep(15);
                //Zufallzahl generieren, um eine Methode im Menu aufzurufen
                iAuswahl = rnd.Next(14);

                //Ruft per Zufall eine Methode auf
                cRückgabe = Menu(iAuswahl);

                sPasswort = sPasswort + cRückgabe;

                //Runterzählen lassen -- Passwortlänge
                iPwLänge--;
            } while (iPwLänge != 0);

            Console.WriteLine(sPasswort);

            //Hält die Konsole nach generien an
            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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: 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:

ausblenden volle Höhe C#-Quelltext
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();

            //Zufallszahl generien um die Passwortlänge zu ermitteln
            iPwLänge = rnd.Next(815);

            do
            {

                System.Threading.Thread.Sleep(15);
                //Zufallzahl generieren, um eine Methode im Menu aufzurufen
                iAuswahl = rnd.Next(14);

                //Ruft per Zufall eine Methode auf
                cRückgabe = Menu(iAuswahl);

                sPasswort = sPasswort + cRückgabe;

                //Runterzählen lassen -- Passwortlänge
                iPwLänge--;
            } while (iPwLänge != 0);

            Console.WriteLine(sPasswort);

            //Hält die Konsole nach generien an
            Console.ReadKey();
        }

        static char Menu(int iAuswahl)
        {
            char cZeichen = ' ';

            switch (iAuswahl)
            {
                case 1:
                    //Großbuchstaben 
                    cZeichen = GenBuchstabe();
                    break;

                case 2:
                    //Kleinbuchstaben
                    cZeichen = GenBuchstabe();
                    //Konvertiert den generierten Großbuchstaben in einen Kleinbuchstaben
                    cZeichen = Char.ToLower(cZeichen);
                    break;

                case 3:
                    //Sonderzeichen
                    cZeichen = GenSonderzeichen();
                    break;

                default:
                    //Falls Fehler der Zufallzahl auftritt
                    Console.WriteLine("Fehler in der Zufallsberechnung");
                    break;
            }

            return cZeichen;
        }

        //Generiert einen Buchstaben und gibt diesen zurück
        static char GenBuchstabe()
        {
            //Alle Buchstaben in einen String gepackt und per Zufall einen Wert davon ausgewählt
            string sBuchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int iZufallszahl = 0;

            iZufallszahl = GenZufallszahl();

            return sBuchstaben[iZufallszahl];
        }

        //Generiert eine Zufallszahl und gibt Sie zurück,
        //um einen zufälligen String Wert aufzurufen
        static int GenZufallszahl()
        {
            int iZahl = 0;

            Random rnd = new Random();
            iZahl = rnd.Next(026);

            return iZahl;
        }

        static char GenSonderzeichen()
        {
            string sSonderzeichen = "!§$%&/()=?*#";
            int iSonderzeichen = 0;


            Random rnd = new Random();
            iSonderzeichen = rnd.Next(012);

            return sSonderzeichen[iSonderzeichen];
        }
    }
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: 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:

ausblenden 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(026);

            return iZahl;
        }

        static char GenSonderzeichen()
        {
            string sSonderzeichen = "!§$%&/()=?*#";
            int iSonderzeichen = 0;


            Random rnd = new Random();
            iSonderzeichen = rnd.Next(012);

            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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: Mi 28.05.14 11:29 
Also quasi dann entweder so:

ausblenden volle Höhe C#-Quelltext
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();

            //Zufallszahl generien um die Passwortlänge zu ermitteln
            iPwLänge = rnd.Next(815);

            do
            {
                //Zufallzahl generieren, um eine Methode im Menu aufzurufen
                iAuswahl = rnd.Next(14);

                //Ruft per Zufall eine Methode auf
                cRückgabe = Menu(iAuswahl, rnd);

                sPasswort = sPasswort + cRückgabe;

                //Runterzählen lassen -- Passwortlänge
                iPwLänge--;
            } while (iPwLänge != 0);

            Console.WriteLine(sPasswort);

            //Hält die Konsole nach generien an
            Console.ReadKey();
        }

        static char Menu(int iAuswahl, Random rnd)
        {
            char cZeichen = ' ';

            switch (iAuswahl)
            {
                case 1:
                    //Großbuchstaben 
                    cZeichen = GenBuchstabe(rnd);
                    break;

                case 2:
                    //Kleinbuchstaben
                    cZeichen = GenBuchstabe(rnd);
                    //Konvertiert den generierten Großbuchstaben in einen Kleinbuchstaben
                    cZeichen = Char.ToLower(cZeichen);
                    break;

                case 3:
                    //Sonderzeichen
                    cZeichen = GenSonderzeichen(rnd);
                    break;

                default:
                    //Falls Fehler der Zufallzahl auftritt
                    Console.WriteLine("Fehler in der Zufallsberechnung");
                    break;
            }

            return cZeichen;
        }

        //Generiert einen Buchstaben und gibt diesen zurück
        static char GenBuchstabe(Random rnd)
        {
            //Alle Buchstaben in einen String gepackt und per Zufall einen Wert davon ausgewählt
            string sBuchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int iZufallszahl = 0;

            iZufallszahl = GenZufallszahl(rnd);

            return sBuchstaben[iZufallszahl];
        }

        //Generiert eine Zufallszahl und gibt Sie zurück,
        //um einen zufälligen String Wert aufzurufen
        static int GenZufallszahl(Random rnd)
        {
            int iZahl = 0;

            iZahl = rnd.Next(026);

            return iZahl;
        }

        static char GenSonderzeichen(Random rnd)
        {
            string sSonderzeichen = "!§$%&/()=?*#";
            int iSonderzeichen = 0;

            iSonderzeichen = rnd.Next(012);

            return sSonderzeichen[iSonderzeichen];
        }
    }
}


Oder ich mach es dann mit Klassen. Oder?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 28.05.14 11:52 
Ja, genau so habe ich es gemeint ;-)
ChrisHa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mi 28.05.14 13:29 
Für so einen Fall mache ich dann gerne Folgendes:
ausblenden C#-Quelltext
1:
private readonly Random _random = new Random();					

Oder statisch:
ausblenden C#-Quelltext
1:
private static readonly Random _random = new Random();					

Oder gleich als Singleton:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 30

Win 7 x64
VS 2010, 2008
BeitragVerfasst: Mi 28.05.14 14:59 
Hallo Palladin007,

verstehe nicht ganz was du da machst?
Wäre ein kurze Erklärung möglich?
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 28.05.14 15:39 
Dann wäre es aber nicht mehr gleichverteilt zufällig. ;-)
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243
Erhaltene Danke: 1



BeitragVerfasst: 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.