未解決ということは、エラトステネスの篩(ふるい)の手順を作れていないのかな。
たとえば n == 50 としたら、int num[50 + 1]; という51要素の配列を用意し、50(num[50])までの数字を検査する、のですよね。
プログラムを考える時、最初から、頭の中だけで、抽象的に考えようとするのはシンドイものです。手も動かして、紙に書き(描き)出してみると良いです。どんな処理をするのか、できるだけ具体的に書いてみるとこんな感じです(あくまで私なりの整理ですが)。質問者もこのようなシミュレーションを自分の手でやってみると良いと思います。
最初に num[2] = 2; 〜 num[50] = 50; と初期化しますね。これは私的に言えば** 2 〜 50 の全てを素数の候補とする**という意味です。
次に、for(k= 2; k<=n; k++) で k の値を変化させながら、繰り返し何かをする。それは合成数を「消し」ていく処理です。そのひとつひとつを書き出すと、こういうことです。
- k == 2 の時、num[2] はそのまま、num[4], num[6], num[8], ... は素数でない(消す)
- k == 3 の時、num[3] はそのまま、num[6], num[9], num[12], ... は素数でない(消す)
- k == 4 の時、num[4] はそのまま、num[8], num[12], num[16], ... は素数でない(消す)
- k == 5 の時、num[5] はそのまま、num[10], num[15], num[20], ... は素数でない(消す)
- k == 6 の時、・・・
たとえば k == 2 の時、num[4], num[6], num[8], ... num[50] を消す=素数でなくする処理を繰り返すので、これもまたループです。つまり、for ループの中にループを書いて、全体は二重のループで篩を実現できることを意味します。中のループも for ループで書けますが for に拘る必要はありません。
では、「素数でない、消す」とは具体的にどうすることか。
たとえば num[4] = 4; と初期化したのは 4 も素数候補にしたのでした。もちろん 4 は素数ではないので、まもなく「消し」て候補から外しますが、それは num[4] を配列から抜き去るという意味ではありません(いや、抜きたくても、できない笑)。
この場合、num[4] を消すとはバツ印をつけるイメージです。よくやる手は num[4] に 0 とか -1 のような値を代入する事です。ここでは 0 という値をバツ印として代入してみましょう。
そのまま何もしない num[2], num[3] などは、初期化した時点の 2, 3 という値が最後まで残ります。そして、そのような数は素数というわけです。
プログラムの後半では、整数 i が素数かどうかを調べる必要があります。
num[i] の値が 0 かどうかを調べれば判断がつくということ。
ともかく、k == 2 の場合 num[4], num[6], num[8], ... num[50] にバツをつけるようなループ・・・どうですか、ループは見えてきましたか?
なお、「そのまま」とは、たとえば k == 2 の時、num[2] に対して何もしないという事。その時点の値(それは 0 かもしれない)がそのまま残ります。
そもそも間違っているならご指摘頂きたく
「▶︎ その数が消されていなければ・・・」とするなら判断・検査することを意味しますが、素数でないとして消す時に、既に消されているかどうか(値が 0 か否か)を考慮する必要があるでしょうか。ありませんね。無条件に消して構わないのです。また、何度バツ印をつけようがバツ印に違いはありません。要するに、そのような判断・検査をする必要はありません。
なお、このようにプログラムの要所要所に、するべき事・処理の概要を予め書く、そののち実際のコードを書く、というのはコーディングの進め方として大変良いやり方です。つまり、コメントとしてプログラム中に残すのです。これを意識的に身につけることをおすすめします。プログラムを書く・保守するのが人間である以上、コメントはプログラムの中の重要な要素です。
ということで、疑問点は聞いてください。