こんにちは。C言語初心者で現在会社で勉強しているものです。上司に課題を出されました。以下の通りです。
「1~100までの数字をランダムに出力するプログラムを作成しなさい。ただし実行するたびにその結果は異なるようにし、同じ数字は表示されないようにしなさい。」
 time関数を使って実行する度に異なる結果が得られるところまではできたのですが、一度表示された数字を省くロジックがわかりません。質問検索で似たような質問をされていた方が何人かいて、それを参考にやってみたのですがどうもうまくいきません。できるだけCPUに負荷をかけないように、という条件もあります。
 提出期限が迫っており困っています。どなたか教えてください。

このQ&Aに関連する最新のQ&A

A 回答 (5件)

2つの課題が有りますね。

今までにやってみて一番気に入った方法を。
(1)実行するたびに同じ並びになったら困る。
    time関数を使わなくても srand関数を最初に1回書けば実行するたびに乱数が変わるはずです。
   (勝手にtime関数を実行してくれる?)

(2)重ならない乱数を効率よく100個取り出す。
   配列を100個用意し、1から100の数字を入れます。
   randでそのうちの1個を選んで出力します。仮に48番目とします。
   48番目と100番目を入れ替えます。
   次に99個の範囲で1つ選んで出力します。仮に35番目とします。
   35番目と99番目を入れ替えます。
   次に98個の中から・・・
   
   ということを次々に繰り返していけば最後に配列の対象範囲が0になります。
   これをチェックしてループを終了すればいい訳です。
   
    • good
    • 0

プログラミングはできるだけ自分の力でやった方がいいですよ。


ゆくゆく苦労してしまいますから。
たとえ自分でやったとして効率の悪いのができたとしても
はるかにためになりますから。
今回はお困りのようなのでちょっとだけ力になります。

void main(void)
{
int num[100] = {1,2,3,4,5,6,7,8,9,10,11.....100};
int i,j;

for(i=0;i<100;i++){
cnt = rand()%(100-i);
printf("%d\n",num[cnt]);

for(j=cnt;j<100-1;j++){
num[j] = num[j+1];
}
}
}

これでできませんかね?
    • good
    • 0

「rand関数を使え」という指示が無ければ、こんな発想もあります。



1~100迄の値が入った数列を用意して、数字をバラバラに入れ替えれば終わりです。(結局ココにrandを使うことになりますので、ある意味課題クリアです)
プログラム量も非常に短くなりますし、負荷は入れ替えの回数次第で調節できます。

ところで、time関数ってミリ秒が帰ってくると思うのですが、高速CPUでやるとずっと同じ値が帰ってきたりしませんか・・?
    • good
    • 0

私も同じようなプログラムを作った経験があります。

お考えのように1~100までの乱数発生させ、一回登場した数値はフラグでチェックして飛ばすという考え方では100個目を選ぶのにえらく時間がかかり、何か無駄なような気がしました。
そこで例えば1~100までの番号がついたボールがあると考えて。
1.最初の1個を乱数で選ぶ
2.残りは99個なので1~99の乱数発生させ、次の一個を選ぶ
3.また1個減るので、1~98の乱数発生させ、次の一個を選ぶ
4.これを繰返す
5.最後には1個になり、ここで100個目を選んで終り。
いかがでしょうか

この回答への補足

 早速の解答ありがとうございます。すごく分かりやすいた例えでありがたいです。しかし現在の私の能力では具体的にどうプログラミングしたらよいかどうしても分かりません。選ぶボールを減らしていく方法を教えてください。

補足日時:2002/03/26 13:52
    • good
    • 0

データ型は bool , short , char のどれでも構いませんが


配列を 101 取ると 0~100 のフラグとして使用できます
その配列を初期化して(これが重要です)
出た結果をフラグに代入し,次に出た結果のフラグに何か代入されているか
をチェックすれば同じ数字を表示することは防げます
また,表示した個数を数えていれば全ての数字を表示したことがわかります
    • good
    • 0

このQ&Aに関連する人気のQ&A

意味 フラグ」に関するQ&A: メールのフラグ

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q乱数の最大値

C言語で0~Nまでの乱数を発生させる場合、

srand((unsigned) time(NULL));
rand()%N;

とやりますよね。
このやり方だと、発生する乱数はRAND_MAX以下しかできません。
RAND_MAX以上の値を発生させるにはどうすればいいのでしょうか?

Aベストアンサー

(RANDMAX + 1) * rand() + rand()
0~1073741823

↓訂正↓

Q最大値と最小値を表示したいのですが・・・

