前提
「アルゴ式」の問題で、出力例と私の出力が違っています。
出力例
4
1
3
Error
2
私の出力
0
4
1
3
3
https://algo-method.com/tasks/828
実現したいこと
可変長配列で配列の末尾に要素を追加(Push)と 配列の末尾を出力してから、配列の末尾を削除(Pop)するプログラムを作っています。配列に要素がない場合「Error」と表示します。
発生している問題・エラーメッセージ
エラーはないです。
該当のソースコード
C
1#include <stdio.h> 2#include <stdlib.h> 3#include <stdint.h> 4 5typedef struct 6{ 7 int *array; 8 int capa; 9 int len; 10} DynamicIntArray; 11 12DynamicIntArray * 13DynamicIntArray_New(int n) 14{ 15 DynamicIntArray *self = calloc(1, sizeof(*self)); 16 if (!self) { 17 return NULL; 18 } 19 self->capa = n; 20 self->array = calloc(self->capa, sizeof(int)); 21 if (!self->array) { 22 free(self); 23 return NULL; 24 } 25 return self; 26} 27 28DynamicIntArray * 29DynamicIntArray_Resize(DynamicIntArray *self, int32_t capa) 30{ 31 int32_t byte = sizeof(int); 32 int32_t size = byte * capa; 33 int *tmp = realloc(self->array, size); 34 if (!tmp) { 35 return NULL; 36 } 37 self->array = tmp; 38 self->capa = capa; 39 return self; 40} 41 42DynamicIntArray * 43DynamicIntArray_PushBack(DynamicIntArray *self, int elem) 44{ 45 if (self->len >= self->capa) { 46 if (!DynamicIntArray_Resize(self, self->capa * 2)) { 47 return NULL; 48 } 49 } 50 self->array[self->len++] = elem; 51 return self; 52} 53 54/*DynamicIntArray_Removeのみ自身で追加。あとは既存のコードを少し改良しました。*/ 55DynamicIntArray * 56DynamicIntArray_Remove(DynamicIntArray *self) 57{ 58 59 return self->len--; 60} 61 62void DynamicIntArray_Del(DynamicIntArray *self) 63{ 64 if(!self) { 65 return; 66 } 67 free(self->array); 68 free(self); 69} 70 71void DynamicIntArray_Show(const DynamicIntArray *self) 72{ 73 printf("%d\n", self->array[self->len]); 74} 75 76int main(void) 77{ 78 int N; 79 (void)scanf("%d", &N); 80 81 DynamicIntArray *ary = DynamicIntArray_New(N); 82 83 int A[101]; 84 for (int i = 0; i < N; i++) { 85 (void)scanf("%d", &A[i]); 86 DynamicIntArray_PushBack(ary, A[i]); 87 } 88 89 int Q; 90 (void)scanf("%d", &Q); 91 for (int i = 0; i < Q; i++) { 92 int query; 93 (void)scanf("%d", &query); 94 if (query == 0) { 95 int v; 96 (void)scanf("%d", &v); 97 DynamicIntArray_PushBack(ary, v); 98 } else if (query == 1) { 99 int size = sizeof(DynamicIntArray) / sizeof(DynamicIntArray); 100 if (size > 0) { 101 DynamicIntArray_Show(ary); 102 DynamicIntArray_Remove(ary); 103 } else { 104 printf("Error\n"); 105 } 106 107 } 108 } 109 110 return 0; 111 112}
試したこと
DynamicIntArray *
DynamicIntArray_Remove()関数を自身で追加しました。
補足情報(FW/ツールのバージョンなど)
「アルゴ式」のオンラインでジャッジするところでコードを書きました。
その問題、配列は固定長で良いのでは…。
hoshi-takanori様
固定長は他の方のコードで見ることができ分かったのですが、可変長で書かれているのが見当たらなかったので、ここで質問させていただきましたm( _ _ )m
N は 100 以下なので、固定長で十分ですね。
Zuishin様
固定長は他の方のコードを見て分かったのですが、どうしても可変長でのやり方を知りたくて、質問させていただきましたm( _ _ )m
DynamicIntArray_Resize の戻り値を使用していないようですが、いいんですか?
Show の時に表示するものが間違ってますね。あと、Remove は無条件でデクリメントして大丈夫?
Zuishin様
それは、DynamicIntArray_RemoveでDynamicIntArray_Resizeの戻りを使用していないという解釈で合っていますでしょうか?
PushBack です。
hosi-takanori様
1.具体的にはShowはどのようにするとよろしいでしょうか?
2.Removeはどのような条件でデクリメントしたらいいのか分からないです。
Zuishin様
ネット上で拾ってきたコードで、そのまま使っております。
以下が元のコードです。
PushBackでDynamicIntArray_Resizeの戻り値を使用しないとやはりダメなのでしょうか?
https://yu-nix.com/archives/c-array-push/#%E5%8F%AF%E5%A4%89%E9%95%B7%E9%85%8D%E5%88%97%E3%81%AB%E8%A6%81%E7%B4%A0%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95
1. 現在 self->array[self->len] を表示してますが、これは配列の最後の値ですか?
2. 出力例のデータでは、最初に 2 要素あって、その後 1 要素 Push して、それから何回 Pop してますか?
「どうしても可変長でのやり方を知りたくて」と言うなら、他人のコードを何も考えずにそのまま使うのではなく、それが何をしてるか理解しないと意味ないのでは…。
realloc は再割り当てに成功した場合、新しいアドレスを返しますが、それを破棄しています。
拾ったコードの信ぴょう性を確かめずそのまま使うのは良くありませんね。
まず固定長で作り、それで問題ないことを確かめた上でその可変長配列とやらに差し替えてみてください。
なお、C 言語で「可変長配列」という言葉は通常、ここで言われているものとは別のものを指します。
独自の言葉を使っている点で「臭い(信用できない)」と思ってください。
hoshi-takanori様
1.私のつたない解釈ではPushした後の配列の最後の値だと考えております。
2.5回Popしてると思います。
hoshi-takanori様
仰る通りです。。。
貴重なお時間割いてしまいすみません。
Zuishin様
貴重なお時間割いてしまいすみません。
まずは固定長で作ってみます。
あと、大変申し訳ないのですが、どの「可変長配列」が正しいのか分からないので、おすすめのネット上の記事があれば教えて頂きたいのですが駄目でしょうか?
Zuishin様
ありがとうございます!!!
さっそく読んでみたいと思います!!!
C の可変長配列は、配列のサイズを途中で増やせないので、質問者さんのやりたいこととは違うでしょうね。しかも、最近の C 言語規格では廃止されたらしいし…。
1. 長さ len の配列の場合、要素は array[0] から array[len - 1] までしかありません。array[len] にあるのはゴミです。
2. ちゃんと数えましょう。1 が 4 つ並んでるので、Pop は 4 回です。そして、最初に要素が 2 つあり、1 つ増えて 3 個になって、その後 4 回 Pop したらどうなりますか? それを防ぐにはどうすれば良いと思いますか?
hoshi-takanori様
1.配列がのインデックスが0から始まるからarray[len-1]なのですね。lenだと現在の要素数になってしまうのですよね?
2. 4回Popしたら配列に要素がなくなるのでErrorですよね。。。?
hoshi-takanoriさん
2は、多分、int size = sizeof(DynamicIntArray) / sizeof(DynamicIntArray);
で長さを計算しているつもりだと思います。
hoshi-takanoriさん
> C 言語規格では廃止されたらしい
廃止じゃなくて、オプションに落ちた、です。C99を2013年まで採用しなかった某MSが嫌ったのでしょうか。
size = sizeof(DynamicIntArray) / sizeof(DynamicIntArray);が要素の数だと思っているように思えて
hoshi-takanoriさんの2の指摘だと、whitehorse85921さんは、要素の数で判断してErrorを出している思っているので気が付きにくいと、思って書いたつもりです。
whitehorse85921さん、aryの要素の数はいくつですか?
tmp様
お心遣いありがとうございます。
aryの要素の数は4つだと思ってます。
皆様方々へ
少し体調を崩して返信が遅くなり大変に申し訳ございません。
皆様方々へ!!!
私じゃ思いつかない、問題提起ありがとうございました!!!
皆様方々にも感謝です!!!
回答1件
あなたの回答
tips
プレビュー