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.