引数をランダムに
-
Dixq (管理人)
Re:引数をランダムに
これでどうでしょう?
int SelectRandNum( int a[/url], int n ){
return ( a [ GetRand( n-1 ) ] );
}
aにはランダムで返したい数字が入っています。
nはその個数です。
int a[5]={6,1,3,2,8}, ans;
ans = SelectRandNum( a, 5 );
このように呼ぶとaの中の数字のどれかが返ります。
-
たかぎ
Re:引数をランダムに
これは規格厳密合致プログラムでは実現できそうもありません。
とりあえず、GCCを使って次のようにすれば実現可能です。
とりあえず、GCCを使って次のようにすれば実現可能です。
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define RandNum(var_decl, ...) const var_decl = RandNumHelper(sizeof((int[/url]){__VA_ARGS__})/sizeof(int), __VA_ARGS__)
int RandNumHelper(size_t n, ...)
{
n = rand() % n;
va_list ap;
va_start(ap, n);
int result;
for (size_t i = 0; i <= n; i++)
{
result = va_arg(ap, int);
}
va_end(ap);
return result;
}
int main(void)
{
for (int i = 0; i < 10; i++)
{
RandNum(int &a, 1, 2, 3);
printf("%d\n", a);
}
}
引数に int &a を渡したときに a に格納しないといけないとのことですので、C++でなければなりません。-
バグ
Re:引数をランダムに
たかぎさんの後は緊張しますねぇ(^_^;)
とりあえず、関数部だけ…
C++やC#で書くことが多いのでmalloc関数を使用する機会が少ないので、なんか新鮮でした(^-^)
// int* data = データ格納用バッファへのポインタ
// int num = 可変個引数の個数
// 戻り値 = 数値取得に成功したら1を、エラー時には0を返します
int RandNum(int* data, int num, ...)
{
// 可変個引数の数値を一時的に格納するメモリを確保
int* buf = (int*)malloc(sizeof(int) * num);
if (buf == NULL)
{
// メモリの確保に失敗したので0を返す
return 0;
}
// 可変個引数の取得
va_list list;
va_start(list, num);
for (int i = 0; i < num; ++i) *(buf + i) = va_arg(list, int);
va_end(list);
// *dataにランダムに選択した数値を格納する
*data = *(buf + rand() % num);
// メモリの解放
free(buf);
// 数値取得に成功したので1を返す
return 1;
}
とりあえず、関数部だけ…
C++やC#で書くことが多いのでmalloc関数を使用する機会が少ないので、なんか新鮮でした(^-^)
// int* data = データ格納用バッファへのポインタ
// int num = 可変個引数の個数
// 戻り値 = 数値取得に成功したら1を、エラー時には0を返します
int RandNum(int* data, int num, ...)
{
// 可変個引数の数値を一時的に格納するメモリを確保
int* buf = (int*)malloc(sizeof(int) * num);
if (buf == NULL)
{
// メモリの確保に失敗したので0を返す
return 0;
}
// 可変個引数の取得
va_list list;
va_start(list, num);
for (int i = 0; i < num; ++i) *(buf + i) = va_arg(list, int);
va_end(list);
// *dataにランダムに選択した数値を格納する
*data = *(buf + rand() % num);
// メモリの解放
free(buf);
// 数値取得に成功したので1を返す
return 1;
}
-
たかぎ
Re:引数をランダムに
バグさん
//形式のコメントや for (int i = 0; i < num; ++i) という書き方から見てC99を想定しているのでしょうが、それならmallocを使わなくても可変長配列で十分な気がします。
そもそも、mallocも可変長配列も不要ですが...
この質問の難しいところは、可変個引数の個数が分からないため、自動的に認識させることと、第1引数に int &a のような宣言を渡すところです。void RandNum(int *Num,・,・,・); という関数原型と矛盾しているような気もしますが...
//形式のコメントや for (int i = 0; i < num; ++i) という書き方から見てC99を想定しているのでしょうが、それならmallocを使わなくても可変長配列で十分な気がします。
そもそも、mallocも可変長配列も不要ですが...
この質問の難しいところは、可変個引数の個数が分からないため、自動的に認識させることと、第1引数に int &a のような宣言を渡すところです。void RandNum(int *Num,・,・,・); という関数原型と矛盾しているような気もしますが...
-
たかぎ
Re:引数をランダムに
第1実引数が int &a ではなく &a でよいのであれば、規格厳密合致プログラムが可能になります。
#include <stdio.h>
#include <stdlib.h>
#define RandNum(result, ...) \
((void)(*(result) = (int[/url]){__VA_ARGS__}[rand() % (sizeof((int[/url]){__VA_ARGS__})/sizeof(int))]))
int main(void)
{
for (int i = 0; i < 10; i++)
{
int a;
RandNum(&a, 1, 2, 3);
printf("%d\n", a);
}
}
今度はC99で扱えます。ただし、このマクロは標準C++では使えません。-
久美
Re:引数をランダムに
このサイトの方たちは皆さん優しいですね><
えっと、言語はC++です。
Dixq (管理人)さんの
int SelectRandNum( int a[/url], int n ){
return ( a [ GetRand( n-1 ) ] );
}
int a[5]={6,1,3,2,8}, ans;
ans = SelectRandNum( a, 5 );
を使いますね>< と言いますか、これしか理論がわからないw
皆さん天才ですか?
できれば配列を使わずにこれをしたいのですが無理そうですのでこれでいきます。
もし、他にもできそうなのでしたらお願いします。
えっと、言語はC++です。
Dixq (管理人)さんの
int SelectRandNum( int a[/url], int n ){
return ( a [ GetRand( n-1 ) ] );
}
int a[5]={6,1,3,2,8}, ans;
ans = SelectRandNum( a, 5 );
を使いますね>< と言いますか、これしか理論がわからないw
皆さん天才ですか?
できれば配列を使わずにこれをしたいのですが無理そうですのでこれでいきます。
もし、他にもできそうなのでしたらお願いします。
-
バグ
Re:引数をランダムに
>>たかぎさん
確かに、わざわざmallocを使う必要無かったですね。ご指摘有り難うございます(^-^)
>>久美さん
C++ならば、vectorに任意の値を格納し、random_shuffleでシャッフルして、先頭の値を返すとかでいいんじゃないでしょうか?
確かに、わざわざmallocを使う必要無かったですね。ご指摘有り難うございます(^-^)
>>久美さん
C++ならば、vectorに任意の値を格納し、random_shuffleでシャッフルして、先頭の値を返すとかでいいんじゃないでしょうか?
-
Dixq (管理人)
Re:引数をランダムに
配列を使わずに、かつわかりやすくということでしたら、こういうのはどうでしょう。
int SelectRandNum(int a, int b){
int *p[2]={&a,&b};
*p += rand()%2;
return **p;
}
a,bのアドレスをポインタ配列pにいれます。
最初*pはaをさしています。もし*pに1を足すと、bをさしますよね。
それを利用して0か1どっちかを足せばaかbどっちかをさします。
*pに入っている変数の中身を返す
return **p;
するとaかbどちらかが返る事になります。
効率は悪いですが、これを沢山作るとか・・。
#include <stdio.h>
#include <stdlib.h>
int SelectRandNum(int a, int b){
int *p[2]={&a,&b};
*p += rand()%2;
return **p;
}
int SelectRandNum(int a, int b, int c){
int *p[3]={&a,&b,&c};
*p += rand()%3;
return **p;
}
int SelectRandNum(int a, int b, int c, int d){
int *p[4]={&a,&b,&c,&d};
*p += rand()%4;
return **p;
}
int main(void){
printf("%d\n",SelectRandNum(1,2));
printf("%d\n",SelectRandNum(2,3,4));
printf("%d\n",SelectRandNum(5,6,7,8));
return(0);
}
実行結果
2
4
7
-
tk-xleader
Re:引数をランダムに
引数40個までで、実装してみました。
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
/*↑
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
の代わり(警告対策)*/
class Input{
int value;
bool isendmark;
public:
Input(int invalue){
value=invalue;
isendmark=false;
}
Input(){
value=-1;//適当に代入しておく(警告封じ)。
isendmark=true;
}
bool IsEndMark()const{
return isendmark;
}
int GetValue()const{
return value;
}
};
void RandNum(int *Num,
const Input&arg1=Input(),
const Input&arg2=Input(),
const Input&arg3=Input(),
const Input&arg4=Input(),
const Input&arg5=Input(),
const Input&arg6=Input(),
const Input&arg7=Input(),
const Input&arg8=Input(),
const Input&arg9=Input(),
const Input&arg10=Input(),
const Input&arg11=Input(),
const Input&arg12=Input(),
const Input&arg13=Input(),
const Input&arg14=Input(),
const Input&arg15=Input(),
const Input&arg16=Input(),
const Input&arg17=Input(),
const Input&arg18=Input(),
const Input&arg19=Input(),
const Input&arg20=Input(),
const Input&arg21=Input(),
const Input&arg22=Input(),
const Input&arg23=Input(),
const Input&arg24=Input(),
const Input&arg25=Input(),
const Input&arg26=Input(),
const Input&arg27=Input(),
const Input&arg28=Input(),
const Input&arg29=Input(),
const Input&arg30=Input(),
const Input&arg31=Input(),
const Input&arg32=Input(),
const Input&arg33=Input(),
const Input&arg34=Input(),
const Input&arg35=Input(),
const Input&arg36=Input(),
const Input&arg37=Input(),
const Input&arg38=Input(),
const Input&arg39=Input(),
const Input&arg40=Input()
){
Input arglist[/url]={
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20,
arg21,
arg22,
arg23,
arg24,
arg25,
arg26,
arg27,
arg28,
arg29,
arg30,
arg31,
arg32,
arg33,
arg34,
arg35,
arg36,
arg37,
arg38,
arg39,
arg40
};
int count;
for(count=0;count<sizeof(arglist)/sizeof(arglist[0]);count++){
if(arglist[count].IsEndMark())break;
}
if(count<1)return ;
*Num=arglist[rand()%count].GetValue();
}
int main()
{
int rnum;
srand((unsigned)time(0));
RandNum(&rnum,10,30,65,20,54,42);
printf("%d\n",rnum);
return 0;
}
コードがめちゃくちゃですが、一応動作チェックはしています。-
hoge
Re:引数をランダムに
雑談になりますが、
No:23076のたかぎさんの発言に反応
> これは規格厳密合致プログラムでは実現できそうもありません。
多分、C99規格に合致していると思われるコードが書けました。
No:23076のたかぎさんの発言に反応
> これは規格厳密合致プログラムでは実現できそうもありません。
多分、C99規格に合致していると思われるコードが書けました。
// ヘッダは省略
#define RandNum(var_decl, ...) RandNum##var_decl, __VA_ARGS__)
#define RandNumint RandNumintHelper(
#define RandNumintHelper(result, ...) \
((void)(*(result) = (int[/url]){__VA_ARGS__}[rand() % (sizeof((int[/url]){__VA_ARGS__})/sizeof(int))]))
int main(void)
{
for (int i = 0; i < 10; i++)
{
int a;
RandNum(int &a, 1, 2, 3);
printf("%d\n", a);
}
}