プロが教える店舗&オフィスのセキュリティ対策術

こんにちは
現在学校でC言語の初歩を習っているのですが、いきなり挫折しています。
先日学校で
ファイル名…prime
引数   …int
戻り値  …int
内容   …引数に一番近い素数をかえす
といったプログラムをかけと言われたのですが、
書き方が全く分からない上に、たとえ先生に聞いたとしても難しく説明されてよくわかりません。
自分なりに調べてみたのですがそれでもわかりません。
次の授業(明日27日)で発表しなくてはいけないのでできるだけ更に焦っています;
どなたか詳しく教えていただけないでしょうか。

A 回答 (7件)

さらに変更。



int near_prime(int n)
{
int p1 = n + !(n & 1), p2 = n - !(n & 1);

if(n <= 2) return 2;
while(!is_prime(p2)){
if(is_prime(p1)) return p1;
p1 += 2;
p2 -= 2;
}
return p2;
}
    • good
    • 0

 変更


int near_prime(int n)
{
int p1 = n + !(n & 1), p2 = n - !(n & 1);

if(n <= 2) return 2;
while(!is_prime(p1)) p1 += 2;
while(!is_prime(p2)) p2 -= 2;
if(p1 / 2 + p2 / 2 + 1 >= n) return p2;
return p1;
}
    • good
    • 0

#include <stdio.h>



int is_prime(int n)
{
int i;

if(!(n & 1)) return 0;
for(i = 3; i * i <= n; i += 2){
if(!(n % i)) return 0;
}
return 1;
}

int near_prime(int n)
{
int p1 = n, p2 = n;

if(n <= 2) return 2;

while(!is_prime(p1)) ++ p1;
while(!is_prime(p2)) -- p2;
if(p1 / 2 + p2 / 2 + 1 >= n) return p2;
return p1;
}

int main(void)
{
int n;

scanf("%d", &n);
printf("%d %d\n", n, near_prime(n));
return 0;
}
    • good
    • 2

// prime.cpp : コンソール アプリケーションのエントリ ポイントを定義します。


//
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>

// こういう問題の場合
// 問題を分けて考える(分割統治という)が有効です
//
// ある自然数Nが与えられ、
// Nは素数であるか否か判定せよ
// というのは簡単な問題です
// (1とその数以外で割ってみれば良い)
//
// ある数Nに一番近い素数というのが少し難しいです
//
// そこで場合分けをしましょう
// A) Nが素数の場合
// Nそのものが解になります
// B) Nが素数でない場合
// 解の候補は2つあります
// 一つ目はNより小さい数で最大の素数
// これをM1とします
// 他の一つはNより大きくて最小の素数
// これをM2とします
// M1とM2のうち、Nに近いほうが解となります
//
// ここでさらに"近い"ということの意味も考える
// 必要があります
// 近いということは”距離が短い"ということです
// 距離を測るには差を求めれば良いですね
// M1 < N < M2なので
// N - M1 が M2 - Nより小さければM1が近い
// N - M1 が M2 - Nより大きければM2が近い
// ことになります
//
// では,等しい場合はどうなるでしょう
// 問題文からは読み取れません
// 私は数学者でないのでわかりませんが
// もしかしたら、このようなケースはあり得ない
// ことが証明されているのかも知れません
//
// しかし、わかりませんので
// 同じ距離の場合は小さい方(M1)を返すことに
// します

// 与えられた数が素数であるかどうかを調べる関数です
// 素数であれば1、そうでなければ0を戻します
static int IsPrime(int n)
{
int i;

// 1は素数ではありません
// ここでは自然数しか扱わないので0以下の整数が
// 与えられることはあり得ないのですが
// 安全のため1か?ではなく1以下か?で判定します
if (n <= 1)
return 0; // 素数でないので0を返します

// 2は素数です
if (n <= 2)
return 1;

// 3以上の場合です
// 3は素数であるとわかりきっているので
// 計算するまでもないのですが
// 無限にifで分岐するわけにもいきませんから
// ここからは計算することにします

// 全ての自然数は1とその数自身で割り切れることは
// 自明です
// よって2とその数(n - 1)以下で割り切れるものが
// あれば素数といえます

for (i = 2; i < n; ++i)
{
if (n % i == 0)
{
// 2以上n-1以下の自然数iで割り切れました
// 素数ではありません
return 0;
}
}

// 2以上n-1以下の自然数で割り切れるものはありませんでした
// つまり1とnでしか割り切れません
// 素数です
return 1;
}

// m1, m2の内nに近い方を返します
// 等距離の場合は小さい方とします
static int GetNearInt(int m1, int m2, int n)
{
int d1, d2;
// m1, m2, nの並び順に依存すると使いにくい関数と
// なってしまいます
// それを避けるため絶対値で比較します
d1 = abs(m1 - n);
d2 = abs(m2 - n);
if (d1 == d2)
{
// 等距離の場合です
// 小さい方を返します
return m1 < m2 ? m1 : m2;
}
else
{
// 距離が小さい方を返します
// d1がm1とnの距離
// d2がm2とnの距離です
return d1 < d2 ? m1 : m2;
}
}

