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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

829閲覧

C言語の可変長配列で配列の末尾を削除する方法で詰まっています。

whitehorse85921

総合スコア34

C

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2022/06/09 09:27

前提

「アルゴ式」の問題で、出力例と私の出力が違っています。

出力例
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/ツールのバージョンなど)

「アルゴ式」のオンラインでジャッジするところでコードを書きました。

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

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

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

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

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

hoshi-takanori

2022/06/09 09:41

その問題、配列は固定長で良いのでは…。
whitehorse85921

2022/06/09 09:44

hoshi-takanori様 固定長は他の方のコードで見ることができ分かったのですが、可変長で書かれているのが見当たらなかったので、ここで質問させていただきましたm( _ _ )m
Zuishin

2022/06/09 09:46

N は 100 以下なので、固定長で十分ですね。
whitehorse85921

2022/06/09 09:48

Zuishin様 固定長は他の方のコードを見て分かったのですが、どうしても可変長でのやり方を知りたくて、質問させていただきましたm( _ _ )m
Zuishin

2022/06/09 09:54

DynamicIntArray_Resize の戻り値を使用していないようですが、いいんですか?
hoshi-takanori

2022/06/09 09:56

Show の時に表示するものが間違ってますね。あと、Remove は無条件でデクリメントして大丈夫?
whitehorse85921

2022/06/09 09:58

Zuishin様 それは、DynamicIntArray_RemoveでDynamicIntArray_Resizeの戻りを使用していないという解釈で合っていますでしょうか?
Zuishin

2022/06/09 09:59

PushBack です。
whitehorse85921

2022/06/09 10:01

hosi-takanori様 1.具体的にはShowはどのようにするとよろしいでしょうか? 2.Removeはどのような条件でデクリメントしたらいいのか分からないです。
hoshi-takanori

2022/06/09 10:07

1. 現在 self->array[self->len] を表示してますが、これは配列の最後の値ですか? 2. 出力例のデータでは、最初に 2 要素あって、その後 1 要素 Push して、それから何回 Pop してますか?
hoshi-takanori

2022/06/09 10:09

「どうしても可変長でのやり方を知りたくて」と言うなら、他人のコードを何も考えずにそのまま使うのではなく、それが何をしてるか理解しないと意味ないのでは…。
Zuishin

2022/06/09 10:11

realloc は再割り当てに成功した場合、新しいアドレスを返しますが、それを破棄しています。 拾ったコードの信ぴょう性を確かめずそのまま使うのは良くありませんね。 まず固定長で作り、それで問題ないことを確かめた上でその可変長配列とやらに差し替えてみてください。 なお、C 言語で「可変長配列」という言葉は通常、ここで言われているものとは別のものを指します。 独自の言葉を使っている点で「臭い(信用できない)」と思ってください。
whitehorse85921

2022/06/09 10:12

hoshi-takanori様 1.私のつたない解釈ではPushした後の配列の最後の値だと考えております。 2.5回Popしてると思います。
whitehorse85921

2022/06/09 10:17

hoshi-takanori様 仰る通りです。。。 貴重なお時間割いてしまいすみません。
whitehorse85921

2022/06/09 10:22

Zuishin様 貴重なお時間割いてしまいすみません。 まずは固定長で作ってみます。 あと、大変申し訳ないのですが、どの「可変長配列」が正しいのか分からないので、おすすめのネット上の記事があれば教えて頂きたいのですが駄目でしょうか?
whitehorse85921

2022/06/09 10:32

Zuishin様 ありがとうございます!!! さっそく読んでみたいと思います!!!
hoshi-takanori

2022/06/09 10:54

C の可変長配列は、配列のサイズを途中で増やせないので、質問者さんのやりたいこととは違うでしょうね。しかも、最近の C 言語規格では廃止されたらしいし…。 1. 長さ len の配列の場合、要素は array[0] から array[len - 1] までしかありません。array[len] にあるのはゴミです。 2. ちゃんと数えましょう。1 が 4 つ並んでるので、Pop は 4 回です。そして、最初に要素が 2 つあり、1 つ増えて 3 個になって、その後 4 回 Pop したらどうなりますか? それを防ぐにはどうすれば良いと思いますか?
whitehorse85921

2022/06/09 11:20

