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

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

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

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

Q&A

解決済

3回答

934閲覧

コードが実行できない件

hyo_uken

総合スコア1

C

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

0グッド

0クリップ

投稿2021/11/20 22:37

編集2021/11/21 08:59

C

1#include <stdio.h> 2 3int main(void) 4{ 5 int n, x, cnt; 6 int a[n], b[n]; 7 scanf("%d %d", &n, &x); 8 9 for(int i=1;i<=n;i++){ 10 scanf("%d", a[i]); 11 b[i] = 0; 12 } 13 cnt = 0; 14 while(b[x] == 0){ 15 b[x] = 1; 16 cnt++; 17 x = a[x]; 18 } 19 printf("%d\n", cnt); 20 return 0; 21}

上記のコードなのですが、Visual Studio Code上で実行すると、エラーは出ないのですが、入力もできずに終わってしまいます。どなたか教えて頂けないでしょうか?

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

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

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

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

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

BeatStar

2021/11/20 22:53

一つ目。コードは"<code>"または"<コード>"のボタンを押して出てくるやつの中に書きましょう。 今のままだと読みづらいです。 質問は編集できるので編集しましょう。 二つ目。デバッグしましょう。 プログラミングは『書いて終わり』ではありません。gdbなり、VSCodeのやつのデバッガなりで潜ってみましょう。
dodox86

2021/11/21 00:56

一応確認ですが、コンパイルだけして実行していないとか。(たまにそういう質問を見かけます)
hyo_uken

2021/11/21 09:00

返事が遅くなってしまい申し訳ありませんでした。ご指摘の通り、変更しましたのでよろしくお願いします。
BeatStar

2021/11/21 09:03

えーっと、私も回答していますが、それ、読みましたか? それでもわからないなら、「どのあたりが理解できないのか」とかを書いてください。
hyo_uken

2021/11/21 09:06

今、読んでいる最中です。もう少し待っていただけるとありがたいです。初学者なので、理解に時間がかかってしまいすいません。
guest

回答3

0

C言語の原則。プログラムは上から順に実行される。プログラムの流れを制御するループや分岐、ジャンプなどの構文で明示的に制御されない限り、後から実行された命令によって以前の結果が影響を受けるようなことはない。

C言語の規則。staticでない(つまりautoの)ローカル変数の初期値は不定。特定の値を期待できない。

ライブラリ関数の規則。scanfの第2引数以降はポインタ型を与える

気をつけたほうがいいこと。配列の宣言時要素数に変数を使えないコンパイラが存在する。(「可変長配列」はCのオプション規格)

C

