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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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総合スコア84423
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総合スコア4830
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/05/26 00:21
2018/05/26 00:50
退会済みユーザー
2018/05/26 01:56
2018/05/26 05:50
2018/05/26 08:04 編集
2018/05/26 08:25
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総合スコア15147
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/05/26 00:24
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総合スコア6851
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
総合スコア16996
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/24 01:39
2018/05/24 01:44
2018/05/24 01:48
2018/05/24 01:54
2018/05/24 01:56
退会済みユーザー
2018/05/26 00:35
2018/05/26 03:34
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総合スコア87719
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。