質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

17531閲覧

ポインタをループ変数として使用する

ikuo-biyori

総合スコア56

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/11/12 00:08

いつもお世話になっています。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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikuo-biyori

2016/11/16 03:36

アドレスでループを回していくということですね、分かりました。ありがとうございます。
guest

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
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikuo-biyori

2016/11/13 21:03

for (p=arr; p - arr < N - 1; p++){ for (q = arr + N - 1; q > p; q--) { minidx=q-1; if (*minidx > *q){ tmp = *q; *q = *minidx; *minidx = tmp; } } } すいません、ここのコードのところが何をしているかわかりません。教えてください。
ikuo-biyori

2016/11/15 10:16

くわしい説明をしていただきありがとうございます。ポインタのことが以前より分かるようになりました。
A.Ichi

2016/11/15 10:19

多分、修正した最初のソースが課題に近い形と思われます。
ikuo-biyori

2016/11/15 10:28

その件に関してですが、おかげさまで解決できました。以下が答えでした。 #include <stdio.h> #define N 5 int main() { double arr[N]; double tmp; double *p,*q,*minidx; printf("Please input %d double numbers\n", N); for (p=arr; p < arr+N; p++ ){ scanf("%lf",p); } for (p=arr; p < arr+N - 1; p++){/*(アドレスのループ)比較するのは2つの数だからarr+N-2回ループが回ればいい。*/ minidx=p;/*最小値アドレス指定*/ for(q=p+1;q<arr+N;q++){/*pの次のアドレスから最小値を決めるアドレスのループ*/ if(*q<*minidx)/*pとqの値比較*/ minidx=q;/*最小値アドレス変更*/ } tmp=*p;/*一時的な変数*/ *p=*minidx;/*最小値をpに代入*/ *minidx=tmp;/*最小値アドレス変更*/ // for (t=arr; t < arr+N; t++ ){ // printf(" %f :", *t); // } // printf("\n\n"); } printf("Sorted data\n"); //p=arr; for (p=arr; p < arr+N; p++ ){ printf("%f\n", *p); } return 0; }
A.Ichi

2016/11/15 10:34

ご自身で解決されたんですね良かったです。
guest

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

Yuki.

総合スコア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

nagaetty

総合スコア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
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問