1int main(void) 2{ 3 int n, x, cnt; //各値は不定。nも不定。実行してみるまでいくつになるかわからない。0かも、-100かも、20億かもしれない 4 int a[n], b[n];//そのnを使うココロは? この記述がエラーになるコンパイラがあることは気にしない? 5 scanf("%d %d", &n, &x);//ここでnを決めても前には波及しない 6 7 for(int i=1;i<=n;i++){ 8 scanf("%d", a[i]);//a[i]はポインタ型ではない。a[n]は配列の範囲外 9 b[i] = 0; 10 }

もう一つ追加。
Cでは要素数Nの配列のインデックス(添字)は0,1,...N-1のN個、ね。配列の範囲外アクセスは「未定義動作」。何が起こっても文句は言えない。

投稿2021/11/21 00:09

編集2021/11/21 00:20
thkana

総合スコア7703

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

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

hyo_uken

2021/11/21 09:13

回答していただきありがとうございました。おかげで理解することができました。
guest

0

ベストアンサー

まず、デバッグぐらいはしましょう
プログラミングは『書いて終わり』…ではありません

『DIYをやってみたい』とか『俺はDIYが趣味だ』と言う人が「椅子を作りたいけど誰か設計図を書いて、それをもとに作ってくれ」とか「椅子を作ったけど高さが合わないから誰か修繕してくれ」と言いますか?

プログラミングも「自分で設計し、自分でコーディングし、自分でデバッグまでする」のが当たり前です。
それすらしないのならいっそやめた方がいいです。だってそれは「他人任せで自分は努力せず、責任転嫁する人」ですから。

なのでデバッグぐらいはしましょう。

出来ればデバッガ(GDB等)を使ってデバッグした方がいいですが、常にそれができるとは限りません。(手元にデバッガが無いとか、使い方が分からないとか……)

その場合はいわゆるprintfデバッグをしましょう。

たとえば、

#include<stdio.h> int main( void ){ int n; int nums[n]; printf( "%d\n", n ); scanf( "%d", &n ); printf( "%d", sizeof(nums) ); return 0; }

というようなコードをprintfデバッグをするなら、それぞれの行の間に printfで数字等を出力する。

// 例 #include<stdio.h> int main( void ){ printf( "ID = %d\n", 1 ); int n; printf( "ID = %d\n", 2 ); int nums[n]; printf( "ID = %d\n", 3 ); printf( "%d\n", n ); printf( "ID = %d\n", 4 ); scanf( "%d", &n ); printf( "ID = %d\n", 5 ); printf( "%d", sizeof(nums) ); printf( "ID = %d\n", 6 ); return 0; }

うまくいけば、

ID = 1
ID = 2
ID = 3
...
ID = 6

のようになるはずです。("ID = <数字>"でなくともいいが、今回のサンプルコードではサイズを表示したりとかの数字が出力される処理があるので)

でもVSCode + MinGW でやると、ID = 1 と ID = 2 までは出力されるが ID = 3 以降が出力されない。

ということは

printf( "ID = %d\n", 1 ); int n; printf( "ID = %d\n", 2 );

の部分は普通に通る。でも次の int nums[n]; 辺りでなんか悪さをしていそうですね。
で、その行は 単純に配列を宣言しているだけです。なにも問題がなさそうですね。一見。

でも、よく考えてみてください。そもそも nとはなんですか? そう、int nとして宣言されたものですね。
ただ、この変数 n は初期化、していませんよね? C言語では初期化していないと不定値が入ります。
環境とかによっては 初期化せずとも 0 になっていることもありますが、私の手元の環境では 4218896のようなでたらめな値になっています。

こういう変数や配列はスタック領域にセットされます。C言語でいうmalloc/freeでやるやつはヒープ領域にセットされます。
スタック領域はサイズが決まっていて、デカい要素数で確保する事はできません。

今回の場合、nを初期化していないので n = 4218896のような状態になっているはです。(数字は違うとは思うが。不定値なので)

そうすると、int nums[4218896]; という状態になります。
でもスタック領域にはそんなサイズは取れないので、エラー的なものに。
(確か、Segmentation Faultだったはず…)

よって、それ以降の処理がされずにクラッシュするのです。

GDBのようなデバッガを使う場合も発想自体は同じです。

単にprintf関数を使って「ここまで通った」とか「現在のnの値は○○」とかみたいにやるのか、next,step等を使うのか、ボタンを使って動かすのかとかが違うだけです。

今回の質問にあるコードだと、

C

1int n, x, cnt; 2int a[n], b[n]; 3scanf("%d %d", &n, &x);

となっています。int a[n], b[n];の時点では、n, x, cmt は初期化されていません。
となると、n = 4218896, x = 4218896, cnt = 4218896 のような状態のはずです。(数字はともかく)

この状態で a[n] を置き換えてみると a[4218896], b[4218896] となります。
でもスタック領域にはそんなに取れません。
よってクラッシュ。

そのため、それ以降の scanf関数だのなんだのの処理がされないのです。

まずはデバッグ方法を覚えましょう。

投稿2021/11/21 07:41

編集2021/11/21 09:03
BeatStar

総合スコア4962

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

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

hyo_uken

2021/11/21 09:12

丁寧に回答していただき、ありがとうございました。おかげで理解することができました。
guest

0

Visual Studio Codeの設定上の問題であればわかりません。

C言語の範囲としては、
int n, x, cnt;
int a[n], b[n];
scanf("%d %d", &n, &x);

だと、配列のサイズが何になっているかわからないので、

int n, x, cnt;
scanf("%d %d", &n, &x);
int a[n], b[n];

の順番にすればいいのでは?

投稿2021/11/20 23:57

PingHermit

総合スコア478

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

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

hyo_uken

2021/11/21 09:13

ありがとうございます。理解することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問