double numに入っている数字から最大値と最小値を求めたいのですが、このままだと両方とも1.000になってしまうんです・・・
どうやったらちゃんと最大値と最小値が表示されるのでしょうか??
初心者なものでスイマセンが教えてください!!


#include<stdio.h>

int main(void)
{
int i,j;
double num[]={4.5,3.1,7.0,9.2,1.0,5.7,9.3,2.3,0.3,1.0};
double max,min;

for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
if(num[i]>num[j])
max=num[i];
}
}

for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
if(num[i]<num[j])
min=num[i];
}
}
printf("最大値は%fです。",max);
printf("最小値は%fです。",min);

return 0;
}

double numに入っている数字から最大値と最小値を求めたいのですが、このままだと両方とも1.000になってしまうんです・・・
どうやったらちゃんと最大値と最小値が表示されるのでしょうか??
初心者なものでスイマセンが教えてください!!


#include<stdio.h>

int main(void)
{
int i,j;
double num[]={4.5,3.1,7.0,9.2,1.0,5.7,9.3,2.3,0.3,1.0};
double max,min;

for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
if(num[i]>num[j])
max=num[i];
}
}

for(i=0; i<10;...続きを読む

Aベストアンサー

なぜforループが2重になっているのかよくわかりませんが、
考え方として、
・とりあえず配列の最初の値を暫定の最大値としてセットする
・forループで配列を調べていき、配列の値が暫定の最大値より大きな場合、それを暫定の最大値とする。
・forループを抜けると、暫定の最大値は暫定ではなく、その配列の最大値となっている。
という流れが普通のやり方です。

以上を踏まえてコーディングを手直しすると、以下のようになります。

#include<stdio.h>

int main(void)
{
int i;
double num[]={4.5,3.1,7.0,9.2,1.0,5.7,9.3,2.3,0.3,1.0};
double max,min;

max=num[0];
for(i=0; i<10; i++)
{
if(num[i]>max)
max=num[i];
}

min=num[0]
for(i=0; i<10; i++)
{
if(num[i]<min)
min=num[i];
}

printf("最大値は%fです。",max);
printf("最小値は%fです。",min);

return 0;
}

なぜforループが2重になっているのかよくわかりませんが、
考え方として、
・とりあえず配列の最初の値を暫定の最大値としてセットする
・forループで配列を調べていき、配列の値が暫定の最大値より大きな場合、それを暫定の最大値とする。
・forループを抜けると、暫定の最大値は暫定ではなく、その配列の最大値となっている。
という流れが普通のやり方です。

以上を踏まえてコーディングを手直しすると、以下のようになります。

#include<stdio.h>

int main(void)
{
int i;
double num[]={4....続きを読む

Qランダムで数を表示するには

C言語を覚えたてなんですが
計算や変数を代入などは本にやり方が書いてあってわかったのですが
たとえばサイコロやルーレットのプログラムを作るとして
1~6の数字がランダムででるようなプログラムをつくるには
どうすればいいのでしょうか?
また1が50%で、2が25%、3が10%で4~6が5%づつとか
出る確率を設定することとかも出来るのでしょうか?

Aベストアンサー

乱数は1の方が答えてるので、確率は

kakuritsu = 80;
if(kakuritsu <=0 || kakuritsu < rand()%100+1)
{
外れ
}else{
当たり
}

で出来るはずです。kakuritsuには%の数が入ります。
この場合は80%の確率で当たります。
関数にすると良いかもしれません。
1が50%で、2が25%というやり方だと、その1とか2という変数に応じて確率を入れると良いと思います。

Q*をユーザーが入力した数字の数だけ表示するプログラムの作り方を教えてください

はじめまして。
現在C言語の勉強している大学生です。

『*』をユーザーが入力した数字の数だけ表示するプログラムの作り方を教えてください。
例えばユーザーが5と入力したら*****とでるもの。

(本に載っている演習なのですが答えがのっていないのです。)
whileかforを使うのだと思うんですが。。
よろしくお願い致します。

Aベストアンサー

これで、OKです。
とても簡単なプログラムです。

#include<stdio.h>
int main(void)
{
int i,num;
printf("何個表示しますか?->");scanf("%d",&num);

for(i=0;i<num;i++)
{
printf("*");
}
printf("\n");

return 0;
}

Q"gets"は危険なのでしょうか?

以下をコンパイルした際に"gets function is dangerous and should not be used "と警告が出ました。直訳すると"getsは危険だから使わないほうが良い"となるのですが、今私の使用している教本には"'gets'に代わる文字列入力の便利な方法は無く、入力文字数が配列を超えないように"との注意しかなく、それは厳守しています。プログラムがいけないのでしょうか。

#include <stdio.h>

int main(void)
{
char str[80];
int i;

printf("文字列を入力してください(80文字以下): ");
gets(str);
for(i=0; str[i]; i++) printf("%c", str[i]);

return 0;

Aベストアンサー

gets関数はバッファオーバーフローの脆弱性の原因になる可能性があります。gets関数がバッファあふれを起こした場合の動作は予測できません。従って使用する場合注意する必要があります(特にrootなどで動かす場合はセキュリティホールの原因になります)。

一般的なのCの関数の説明でもgetsは使うべきではないと成っています。そのためにコンパイラで警告が出るようになっています。

参考URL:http://www.linux.or.jp/JM/html/LDP_man-pages/man3/gets.3.html

Q4の倍数を論理演算で表す。。

/*Prog32.cキーボードから整数型変数aへデータを入力し、aの値が4の倍数のときは“4の倍数です”と表示し、そうでないときは、“4の倍数ではありません”と表示する。ただし、整数データのビット数はわからないものとし、計算にはビットごとの論理演算のみを用いる。*/

#include <stdio.h>
int main(void)

{

int a;
printf("整数を入力して下さい! "); scanf("%d", &a);
(a % 4 ) ? printf("4の倍数ではありません。\n", a)
:printf("4の倍数です。\n", a);

return(0);

}

4の倍数を論理演算で表す方法がわかりません。。
自分では上記のように算術を使うやりかたしかわかりませんでした。
よろしくお願いします!

Aベストアンサー

#include <stdio.h>
int main(void)
{

int a;
printf("整数を入力して下さい! ");
scanf("%d", &a);
if(a%4==0){
printf("%dは4の倍数です。\n", a);
}
else{
printf("%dは4の倍数ではないです。\n", a);
}
return(0);
}
のまちがいか。

Qif文を使わずに奇数・偶数を判断

はじめまして。C言語解説サイトを巡ってみたのですが、if文無しの奇数偶数判断にまで辿りつかず頭を抱えています。
任意の数字を(指定回数分)打ち込み、奇数だった場合のみ加算し合計を表示するというプログラムを作成したいのですが色々と規制がかかっており、if文・switch文は使用不可/ループも1回のみとなっています。
if文を使えれば x%2 == 1 で奇数と判断できるのですが・・・。

■ if文を使わず奇数・偶数かを判断→加算 の流れ

を是非教えて頂きたいです。お時間ありましたらご教授よろしくお願い致します。

Aベストアンサー

打ち込んだ数値が整数だったらの話ですが。

・偶数の場合2で割った余りは0 奇数の場合2で割った余りは1

・(上で余りとして出た)0を掛けた答えは0
・(上で余りとして出た)1を掛けた答えは奇数だった数値そのもの

というのを利用するとif文無しで奇数のみを加算できそうですね。

Q3のつく数字と3の倍数のみを表示するプログラム

C言語で3のつく数字と3の倍数のみ(1~150)を表示するプログラムを作りたいのですがどうすればいいのでしょうか?

Aベストアンサー

数字で全部処理するとしたら、ある数x(1~150)について

・xが3で割り切れるかどうか?(x%3が0かどうか)
・xの下1桁目が3であるかどうか?(x%10が3かどうか)
・xの下2桁目が3であるかどうか?(x%100/10が3かどうか)

以上のことをif文等で場合分けすればいいかなと思います。
(汎用性を考えるなら、No.2さんの考え方の方が良いです)

QC言語 最大値と最小値を求めて表示するプログラム

はじめまして。

C言語を学習中です。

下記の問題演習の解答として記載されているプログラムがどうしても理解できません。

特にプログラムの最後の方のwhile文で最大値と最小値の判定をしているのかと思いますが、どのような計算をして判定しているのでしょうか。

while (array[i] != -1) {
if (array[i] > *max) *max = array[i];
if (array[i] < *min) *min = array[i];
i++;

具体的に教えてください。

よろしくお願い致します。


●問題
0~100の範囲で入力された複数の数値の中から、
最大値と最小値を求めて表示するプログラムを作成せよ。
-1が入力された場合は入力の終わりと判定する。
ただし、最大値と最小値はmain関数以外の一つの関数の中で求める。
また、入力された数値を記憶する配列の要素数は10とし、
それ以上入力された場合はエラーが起きても仕方ないこととする。
ヒント:配列の中に -1 があればデータの終わりだと判断できる。
ヒント:最小値を探すには、最大値を記憶した変数との比較を繰り返せば良い。


●解答
#include <stdio.h>

void maxmin(int array[],int *max,int *min);

int main(void)
{
int i = 0,array[10],max,min;

do {
printf("%d 番目の数:",i + 1);
scanf("%d",&array[i]);
i++;
} while (array[i - 1] != -1);

maxmin(array,&max,&min);

printf("最大値 %d : 最小値 %d\n",max,min);

return 0;
}

void maxmin(int array[],int *max,int *min)
{
int i = 0;

*max = 0;
*min = 100;

while (array[i] != -1) {
if (array[i] > *max) *max = array[i];
if (array[i] < *min) *min = array[i];
i++;
}
}

はじめまして。

C言語を学習中です。

下記の問題演習の解答として記載されているプログラムがどうしても理解できません。

特にプログラムの最後の方のwhile文で最大値と最小値の判定をしているのかと思いますが、どのような計算をして判定しているのでしょうか。

while (array[i] != -1) {
if (array[i] > *max) *max = array[i];
if (array[i] < *min) *min = array[i];
i++;

具体的に教えてください。

よろしくお願い致します。


●問題
0~100の範囲で入力された複数の数値の中から、
最大値と最小値を求...続きを読む

Aベストアンサー

>while (array[i] != -1) {
>if (array[i] > *max) *max = array[i];
>if (array[i] < *min) *min = array[i];
>i++;

手でコードを追いかけていくのが上達への近道だとは思いますが…。

今回は、データの範囲が0~100と決まっていますので、
まずは、仮の最大値として下限の0を、仮の最小値として上限の100を、
それぞれセットしています。
そして、配列の中身を、その時点での最大値や最小値と比べて、
データの方がその時点での最大値よりも大きければ最大値の値を更新し、
データの方がその時点での最小値よりも小さければ最小値の値を更新する、
というアルゴリズムです。

ループを脱出した(つまり、すべてのデータをチェックし終わった)段階で
変数maxやminに入っている値が、(仮ではない)真の最大値や最小値となります。

QC言語 重複しない4ケタの乱数 教えてください

以下のプログラムを使って重複しない4ケタの乱数を発生させ、数当てゲームを作りたいです。
以下のプログラムで乱数を4つ作ることができたのですが、重複してしまいます。
どのようにすればよいのですか?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
main()
{
int i,d;
float f;
unsigned long time1;
unsigned seed;
time(&time1);
seed=time1;
srand(seed);
for (i=0;i<4;i++)
{
f=rand();
d=f*10/32768.0;
printf ("%d ",d);
}
}

Aベストアンサー

やりたいことは、”1ケタの数字(0~9)を4つ重複しないように乱数生成する”ですかね?
(4ケタの数字1000~9999ではないですよね?プログラムの内容的に。)

実現方法はいくつかあると思います。

案1.配列に生成した乱数を記録しておいて、
  2回目以降の乱数で抽選された数字が、
  配列に記録してある数字と一致するかチェックし、
  一致した場合は、一致しなくなるまで再度乱数生成をし直す。

  以下のプログラムは一例。(手元がC++の環境なので微妙に違うけど。)
  これが良い例というわけではないです。何かバグあるかもしれん。
int i, d;
srand((unsigned)time(NULL));
int ary[4];//生成した乱数格納用
//配列初期化、乱数で選ばれる事が無い-1を入れておく。
for (i = 0; i < 4; i++){
ary[i] = -1;
}
for (i = 0; i<4; i++)
{
while (ary[i] < 0){
d = rand() % 10;
if ((d != ary[0]) && (d != ary[1]) && (d != ary[2])){ //要素数が少ないので横着
ary[i] = d;
}
}
printf("%d ", d);
}

案2.配列(要素数10)に0~9の数字を入れておいて、
  ランダムに配列内の並び順をシャッフルして、
  その後、先頭の4つを出力する。
  参考:http://mementoo.info/archives/746


案2の方がスマートな気がしますが、せっかく途中までプログラム作ってたようなので、
案1はそれの改造版ですな。

やりたいことは、”1ケタの数字(0~9)を4つ重複しないように乱数生成する”ですかね?
(4ケタの数字1000~9999ではないですよね?プログラムの内容的に。)

実現方法はいくつかあると思います。

案1.配列に生成した乱数を記録しておいて、
  2回目以降の乱数で抽選された数字が、
  配列に記録してある数字と一致するかチェックし、
  一致した場合は、一致しなくなるまで再度乱数生成をし直す。

  以下のプログラムは一例。(手元がC++の環境なので微妙に違うけど。)
  これが良い例というわけ...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング