Passwort generieren in C

Kirby.exe

Top Contributor
Alsoo wir sollen ein Programm schreiben, welches uns ein Password in C generiert. Dazu sollen wir erst einlesen wie groß das Passwort sein sollen, wie viele Uppercase, Lowercase und Sonstige Zeichen es enthalten soll. Diese Zeichen sollen wir in ein dynamisches char Array speichern, welches zu meinem ersten Problem führt...Mich verwirren die Pointer in C etwas xD Wie kann ich in C schauen ob eine Array Speicherzelle leer ist? Werden in C Speicherzellen von primitiven Daten Typen mit 0 instanziert?

Ich sende einfach mal den Code den ich bis jetzt habe:

C:
int main(int argc, const char * argv[]){
    int size;
    printf("Enter the length of your Password: ");
    scanf("%d", &size);
    char * password = (char*) malloc(size * sizeof(int));
   
    int uppercaseLetters;
    printf("\nEnter the number of uppercase letters: ");
    scanf("%d", &uppercaseLetters);
   
    int lowercaseLetters;
    printf("\nEnter the number of lowercase letters: ");
    scanf("%d", &lowercaseLetters);
   
    int symbols;
    printf("\nEnter the number of symbols: ");
    scanf("%d", &symbols);
   
    printf("Hello, your Password will have a length of %d with %d uppercase letter, %d lowercase letters and %d symbols\n", size, uppercaseLetters, lowercaseLetters, symbols);
}
 

mihe7

Top Contributor

Kirby.exe

Top Contributor
Würde man den so Werte ins Array stecken?:

C:
for (int i = 0; i < size ; i++) {
        *password = 'i';
        password++;
}
 
K

kneitzel

Gast
Na toll xD Ich freue mich...Da fande ich ja sogar Assembler besser xD
Assembler macht doch gerade deutlich weniger. Und das massive arbeiten mit Pointern ist in C++ auch relativ verschwunden. Wer heutzutage noch mit new / malloc rumhantiert, der hat doch den Schuss nicht gehört!

Wenn Du ein char Array der Größe size brauchst, dann kannst du das doch erstellen mit
char password[size];

Zugriff auf Array Elemente kannst Du per password[i] bekommen.

Also Code wie der hier ist natürlich vollkommen ok:
Code:
    int size = 100;
    char password[100];

    for (int i=0; i<size; i++) {
        password[i] = 'a';
    }

Wenn Du aber unbedingt auf pointer-Ebene arbeiten willst, dann schau Dir den verwendeten Compiler bitte an. Der hat evtl. die Möglichkeit inline Assembler zu nutzen. Dann kannst Du alles in Assembler schreiben. Unleserlicher wird das bestimmt nicht dadurch ...
 
K

kneitzel

Gast
Und diese Array Deklaration ist sogar asbach uralt C - also nicht das du meinst, ich hätte hier C++11 oder so heraus geholt und Dein Prof wäre noch auf C++98 oder so hängen geblieben...

 
K

kneitzel

Gast
Du kannst entweder Pointer-Arithmetik einsetzen oder mit dem Array-Operator [] arbeiten.
Ja, natürlich kann man die Pointer Arithmetik kann man verwenden .... Und Code Reviews mit zurückweisen von Commits kann man zum Glück auch machen .... Also die Welt ist gar nicht mal so schlimm .... ok, für Pointer Arithmetik Leute schon, weil die ihre Changes nicht rein bekommen :)
 

Kirby.exe

Top Contributor
Also ich hatte es am Anfang genauso wie @JustNobody, aber mir wurde dann mitgeteilt, dass es ein "dynamisches" Array sein soll. Nach kurzem googlen bin ich dann auf malloc/calloc/free gestoßen xD Ich sende einfach mal die gesamte Aufgabenstellung :)
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Ja, natürlich kann man die Pointer Arithmetik kann man verwenden .... Und Code Reviews mit zurückweisen von Commits kann man zum Glück auch machen .... Also die Welt ist gar nicht mal so schlimm .... ok, für Pointer Arithmetik Leute schon, weil die ihre Changes nicht rein bekommen :)

So dramatisch finde ich das nicht:

C:
void fill(char *password, size_t size, char ch) {
    char *pos;
    for (pos = password; pos < password + size; pos++) {
        *pos = ch;
    }
}
 
K

kneitzel

Gast
Also das Array ist doch dynamisch, wenn Du size nicht fest vorgibst sondern einliest.

Was ist daran nicht dynamisch? Mal von meinem Tippfehler abgesehen, dass ich das Array fest mit 100 initialisiert habe und nicht mit size.

Aber der Code könnte so aussehen:
Code:
    int size;
    printf("Enter the length of your Password: ");
    scanf("%d", &size);
    char password[size];

Aber wenn Du unbedingt malloc verwenden willst (musst) - aus welchen für mich unverständlichen Gründen auch immer:
Dann verwende doch bitte wenigstens den gleichen Typ bei Deklaration der Variable und sizeof. Einmal char und einmal int dürfte kaum richtig sein.

char hat 1 Byte, int 2 oder 4 ja nach Plattform / Compiler.

 

Kirby.exe

Top Contributor
Ich werde mich glaube ich gleich bei meiner Dozentin melden und mich erkundigen wie sie es den gerne hätten xD Mir wäre das simple einlesen etc ohne malloc lieber xD
 
K

kneitzel

Gast
So dramatisch finde ich das nicht:

Das dramatische ist weniger die Lesbarkeit. Das dramatische ist die manuelle Speicherverwaltung. Also ich sehe bei Kirby ein malloc aber wo wird der Speicher wieder frei gegeben? Oder zählt das nicht, weil das Programm sich ja eh sofort wieder beendet? Also Speicherlecks sind doch hier das dramatische aus meiner Sicht, weshalb man das vermeiden sollte.

Wenn es hier explizit gewünscht ist, dann geht das natürlich auch mit malloc. Ich sehe ja ein, dass man den Umgang mit Zeigern auch können sollte, denn es kann Situationen geben, in denen man es nutzen muss. Aber dennoch sollte man es durchaus sein lassen und auch wenn der Code von mihe7 durchaus lesbar ist, empfinde ich den Zugriff über den Array Operator doch deutlich lesbarer. Aber das mag tatsächlich Geschmack sein...
 
K

kneitzel

Gast
Ich habe jetzt noch einmal nachgeschlagen, was unter dynamischen Arrays verstanden wird in C.

Ich hatte dynamisch so verstanden, dass die Größe Dynamisch ist, je nach size. Aber das war ein Denkfehler. Die Variable soll dynamisch auch andere Werte annehmen können.

Hat man char password[size];, dann ist diese Variable fest. Du kannst Da jetzt kein neues Array mehr einfügen, z.B. mit einer anderen Größe.

Wenn man das Array aber mit malloc belegt, dann kann ich später ein neues array mit einer anderen Größe zuweisen.

Da ist dann auch ein Beispiel, bei dem dann noch mehr Werte eingegeben werden sollen und so ...

Also hier muss ich mich entschuldigen: Ich hatte das Wort dynamisch falsch interpretiert.

Edit: Und bezüglich dem Beispiel: Da wird auch nichts freigegeben. Also für ein Lehrbuch ein extrem schlechtes Beispiel.
Vor dem value = malloc(...) Aufruf in der Schleife muss das bereits enthaltene value frei gegeben werden.
Und nach dem kopieren von temp -> value muss temp wieder frei gegeben werden.
 
Zuletzt bearbeitet von einem Moderator:
K

kneitzel

Gast
Aber dennoch bitte:
- du kannst Du mit dem Array Operator zugreifen. (optional)
- beim Malloc bitte den typ noch anpassen (char = 1 Byte, int hat 2 oder 4 Byte .... )
- nach malloc prüfen, ob da ein Wert zurück gekommen ist - falls kein Speicher verfügbar ist, ist da halt 0 zurück gekommen.
- am Ende ruhig ein free einbauen. Hier ist es egal, da Dein Programm danach beendet wird und damit der ganze Speicher frei gegeben wird.

Die letzten zwei Punkte sind für die Uni evtl. egal, aber das sind Dinge, die Du Dir angewöhnen solltest. Das gehört zum sauberen Arbeiten dazu und später wird man dafür verhauen, wenn man es nicht machen sollte :)
 
K

kneitzel

Gast
Was ist denn ein Pointer? Und schau zur Not einmal in den Link von #17 - da ist ein Beispiel, das das auch prüft ...
 
K

kneitzel

Gast
Wie kannst Du einen pointer bei printf ausgeben? ==> %p (falls Du es nicht so schnell findest).

Dann mach mal ein printf("%p\n", password); - was bekommst du ausgegeben? Was ist das unter dem Strich? Was siehst Du da?

Oder auch im Assembler - wenn Du da eine Speicheradresse wegschreibst - was ist das denn dann eigentlich?

Aber ehe wir lange herum raten und du nicht siehst, worauf ich hinaus will: Ein Zeiger ist auch einfach nur eine Zahl. Wie diese Zahl auszuwerten ist, ist dann eine andere Frage (z.B. mit einem Offset, der berücksichtigt werden muss), aber generell ist es einfach nur eine Zahl.

Und daraus ergibt sich dann auch die Definition von NULL. NULL ist einfach 0 oder 0L (also gleich als long) oder etwas wie (void *) 0
Das macht so erst einmal keinen wirklichen Unterschied, denn es ist einfach ein Pointer. Der Typ spielt beim vergleich von Zeigern keine Rolle.
(Aber natürlich sind die Definitionen oben nicht gleich! Wenn NULL als void * definiert wurde, dann kannst Du z.B. kein int i = NULL; schreiben.)
Siehe dazu z.B. http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/014_c_dyn_speicherverwaltung_003.htm
 

Neue Themen


Oben