Namensgenerator
-
Hey Leute ich beschäftige mich ja jetzt schon eine Weile mit cpp und ich finde in diesem Code hier :
#include <iostream> #include <string> #include <conio.h> #include <stdlib.h>//srand #include <time.h>//time using namespace std; string generiere_name(int); int main(){ srand (time(NULL)); cout << "Wie viele Zeichen soll der zufällig generierte Name haben?\n" << "Wahl: "; int z_anzahl; cin >> z_anzahl; string name = generiere_name(z_anzahl); cout << "Name: " << name; getch(); return 0; } //65 (A) - 90 (Z) string generiere_name(int z_anzahl){ string name; string zwischenspeicher; int ascii_anfang=65; for(unsigned int i=0;i<z_anzahl;i++){ int zahl; zahl = rand() % 25 + 0; zahl = zahl + ascii_anfang; static_cast<char> (zahl); zwischenspeicher = zahl; name = name + zwischenspeicher; } return name; }(vor allem in der Funktion) sind sehr viele Variablen kann ich das kürzen?
Oder eventuell sogar noch besser schreiben?
Weil mein Auge sagt mir das es nicht gut aussieht
Gruß
-
Ich würd das so schreiben:(40-45)
int zahl=rand() % 25 + ascii_anfang; name += static_cast<char> (zahl);sollte das selbe ergeben...
bin mir aber nicht hundert pro sicher
-
Hi,
erstmal vorne weg ich lerne auch noch C++ aber ich kann es ja mal versuchen.
Das erste was mir aufgefallen ist, dass ich deinen code in Visual Studio2013 nicht kompilieren kann.
Der Compiler meckert das getch()deprecated ist.Fehler 2 error C4996: 'getch': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _getch. See online help for details.
Ich kenn mich mit getch nicht aus vielleicht googelst du mal.
Ich habe die string Funktion mal umgeschrieben so hätte ich das gemacht.
string generiere_name(int z_anzahl){ string name; name.reserve(z_anzahl); vector<char> alphabet; alphabet.reserve(26); // erstelle Alphabet for (int i = 0; i <= 25; ++i) alphabet.push_back(65 + i); //Wähle Buchstabe und schiebe ihn in den string for (int i = 0; i < z_anzahl; ++i) name += alphabet[rand() % 25]; return std::move(name); }P.S. frage an alle:
Ich bin mir mit std::move immer ein wenig unsicher.
Ich weiß, dass der compiler, wenn er es erkennen kann und der move-constructor vorhanden ist automatisch moved.Ansonsten muss man ihm einen kleinen Tipp geben.
Reicht es ihm den Tipp im return statement zu geben oder muss es auch beim Funktionsaufruf sein, oder ist es sicherer es auf beiden Seiten zu machen?e.g.:
string name = std:move(generiere_name()); // return std::move(name);
-
a-Z
string generiere_name(int z_anzahl){ string name; for (int i = 0; i < z_anzahl; ++i) name += ((rand() % 2) ? 'a' : 'A') + rand() % 26; return name; }a-z
string generiere_name(int z_anzahl){ string n :( ame; for (int i = 0; i < z_anzahl; ++i) name += 'a' + rand() % 26; return name; }A-Z
string generiere_name(int z_anzahl){ string name; for (int i = 0; i < z_anzahl; ++i) name += 'A' + rand() % 26; return name; }Wenn ein Name nur aus bestimmten Buchstaben bestehen soll:
string generiere_name(int z_anzahl){ static const char Ch[] = { 'a', 'b', 'c', 'd', 'e' }; string name; for (int i = 0; i < z_anzahl; ++i) name += Ch[rand() % sizeof(Ch)]; return name; }
-
Ich weiß, dass der compiler, wenn er es erkennen kann und der move-constructor vorhanden ist automatisch moved.
Nicht ganz korrekt. Der Compiler macht alles nach Sprachstandard - und der schreibt vor, dass wenn der Initializer ein rvalue ist, und ein Move-Konstruktor vorhanden ist*, dieser aufgerufen wird. Er kann nicht automatisch Situationen erkennen wo ein Objekt nicht mehr benutzt wird.
Reicht es ihm den Tipp im return statement zu geben oder muss es auch beim Funktionsaufruf sein, oder ist es sicherer es auf beiden Seiten zu machen?
Es reicht ihm gar keinen Tipp zu geben! Nämlich dank (N)RVO.
Mit C++11 sähe das ganze übrigens so aus
#include <random> #include <algorithm> #include <string> template <char first, char last> std::string generateRandomString( std::string::size_type n ) { static std::uniform_int_distribution<char> dis(first, last); static std::mt19937 eng( std::random_device{}() ); std::string rval; rval.reserve(n); std::generate_n( std::back_inserter(rval), n, [&] {return dis(eng);} ); return rval; } template <char const* str, std::size_t length> std::string generateRandomString( std::string::size_type n ) { static std::uniform_int_distribution<std::size_t> dis(0, length-1); static std::mt19937 eng( std::random_device{}() ); std::string rval; rval.reserve(n); std::generate_n( std::back_inserter(rval), n, [&] {return str[dis(eng)];} ); return rval; } auto const generateRandomUpper = generateRandomString<'A', 'Z'>; auto const generateRandomLower = generateRandomString<'a', 'z'>; char constexpr letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; auto const generateRandomAlpha = generateRandomString<letters, sizeof(letters)>; #include <iostream> int main() { for (int n; std::cin >> n;) std::cout << generateRandomUpper(n) << ' ' << generateRandomLower(n) << ' ' << generateRandomAlpha(n) << '\n'; }Natürlich wollen wir eigentlich dass das Ganze über Iteratoren funktioniert - der Einfachkeit halber ist das aber einfach mit
std::stringimplementiert.* nicht als
deleted-definiert.
-
ghjghjghj schrieb:
a-Z
a-z
string generiere_name(int z_anzahl){ string n :( ame; for (int i = 0; i < z_anzahl; ++i) name += 'a' + rand() % 26; return name; }Die Lösung find ich wirklich schön minimalistisch.
Arcoth schrieb:
Nicht ganz korrekt. Der Compiler macht alles nach Sprachstandard - und der schreibt vor, dass wenn der Initializer ein rvalue ist, und ein Move-Konstruktor vorhanden ist*, dieser aufgerufen wird. Er kann nicht automatisch Situationen erkennen wo ein Objekt nicht mehr benutzt wird.
Danke! Hat mir wirklich sehr geholfen.
-
Danke Leute!
Eure Lösungen sind wirklich um einiges besser als mein Ansatz
Die Antwort kommt ein wenig zu spät, da ich im Urlaub war -> sorry ^^