hoshi-takanori様 1.配列がのインデックスが0から始まるからarray[len-1]なのですね。lenだと現在の要素数になってしまうのですよね? 2. 4回Popしたら配列に要素がなくなるのでErrorですよね。。。?
tmp

2022/06/09 11:31

hoshi-takanoriさん 2は、多分、int size = sizeof(DynamicIntArray) / sizeof(DynamicIntArray); で長さを計算しているつもりだと思います。
thkana

2022/06/09 12:30

hoshi-takanoriさん > C 言語規格では廃止されたらしい 廃止じゃなくて、オプションに落ちた、です。C99を2013年まで採用しなかった某MSが嫌ったのでしょうか。
tmp

2022/06/09 13:05

size = sizeof(DynamicIntArray) / sizeof(DynamicIntArray);が要素の数だと思っているように思えて hoshi-takanoriさんの2の指摘だと、whitehorse85921さんは、要素の数で判断してErrorを出している思っているので気が付きにくいと、思って書いたつもりです。 whitehorse85921さん、aryの要素の数はいくつですか?
whitehorse85921

2022/06/11 09:11

tmp様 お心遣いありがとうございます。 aryの要素の数は4つだと思ってます。
whitehorse85921

2022/06/11 09:12

皆様方々へ 少し体調を崩して返信が遅くなり大変に申し訳ございません。
whitehorse85921

2022/06/11 09:57

皆様方々へ!!! 私じゃ思いつかない、問題提起ありがとうございました!!! 皆様方々にも感謝です!!!
guest

回答1

0

ベストアンサー

ご提示のコードはご自身のモノでは無いようですので、最初から組んだ方が早いでしょう。
スタックであれば push/pop だけあれば良いはずです。
扱うデータの範囲が正数だけですので、 pop 時にデータが無ければ -1 を返すことで "Error" を表現出来ます。
ついでに(?) 入力が面倒なので直接 push/pop してみました。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5typedef struct { 6 int cap; 7 int i; 8 int v[0]; 9} STACK; 10 11STACK *create() { 12 STACK *s = malloc(sizeof(STACK)); 13 if(s == NULL) { 14 fprintf(stderr, "malloc error."); 15 return NULL; 16 } 17 s->cap = 0; 18 s->i = -1; //empty 19 return s; 20} 21 22void delete(STACK *s) { 23 free(s); 24} 25 26STACK *push(STACK *s, int v) { 27 if(s->i + 1 == s->cap) { 28 STACK *p = realloc(s, sizeof(STACK) + sizeof(int) * (s->cap + 1)); 29 if(p == NULL) { 30 fprintf(stderr, "realloc error."); 31 free(s); 32 return NULL; 33 } 34 if(p != s) { 35 s = p; 36 } 37 s->cap ++; 38 } 39 s->v[++ s->i] = v; 40 return s; 41} 42 43int pop(STACK *s) { 44 if(s->i < 0) return -1; //empty 45 return s->v[s->i --]; 46} 47 48int main(void) { 49 STACK *s = create(); 50 51 //N=2 52 s = push(s, 3); 53 s = push(s, 1); 54 55 //Q=7 56 s = push(s, 4); //0 4 57 printf("%d\n", pop(s)); //1 58 printf("%d\n", pop(s)); //1 59 printf("%d\n", pop(s)); //1 60 printf("%d\n", pop(s)); //1 61 s = push(s, 2); //0 2 62 printf("%d\n", pop(s)); //1 63 64 delete(s); 65 return 0; 66}

実行結果

plain

14 21 33 4-1 52

投稿2022/06/09 17:53

編集2022/06/09 19:17
jimbe

総合スコア12646

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

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

whitehorse85921

2022/06/11 09:17

jimbe様 スマホから操作している為、コメントを押そうと思ったら間違えてベストアンサーを外すを押してしまい大変に申し訳ございません! ありがとうございます!!!
whitehorse85921

2022/06/11 09:55 編集

jimbe様 reallocの戻り値をちゃんと使ってあるコードありがとうございました!!! popする時の条件もつけて下さり感謝です!!! 自分じゃなかなか思いつかなかったので助かります!!!
jimbe

2022/06/12 16:43

create や push では malloc/realloc が NULL を返した場合を書いていますが、 main では create や push が NULL を返した場合を書いていませんので、結局中途半端で意味が無いんですけどね(><
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問