いつもお世話になっています。c言語初心者で、勉強中です。ポインタについて質問させて頂きます。課題で、N個(マクロで5と定義してある)の浮動小数データを入力すると 小さい順に並び換えて表示する(ソート)プログラムを作りたいのですが、i,jを使わず、ポインタをループ変数として使用させる方法が分かりません。よろしくお願いします。以下がコードです。
C言語
1コード 2```#include <stdio.h> 3 4#define N 5 5 6int main() 7{ 8 double arr[N]; 9 double tmp; 10 double *p,*q,*minptr; 11 printf("Please input %d double numbers\n", N); 12 for(i= 0; i< N; i++) 13ここのiを使わず、ループを回す方法を教えて下さい。 14 scanf("%lf", &arr[i]); 15 16 for(i = 0; i < N - 1; i++){ 17ここのiを使わず、ループを回す方法を教えて下さい。 18 minidx = i; 19 for(j = i + 1; j < N; j++){ 20ここのi,jを使わず、ループを回す方法を教えて下さい。 21 if(arr[j] < arr[minidx]) minidx = j; 22 } 23 tmp = arr[i]; 24 arr[i] = arr[minidx]; 25 arr[minidx] = tmp; 26 } 27 28 printf("Sorted data\n"); 29 for(i = 0; i < N; i++) { 30ここのiを使わず、ループを回す方法を教えて下さい。 31 printf("%f\n", arr[i]); 32 } 33 return 0; 34}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
こんにちは。
ポインタの中身は「アドレス」が入っていますが、アドレスは単なる数値です。
そのように考えると、原理的にはint型を使う場合と同じ操作でできます。
double型のサイズが8バイトの場合、例えば下記のようになります。(実際のアドレスとは異なります。)
変数 先頭アドレス
arr[0] 0x40000200
arr[1] 0x40000208
arr[2] 0x40000210
arr[3] 0x40000218
arr[4] 0x40000220
ならば、最初にarr[0]のアドレスを設定し、+8しつつ、arr[4]のアドレスを越えない間ループを継続すれば良いです。
そして、C言語のポインタはそれが指し示している先の「型」の情報も持っています。
今回の場合double型ですので8バイトあることをコンパイラは把握しています。
ですので、「ポインタを1つ進める」という自然な書き方で+8してくれます。
arr[0]のアドレスは&arr[0]で取り出せることは既にご存知ではないかと思います。
以上を纏めるとfor(i= 0; i< N; i++)
は下記のように書けます。(自分がコンピュータになってつもりで、上記のアドレスを1つ1つ当てはめて動きを考えてみて下さい。)
C
1double *p; 2double *end=arr+N; 3for(p=&arr[0]; p < end; p++)
他も同じ考え方でポインタへ変換できますので、頑張ってみて下さい。
投稿2016/11/12 01:26
編集2016/11/12 01:28総合スコア23272
0
ベストアンサー
for文とポインタのみで作成してみました。
改良してみました。minidxが使えませんでしたが。。。
c
1#include <stdio.h> 2#define N 5 3 4int main() 5{ 6 double arr[N]; 7 double tmp; 8 double *p,*q,*minidx; 9 printf("Please input %d double numbers\n", N); 10 11 for (p=arr; p - arr < N; p++ ){ 12 scanf("%lf",p); 13 14 for (q=arr; p - q > 0; q++){ 15 if (*p < *q){ 16 tmp = *q; 17 *q = *p; 18 *p = tmp; 19 } 20 } 21 } 22 23 printf("Sorted data\n"); 24 p=arr; 25 for (p=arr; p - arr < N; p++ ){ 26 printf("%f\n", *p); 27 } 28 return 0; 29}
c
1#include <stdio.h> 2#define N 5 3 4int main() 5{ 6 double arr[N]; 7 double tmp; 8 double *p,*q,*minidx; 9 printf("Please input %d double numbers\n", N); 10 11 for (p=arr; p - arr < N; p++ ){ 12 scanf("%lf",p); 13 } 14 15 for (p=arr; p - arr < N - 1; p++){ 16 for (q = arr + N - 1; q > p; q--) { 17 minidx=q-1; 18 if (*minidx > *q){ 19 tmp = *q; 20 *q = *minidx; 21 *minidx = tmp; 22 } 23 } 24 } 25 26 printf("Sorted data\n"); 27 p=arr; 28 for (p=arr; p - arr < N; p++ ){ 29 printf("%f\n", *p); 30 } 31 return 0; 32}
ポインターのみで作成すると言う事は、多分ポインターの課題だと思い作成しました。
c
1for (p=arr; p - arr < N - 1; p++){ 2 for (q = arr + N - 1; q > p; q--) { 3 minidx=q-1; 4 if (*minidx > *q){ 5 tmp = *q; 6 *q = *minidx; 7 *minidx = tmp; 8 } 9 } 10}
double arr[N];
double tmp;
double *p,*q,*minidx;
arrは、doubleの配列です、この場合doubleが5個並んで存在している事になります。
同様に他のポインター(*p,*q,*minidx)もdoubleで定義しています。
意味はp,q,minidxは、ダブルの値を持つアドレスを示すポインターです。
for (p=arr; p - arr < N - 1; p++){
p=arr;
&arr[0](アドレス)がforの最初、p=arr;で配列arrの先頭アドレスを p にセットします。
p++
先にp++の説明ですが、ポインターをインクレメント(+1)すると次のdouble分の長さの分のアドレスがセットされます。p++するとarr[1]を指す事になります。これで配列arr[0],[1]...と順番に差します。
例として char c = "abcd"; とした場合ポインターcは'a'のアドレスを指します。
c++すると'b'が指せますし、或いは(c+1)とも表現できます。
p - arr < N - 1;
pはfor分の中でarrの配列を0,1,2,3と順番に差していき、最終の4になったら終了させたいので
pのアドレスが配列[3]を指したら抜けて為にp - arr < 4 と指定しています。
中はバブルソートなので4個までで終了です。(この辺は大丈夫と思いますが)
p - arr
ポインターを引き算だとアドレスの差が答えでは?と思いますが、ポインターの引き算は
p++;と同様な0,1,2,3,4のアドレスの差でなくポインターの差が得られます。
for (q = arr + N - 1; q > p; q--) {
昇順で並べると言う事なので極一般的バブルソートロジックを採用しています。(ググルとでます)
多くのサンプルは配列[i]で表現していますが、これをポインターに置き換えただけです。
今回は少ない回数で行う方法ですので、他の方法でも可能です。
つたない説明ですので、ご質問にてカバーさせていただきます。
付録
/* バブルソートを行う */ int BubSort(int x[ ], int n) { int i, j, temp; for (i = 0; i < n - 1; i++) { for (j = n - 1; j > i; j--) { if (x[j - 1] > x[j]) { /* 前の要素の方が大きかったら */ temp = x[j]; /* 交換する */ x[j] = x[j - 1]; x[j - 1]= temp; } } /* ソートの途中経過を表示 */ ShowData(x, NUM_DATA); } }
C
1int main(void) { 2 double arr[5]; 3 double *p,*q; 4 p=arr; 5 q=&arr[4]; 6 printf("Pointer q-p:%d",q - p ); 7 return 0; 8}
投稿2016/11/12 03:46
編集2016/11/14 23:21総合スコア4070
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/15 10:16
2016/11/15 10:19
2016/11/15 10:28
2016/11/15 10:34
0
変数等は全て定義されているものを使い、i,jを使わずに書き直しました。
多分、これが答えです。
ただし、コンパイル等はしていませんのでその辺りはご了承下さい。
int main() { double arr[N]; double tmp; double *p,*q,*minptr; q = arr + N; printf("Please input %d double numbers\n", N); for(p = arr; p < (arr + N); p++) { // ここのiを使わず、ループを回す方法を教えて下さい。 scanf("%lf", p); } for(p = arr; p < (arr + N) - 1; p++) { // ここのiを使わず、ループを回す方法を教えて下さい。 minptr = p; for(q = p + 1; p < (arr + N); q++) { // ここのi,jを使わず、ループを回す方法を教えて下さい。 if(*q < *minptr) { minptr = q; } } tmp = *p; *p = *minptr; *minptr = tmp; } printf("Sorted data\n"); for(p = arr; p < (arr + N); p++) { // ここのiを使わず、ループを回す方法を教えて下さい。 printf("%f\n", *p); } return 0; }
投稿2016/11/14 04:51
総合スコア27
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
学生のようなので、まずは下記のURLからソート考えたかたを
http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/
ソート関数を利用した場合:
C言語
1#include <stdlib.h> 2#include <stdio.h> 3 4int compare_int(const void *a, const void *b) 5{ 6 return *(float *)a - *(float *)b ; 7} 8 9main() 10{ 11 float data[] = {4.0, 2.0, 3.0, 6.0, 3.0, 2.0, 1.0, 3.0, 5.0, 7.0}; 12 int i; 13 14 qsort(data, 10, sizeof(int), compare_int); 15 for (i = 0; i < 10; i++) { 16 printf("%d, %3f\n", i, data[i]); 17 } 18 printf("\n"); 19}
投稿2016/11/12 01:27
総合スコア1106
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
難しい課題です。i, j等の新たなint型変数を使わずにN回ループを回すという一般的な方法が無いからです。ということで、null終端文字列のようにnan終端double配列というものを考えてみました。null終端文字列がnullだったら終わりと判断するように、nan終端double配列はnanだったら終わりと判断します。scanfでnanが入力されることもありますが、nanはそもそも大きさが定義できずソートの対象にできないため、nanの入力は単純に無視することにしました。
C
1#include <math.h> 2#include <stdio.h> 3#include <stdlib.h> 4 5#define N 5 6 7// nan 未対応 8inline static int double_compare(const void *a, const void *b) 9{ 10 double ad = *(const double *)a; 11 double bd = *(const double *)b; 12 return (ad > bd) - (ad < bd); 13} 14 15int main(void) 16{ 17 double arr[N + 1] = {0}; // 全部 0 で初期化 N + 1 個にすること。 18 arr[N] = NAN; // 終端を nan にする。 19 20 printf("Please input %d double numbers\n", N); 21 // あらかじめ入っている nan まで 22 for (double *p = arr; !isnan(*p);) { 23 switch (scanf("%lf", p)) { 24 case 1: 25 if (isnan(*p)) { 26 // nan ならもう一回 27 *p = 0; 28 } else { 29 p++; 30 } 31 break; 32 case 0: 33 scanf("%*c"); // バッファを捨てる 34 break; 35 default: 36 fprintf(stderr, "stdin is end of file."); 37 return 1; 38 } 39 } 40 41 // qsort を使う。 42 qsort(arr, N, sizeof(double), double_compare); 43 44 printf("Sorted data\n"); 45 // nan まで 46 for (double *p = arr; !isnan(*p); p++) { 47 printf("%f\n", *p); 48 } 49 return 0; 50}
ソート部分は面倒だったのでqsortを使っています。
投稿2016/11/12 01:05
編集2016/11/12 01:10総合スコア21735
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/16 03:36