Elikkäs, onko Pick funktiota joka valitsisi annetusta listasta yhden vaihtoehdon. Tähän funktioon olen DM kielessä ja tässä on esimerkki miten tuota käytetää DM:sssä.
var/A = pick("A","B","C","D","E") //Eli muuttuja A olisi joku parametrien kirjaimista.
Tästä linkistä löytyy lisää tietoa.
C++ ei sisällä valmiiksi moista funktiota, mutta sen voi tehdä itse. Haluatko arpoa yhden merkin vai yhden merkkijonon?
Merkkijonon.
Tässä on yksi ratkaisu:
#include <iostream> #include <cstdlib> #include <ctime> std::string lista[] = {"apina", "banaani", "cembalo"}; int main(void) { srand(time(0)); std::cout << lista[rand() % 3] << "\n"; }
Siis vaihtoehdot laitetaan taulukkoon ja sitten niistä arvotaan yksi.
Aah! Kiitos tästä. Tulen tätä tarvitsemaan jatkossa.
Jos haluat käyttöösi jotain tuota pick-funktiota muistuttavaa, voit tehdä sellaisen C:stä perityillä muuttuvan mittaisilla argumenttilistoilla:
#include <cstdarg> #include <cstdlib> #include <ctime> #include <iostream> using namespace std; #define MAX_PICK_ARGS 16 const char* pick_impl(const char* first, ...) { const char* choises[MAX_PICK_ARGS] = {first}; int count=1; va_list ap; va_start(ap,first); while(const char* str = va_arg(ap,const char*)) choises[count++] = str; va_end(ap); return choises[rand()%count]; } #define pick(...) pick_impl(__VA_ARGS__, NULL) int main() { srand(time(0)); cout << pick("a", "b", "c", "d") << endl; }
Pick on tässä toteutettu macrona, joka kutsuu funktiota pick_impl lisäten argumenttilistan perään nullin, jotta pick_impl tietää, koska parametrit loppuvat (argumenttilistat eivät tarjoa mahdollisuutta kysyä listan kokoa). Funktio pick_impl käyttää Antin ehdottamaa ideaa, eli se vain sijoittaa parametrit taulukkoon, ja valitsee sieltä satunnaisesti.
Vastaavan toiminnallisuuden voisi myös helpohkosti toteuttaa tulevan C++-standardin variadic templateilla, joita ainakin GCC jo tukee. Tällöin tuosta saisi helposti myös geneerisemmän version, jonka argumentit voisivat olla mitä tahansa (samaa) tyyppiä, ja toteutus olisi myös tyyppiturvallisempi - nyt missään ei tarkisteta, että kaikki annetut parametrit ovat merkkijonoja.
Antti Laaksonen kirjoitti:
std::cout << lista[rand() % 3] << "\n";
Sen suuremmin C:tä tuntematta..
rand() % 3
rand() palauttaa siis desimaaliluvun [0..1[
% ottaa siitä kokonaisluku moduluksen 3:sta...
vai?? :p
Edit: Toisinsanoen
rand() palauttaa siis suuren kokonaisluvun.
#include <iostream> #include <ctime> #include <cstdlib> #include <vector> template<typename T> T pickFromVector(std::vector<T> vec) { if(vec.size() > 0) { return vec.at(rand() % vec.size()); } else { return 0; } } int main() { srand((unsigned int)time(0)); std::vector<int> intVector; intVector.push_back(5); intVector.push_back(10); intVector.push_back(15); intVector.push_back(20); intVector.push_back(25); int valinta = pickFromVector(intVector); std::cout << "Valittu luku on:" << valinta << "\n" << std::endl; std::cin.get(); return 1; }
Tulipa toteutettua tämä ehdottamani C++0x-versio. Kääntö onnistuu GCC:llä vivulla -std=c++0x.
#include <cstdlib> #include <ctime> #include <iostream> using namespace std; template<class T> T get_nth(int, T x) { return x; } template<class T,class...A> T get_nth(int n, T x, A... rest) { return n==0 ? x : get_nth(n-1, rest...); } template<class T,class...A> T pick(T x, A... rest) { int count = 1+sizeof...(A); return get_nth(rand() % count, x, rest...); } int main() { srand(time(0)); cout << pick(5,10,15,20,25) << endl; cout << pick('a','b','c','d') << endl; cout << pick("sieni", "karhu", "kuusi") << endl; }
Aihe on jo aika vanha, joten et voi enää vastata siihen.