// 与えられた数未満で最大の素数を返します
static int GetMaxPrime(int upperLimit)
{
int i;
// 上限から減少し、素数を見つけます
// 最小の素数は2なので、2以下を調べる必要はありません
for (i = upperLimit; i >= 3; i--)
{
if (IsPrime(i))
{
// 素数を見つけました
return i;
}
}

// 与えられた範囲で3以上の素数はありません
// 最大の素数は2に決定です
return 2;
}

// 与えられた数より大きくて最小の素数を返します
// 最大の整数まで調べて見つからない場合は-1として
// エラーを知らせます
static int GetMinPrime(int LowerLimit)
{
int i;
// 下限から上昇し、素数を見つけます
// 最大の整数で打ち切ります
for (i = LowerLimit; i < INT_MAX; i++)
{
if (IsPrime(i))
{
// 素数を見つけました
return i;
}
}

// 最大の整数値未満では素数がありませんでした
// 最大の整数が素数ならその値を返します
if (!IsPrime(INT_MAX))
return -1;
else
return INT_MAX;
}


// 引数に一番近い素数をかえす関数です
static int GetNearPrime(int n)
{
int m1, m2;

// nが1なら一番近い素数は2です
if (n <= 1)
return 2;

// nが素数ならそのまま返します
if (IsPrime(n))
return n;

// n未満の最大の素数を求めます
m1 = GetMaxPrime(n);

// nより大きくて最小の素数を求めます
// 求められない可能性もあります
m2 = GetMinPrime(n);

if (m2 < 0)
{
// nより大きい素数は見つかりませんでした
// (計算限界に達したため)
// 仕方ないのでn未満の最大の素数を
// 最も近い素数に決定します
return m1;
}
else
{
// n未満の最大の素数及び
// nより大きい最小の素数の両者が見つかりました
// 距離の近い方が
// 最も近い素数です
return GetNearInt(m1, m2, n);

}
}


// 引数に一番近い素数をかえす
int main(int argc, char* argv[])
{
int n;

// 引数は"プログラム名", "整数"の2個でなければ
// なりません
if (argc < 2)
{
printf("usage : prime [Number]\n");
return -1;// エラーとします
}

// 引数はargv[]で渡されます
// argv[0] : プログラム名(prime)
// argv[1] : 整数(を表す文字列)
// 入力ミスでargv[1]に整数以外が渡される可能性も
// あります

// 文字列を整数に変換します
// いろんな方法がありますが
// scanf()が最も汎用性があります
// atoi()でも実装できます
// ただし、atoi()は変換できない場合は0を戻します
// 0を正しく変換できた場合も同じ0で区別できない
// 弱点があります
// その分速いです
// 今回は0がエラーなのでatoiを採用します
// 0も正しいデータとして扱いたい場合
// atoi()は使えないのでscanf()を用います
n = atoi(argv[1]);
if (n <= 0)
{
printf("usage : prime [Number]\n");
printf("Numberは自然数でなければなりません。\n");
return -1;
}

n = GetNearPrime(n);
printf("最も近い素数は %d です。\n", n);

return n;
}
    • good
    • 1

>たとえ先生に聞いたとしても難しく説明されてよくわかりません。


で、難しく説明されて、あなたはどうしたのでしょうか?
わかったふうな顔をして、そのまま帰ってきたのでしょうか?

わからないなら、わからないと言わないと、先生も立場がないです。
わからないと言ってくれれば、どこからわからないのかを探りながら教えることもできます。

>大まかに言ってしまえば先ほどのすべてに該当します。
ということは、Hellow Worldすらわからないのでしょうか。
その段階では明日までに素数を返す関数を書くのは非常に難しいと思われます。
ただの課題ならまだしも、発表ということは、その場で突っ込みをうける可能性が大でしょう。そうなると、人の回答の丸写しではより大きな恥をかくのが目に見えてます。

もう夕方ですが、もう一度先生に相談することをおすすめします。

これが、あと一週間、いや3日もあるんだったら、こんな掲示板でもなんとかなるかもしれませんが、明日までというのでは無理ですねぇ。
    • good
    • 0

こんにちは。



 下記サイトをご参照下さい。
  http://www.sgnet.co.jp/c/8-1.htm
  C言語の関数の作り方を順を追って書いてあります。
  1.mainで書いて見る。(p1前半)
  2.関数にする。(p1後半)
  3.関数から戻り値を受け取れるようにする。(p3)

では。
    • good
    • 0

答えを丸ごと書いたら「課題」の勉強にはならないので。



>書き方が全く分からない上に、
・関数の定義がわからない
・素数を求める方法がわからない
・それ以前にC言語そのものがわからない
のいずれでしょうか?

>たとえ先生に聞いたとしても難しく説明されてよくわかりません。
というのは質問の仕方に問題があると思います。
「何がどうわからないのか」をきちんと説明できていますか?
この質問文からは上記のいずれとも取れますよ。
質問者さんが「わからない」のはどの部分ですか?

この回答への補足

いろいろと不備があって申し訳ありません。
大まかに言ってしまえば先ほどのすべてに該当します。
まず何をして、次にこれをして、という流れもわからない上に、
仮に完成したプログラムを見せられて、ここでこれがこうなっているからこういった結果になる、という説明もできません。
これが現状なのですが…

補足日時:2009/05/26 16:03
    • good
    • 0

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