args[1] prüfen



  • Hallo zusammen,

    ich habe einen kleinen Passwortgenerator geschrieben und habe nun ein Problem mit den Argumenten, die man main() übergeben kann.

    Wie man im Code sehen kann, möchte ich einen Hilfetext ausgeben, wenn der Benutzer --help oder -h als Argument angibt.

    Allerdings klappt das nicht. Statt dem erwünschten Hilfetext bekomme ich nur eine leere Zeile und danach beendet sich das Programm.

    #include <iostream>
    #include <string>
    
    #define DEFAULT_LENGTH 8
    
    using namespace std;
    
    void help();
    
    void help() {
    	cout << "hilfetext" << endl;
    }
    
    int main(int argc, char* args[]) {
    	string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    	chars += "abcdefghijklmnopqrstuvwxyz";
    	chars += "0123456789_#";
    	string password;	// used to store the password
    	int index;	// used to iterate through 'string chars'
    	int password_length;	// the length of the password
    
    	srand(time(NULL));
    
    	if(argc < 2) {
    		// set all settings to default
    		password_length = DEFAULT_LENGTH;
    	}
    	else if(argc >= 2) {
    		if(args[1]=="--help"||args[1]=="-h") {
    			help();
    			return 0;
    		}		
    		else {
    			password_length = atoi(args[1]);
    		}
    	}
    
    	for(int j=0; j<password_length; ++j) {
    		index = rand() % chars.length();
    		password += chars[index];
    	}
    
    	cout << password << endl;
    
    	return 0;
    }
    

    Wenn ich ausgeben lasse, welchen Wert args[1] hat, wird korrekterweise "--help" oder "-h" angezeigt (je nach dem, was ich übergebe beim Programmstart). Hat jemand von euch eine Idee warum das nicht funktioniert? Vielleicht sehe ich auch nur den Wald vor lauter Bäumen nicht.

    Bin dankbar für jeden Tipp 🙂


  • Administrator

    Ich kommentiere mal deinen Code.

    #include <iostream>
    #include <string>
    #include <sstream> // wir brauchen stringstream für später
    
    #define DEFAULT_LENGTH 8 // GAAANZ übel, man sollte nicht Makros für Konstante verwenden.
    // Verwende lieber C++ Mittel:
    int const DEFAULT_LENGTH = 8;
    
    // Präprozessor ist nur ein dummer Textersetzer. Damit macht man Fehler, ohne das man es bemerkt!
    // Hände weg vom Präprozessor, wo es nur geht!
    
    // using namespaces mit Vorsicht geniessen! Ja nicht in einen Header damit!
    using namespace std;
    
    // Unnötig:
    //void help();
    
    // Deklaration und Definition kann auch gleichzeitig stattfinden!
    void help() {
    	cout << "hilfetext" << endl;
    }
    
    int main(int argc, char* args[]) {
    
    	// Man kann String literale über mehrere Zeilen zusammenhängen.
    	string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"//;
    	/*chars += */"abcdefghijklmnopqrstuvwxyz"//;
    	/*chars += */"0123456789_#";
    	string password;	// used to store the password
    	int index;	// used to iterate through 'string chars'
    	int password_length;	// the length of the password
    
    	// Ich empfehle die Verwendung von 0 statt NULL. Oder nullptr. Siehe dazu auch die FAQ.
    	// srand(time(NULL));
    	srand(time(0));
    
    	if(argc < 2) {
    		// set all settings to default
    		password_length = DEFAULT_LENGTH;
    	}
    	else if(argc >= 2) {
    		// if(args[1]=="--help"||args[1]=="-h") { // Du vergleichst die Zeiger und nicht den Inhalt!
    		// Korrekt wäre z.B. sowas:
    		string arg1 = args[1];
    
    		if(arg1.compare("--help") == 0 ||
    		   arg1.compare("-h") == 0) {
    			help();
    			return 0;
    		}		
    		else {
    			// password_length = atoi(args[1]);
    			// atoi ist C, in C++ benutzt man stringstreams.
    			stringstream ss(args[1]);
    
    			if(!(ss >> password_length))
    			{ /* Fehler! */ }
    		}
    	}
    
    	for(int j=0; j<password_length; ++j) {
    		index = rand() % chars.length();
    		password += chars[index];
    	}
    
    	cout << password << endl;
    
    	return 0;
    }
    

    Ist denke ich das Gröbste und wenn du anstatt den Zeiger den Inhalt der Strings vergleichst, sollte auch das mit dem "help" gehen.

    Grüssli



  • Hi,

    nur noch eine Kleinigkeit als Ergänzung: Wer (wie ich) lieber mit strings als mit char* arbeitet (u.A. um sie direkt vergleichen zu können), kann das mit einer einzigen Zeile hinkriegen:

    int main(int argc, char* argv[]) { // <-- übrigens: wird üblichweise argv genannt und nicht args
       vector<string> args(argv, argv+argc);
    ...
    

    Weiterer Vorteil IMHO: Da ich auf Kopien arbeite, kann ich beliebig Argumente ändern und sogar welche hinzufügen/löschen ...

    Gruß,

    Simon2.



  • Oh, vielen Dank für die Tipps!

    Wieder eine Menge gelernt 🙂

    stringstreams kannte ich noch gar nicht. Klingt gut 😃

    EDIT: Habe bei mir jetzt auch die "using namespace"-Anweisung rausgenommen. Klappt alles wunderbar, vielen Dank!


Anmelden zum Antworten