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

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

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

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

Q&A

解決済

7回答

2603閲覧

C言語で変数を使わずに配列の中身分ループさせたい

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2018/05/23 21:49

編集2018/05/23 23:06

C言語で、変数(ローカル、グローバル共に)を使わずに配列分ループさせて配列の中身を取り出すことは可能なのでしょうか?

例えば、このようなロジックを考えてみたのですが、
いまくいきません。

C

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8int main(void){ 9 10 // 構造体配列に初期値セット 11 person1 person[] = { 12 {1,2}, 13 {2,3} 14 }; 15 16 // for文を初期値なしでpersonのアドレスインクリメントでループ 17 for(;person !=null;person++){ 18 printf("%d\n", person.no1); 19 } 20 21}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

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

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

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

maisumakun

2018/05/23 22:54

なぜ「ローカル変数を使わずに」やらないといけないのでしょうか。
yohhoy

2018/05/24 00:15

あなたの言う「変数」とは何ですか?personは変数ではないという認識でしょうか?
退会済みユーザー

退会済みユーザー

2018/05/26 00:15

いいえ。personも変数でした。
a_saitoh

2018/05/28 02:15

処理すべきデータの入った配列は無しではすみませんよね。それ以外に変数を使わずに、ということですか?
guest

回答7

0

関数を作れば出来るかと思いましたが、関数の仮引数もだめだと言うことだと、無理でしょう。

一応、関数版を書いておきます。

C

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8void foo(person1 *p, person1 *q){ 9 if(p<q){ 10 printf("%d\n", p->no1); 11 foo(p+1, q); 12 } 13} 14 15int main(void){ 16 person1 person[] = { 17 {1,2}, 18 {2,3}, 19 }; 20 foo(person, person+sizeof person/sizeof *person); 21}

そもそも仮引数を使って良いなら、

C

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8int main(int i){ 9 person1 person[] = { 10 {1,2}, 11 {2,3}, 12 }; 13 14 for(i=0; i<sizeof person/sizeof *person; i++){ 15 printf("%d\n", person[i].no1); 16 } 17 18}

投稿2018/05/24 01:47

編集2018/05/24 04:04
otn

総合スコア84423

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

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

退会済みユーザー

退会済みユーザー

2018/05/26 00:25

うーん、そうですね。。。 引数でも変数なので。。。
otn

2018/05/26 03:05

他の回答へのコメントを見ると、「変数(引数を含む)を使いたくない」じゃなくて、「変数(引数を含む)への明示的な代入・更新を書きたくない」ですか? 仮引数への実引数の代入はOKということ? あるいは、constの付いた変数は変数じゃない扱い?
guest

0

ベストアンサー

(簡単のためサンプルは自前です)例えば、以下のような再帰関数を使うという方法が挙げられます。
これは純粋関数型言語Haskelなどで用いられる方法です。

C

1//ar[]は終端要素0で終わるものとする。 2void dumpElement(int ar[]) 3{ 4 if(ar[0]){ 5 printf("%d\n", ar[0]); 6 dumpElement(&ar[1]); 7 } 8} 9//または↓の形もあり 10 11void dumpElement(int ar[], int length) 12{ 13 if(0 < length){ 14 printf("%d\n", ar[0]); 15 dumpElement(&ar[1], length - 1); 16 } 17}

以下追記、
**皆さんの回答を見ていると「変数使用しないなんて無理」**という意見がありますけれど、変数を使用しない言語も実在します(純粋関数型言語)。もちろん、各定義時に初期値のセットだけは必要ですけれど、値の更新を行わない(定数として扱う)プログラム技法というのも実際にあります。例えばHaskellでは本例のように、再帰を使うことで(C言語でいうところの変数の値の更新を)実現するという手があります。当然ながら、プログラミングに強い制約を課すことにはなりますが、これはこれで一つのやり方と呼べます。

投稿2018/05/25 14:18

編集2018/05/25 15:57
HogeAnimalLover

総合スコア4830

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

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

退会済みユーザー

退会済みユーザー

2018/05/26 00:21

おお!なんと素晴らしい! これならインクリメントを繰り返しながら変数を使わずにループ処理ができますね! この方法でやってみます。 ありがとうございました~
cateye

2018/05/26 00:50

>しかし、引数でも変数なので。。。と、asmさんの回答に言っていますがdumpElement()の引数はいいのでしょうか?
退会済みユーザー

退会済みユーザー

2018/05/26 01:56

ええ、そうなんですが、これならint ar[]の代わりにconstを使ってもいけるなと。 ん?無理か? ちょっとやってみます。
HogeAnimalLover

2018/05/26 05:50

未確認ですがconst配列にしてもできるはずですよ。
cateye

2018/05/26 08:04 編集

dumpElement()に渡した時点で、int ar[]はint *pと等価(ポインタは変数)ですから配列の中身を変更しなければconstでもOKです。私が言いたかったのは、「引数でも変数」と言いながらなぜOKなのかが知りたかったのです。 プロの方が多いと思いますので、こういった事には敏感だと思いますが?
HogeAnimalLover

2018/05/26 08:25

「指し示す中身の変更をしない。」のみでなく、「指し示す先の変更もしない」ですので、より制限が強い形で実現しています。 asmさんの回答では「指し示す先の変更」を許容しています。
guest

0

C++ならばrange-based forで

C++

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8int main(void){ 9 person1 person[] = { 10 {1,2}, 11 {2,3} 12 }; 13 for(person1& p : person){ 14 printf("%d\n", p.no1); 15 } 16}

出来ます。

どうしてもC言語で変数を使いたくないなら…

C

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8void for_loop(void* base, void* end, size_t elem_size, void (*func)(void* it)){ 9 for(;base < end; base += elem_size) 10 func(base); 11} 12 13void print_person(person1* p){ 14 printf("%d\n", p->no1); 15} 16 17int main(void){ 18 person1 person[] = { 19 {1,2}, 20 {2,3} 21 }; 22 for_loop(person, person + sizeof(person) / sizeof(*person), sizeof(person1), print_person); 23}

引数は変数ではないという言葉遊びの域ですが可能です。

あとは繰り返しの方法について指示がないのでCプリプロセッサを用いる事で可能なようにも思います。


追記
あれ?const修飾したいだけなのかな?

c

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8int main(void){ 9 person1 person[] = { 10 {1,2}, 11 {2,3} 12 }; 13 for(const person1 *cur = person, *const end = cur + (sizeof(person) / sizeof(*person)); 14 cur < end; 15 cur++){ 16 printf("%d\n", cur->no1); 17 } 18}

投稿2018/05/24 01:58

編集2018/05/26 06:25
asm

総合スコア15147

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

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

退会済みユーザー

退会済みユーザー

2018/05/26 00:24

うーん、なるほど。。。 しかし、引数でも変数なので。。。
guest

0

C

1 person1 person[] = { 2 {1,2}, 3 {2,3}, 4 {-1,0} /* 終わりの印を入れておく */ 5 };

とかしておいて、

C

1for(p=person; p->no1 >= 0; p++){

じゃ、だめ?

投稿2018/05/24 02:17

nob.

総合スコア711

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

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

退会済みユーザー

退会済みユーザー

2018/05/26 00:22

ごめんなさい。 これだとそもそもpが変数なので。。。
guest

0

普通に書けば、以下のようになりますが削除したい(使いたくない)のはどれでしょう?

c

1int main(void){ 2 3 // 構造体配列に初期値セット 4 person1 person[] = { 5 {1,2}, 6 {2,3} 7 }; 8 9 // for文を初期値なしでpersonのアドレスインクリメントでループ 10// for(;person != NULL;person++){ 11 // personは配列の先頭アドレスなので左辺値にはなれない。(インクリメント不可) 12 for(int i= 0; i < sizeof(person)/sizeof(person1);i++){ 13 printf("%d\n", person[i].no1); 14 } 15 16 return 0; 17} 18

題意とは違うと思いますが、再起を使うと・・・

c

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8void print(person1 *pp) 9{ 10 if( pp->no1== 0){ 11 return; 12 } 13 printf("%d\n", pp->no1); 14 // 15 print(++pp); 16} 17 18int main(void){ 19 20 // 構造体配列に初期値セット 21 person1 person[] = { 22 {1,2}, 23 {2,3}, 24 {0,0} 25 }; 26 27 print(person); 28 29 return 0; 30} 31

「追記」こういったこと?

c

1#include <stdio.h> 2 3typedef struct { 4 int no1; 5 int no2; 6} person1; 7 8void print(const person1 * const pp) 9{ 10 if( pp->no1 != 0){ 11 printf("%d\n", pp->no1); 12 print(pp+1); 13 } 14} 15 16int main(void){ 17 18 // 構造体配列に初期値セット 19 person1 person[] = { 20 {1,2}, 21 {2,3}, 22 {0,0} 23 }; 24 25 print(person); 26 27 return 0; 28}

usr~/test % ./a.out
1
2
usr~/test %

投稿2018/05/24 01:33

編集2018/05/26 08:48
cateye

総合スコア6851

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

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

otn

2018/05/24 02:48

仮引数がOKであれば、mainの仮引数を宣言してそれを使えばいいかと。
退会済みユーザー

退会済みユーザー

2018/05/26 00:28

この中だと変数iを使いたくないのと、personはconstにしたいです。 でも、constだと++ができないんですよね。。。
cateye

2018/05/26 01:24

personは配列の先頭アドレス(固定です)からもともと左辺値にはなりませんd++
guest

0

おそらくループ用のカウンタを使わずに、ってことなんでしょうか。
であるなら、構造体の配列のポインタくらいはないと実現できません。
但しそうした場合でも配列の終端が提示コードの情報ではわからないので、ループの終わりが判定できません。

c

1person1 *pperson = (person1*)person; 2for( ; /* ここが書けない */ ; pperson++){ 3 printf("%d\n", pperson->no1); 4}

あ、いやアドレス計算すればできるか。

c

1person1 *pperson = (person1*)person; 2for( ; pperson < (person + sizeof(person)); pperson++){ 3 printf("%d\n", pperson->no1); 4}

投稿2018/05/23 23:46

ttyp03

総合スコア16996

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

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

cateye

2018/05/24 01:39

(person + sizeof(person))って、person+16になりませんか?
ttyp03

2018/05/24 01:44

なりますね(int型が4バイトの場合) ダメですか?
ttyp03

2018/05/24 01:48

やってみたらダメでした orz 自分が何かを勘違いしている…。
cateye

2018/05/24 01:54

えっと、person+16は、&person[16]と同じですd^^;
ttyp03

2018/05/24 01:56

> cateyeさん ですね。 うっかりでした。 なので、personをキャストすればよさそう。 ((long)person + sizeof(person))
退会済みユーザー

退会済みユーザー

2018/05/26 00:35

すいません。 personはconstにしたいです。 そうすると、++できないんですよね。。。
ttyp03

2018/05/26 03:34

いえ、personのアドレスをppersonに入れてるでconstでも大丈夫ですよ。
guest

0

グローバル変数を使うということ?


無理ですねー、と言いながら考えてみました

C

1int main(void){ 2 3 // 構造体配列に初期値セット 4 person1 person[] = { 5 {1,2}, 6 {2,3} 7 }; 8 person1 *p; 9 // for文を初期値なしでpersonのアドレスインクリメントでループ 10 for(p=person;p<(person+(sizeof(person)/sizeof(*person));p++){ 11 printf("%d\n", p->no1); 12 }

これでどんなもんでしょw

投稿2018/05/23 21:55

編集2018/05/23 23:20
y_waiwai

総合スコア87719

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

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

退会済みユーザー

退会済みユーザー

2018/05/23 23:04

いいえ、グローバル変数も使ってはいけません。
y_waiwai

2018/05/23 23:05

なら無理ですね
y_waiwai

2018/05/23 23:21

と言いながら更新しましたw
退会済みユーザー

退会済みユーザー

2018/05/26 00:36

うーん、すいません。 p*も変数なのでそれも使いたくないです。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問