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

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

新規登録して質問してみよう
ただいま回答率
85.35%
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

5030閲覧

エラーはないのに途中で実行が終わってしまうプログラムの修正

MIKE1216

総合スコア1

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/07/04 15:16

前提・実現したいこと

最近隣法を用いた、巡回セールスマン問題のプログラムを書いたのですが、実行結果が、for (k = 2; k <= N; k++)のfor文の手前まで実行されて、それ以降の処理がなされずに終了してしまいます。何回も見直しをしたのですが、エラーもないため、どこが良くないのか分からず手詰まりの状況です。このプログラムがきちんと実行するように修正したいです。

発生している問題・エラーメッセージ

エラーはありません。

該当のソースコード

C++

1ソースコード 2```#include<stdio.h> 3#include<stdlib.h> 4#define _USE_MATH_DEFINES 5#include<math.h> 6#include<time.h> 7 8#define distance(xi,xj,yi,yj) (sqrt(pow((xi)-(xj), 2.0) + pow((yi)-(yj), 2.0))); 9 10FILE* fp1; 11FILE* fp2; 12FILE* fp3; 13 14struct CityInfo 15{ 16 int citynumber; 17 double x; 18 double y; 19}; 20 21int main(void) { 22 int N, n, city_number; 23 double x_point, y_point, a, b, ux, uy; 24 25 printf("訪問都市の位置情報x座標とy座標の範囲(下限a,上限b)の設定について\n"); 26 printf("範囲の下限aを実数値で指定してください。...>"); 27 scanf_s("%lf",&a); 28 printf("範囲の上限bを実数値で指定してください。...>"); 29 scanf_s("%lf",&b); 30 printf("訪問都市数Nを指定してください。...>"); 31 scanf_s("%d",&N); 32 33 fopen_s(&fp1, "citydata_info.csv", "w"); 34 35 srand((unsigned int)time(NULL)); 36 37 for (n = 1; n <= N; n++) { 38 city_number = n; 39 ux = (double)rand() / (double)RAND_MAX; 40 x_point = a + (b - a) * ux; 41 uy = (double)rand() / (double)RAND_MAX; 42 y_point = a + (b - a) * uy; 43 fprintf(fp1, "%d,%lf,%lf\n", n, x_point, y_point); 44 } 45 46 fclose(fp1); 47 48 49 struct CityInfo* cityinfodata; 50 51 cityinfodata = (struct CityInfo*)malloc((N + 1) * sizeof(struct CityInfo)); 52 53 if (cityinfodata == NULL) { 54 printf("メモリが確保できません。\n"); exit(1); 55 } 56 57 for (n = 0; n <= N; n++) { 58 cityinfodata[n].citynumber = 0; 59 cityinfodata[n].x = 0.0; 60 cityinfodata[n].y = 0.0; 61 } 62 63 fopen_s(&fp2, "citydata_info.csv", "r"); 64 65 n = 1; 66 67 while (fscanf_s(fp2, "%d,%lf,%lf",&cityinfodata[n].citynumber, &cityinfodata[n].x, &cityinfodata[n].y) != EOF) { 68 n++; 69 } 70 71 fclose(fp2); 72 73 fopen_s(&fp3, "task.csv", "w"); 74 75 printf("都市番号 x座標 y座標\n"); 76 fprintf(fp3, "都市番号,x座標,y座標\n"); 77 78 for (n = 1; n <= N; n++) { 79 printf("%d %lf %lf\n", cityinfodata[n].citynumber, cityinfodata[n].x, cityinfodata[n].y); 80 fprintf(fp3, "%d,%lf,%lf\n", cityinfodata[n].citynumber, cityinfodata[n].x, cityinfodata[n].y); 81 } 82 83 int* z; 84 z = (int*)malloc((N + 1) * sizeof(int)); 85 if (z == NULL) { 86 printf("一次元配列zのメモリを確保できません。\n"); exit(1); 87 } 88 for (n = 0; n <= N; n++) { 89 z[n] = 0; 90 } 91 92 int* zz; 93 zz = (int*)malloc((N + 1) * sizeof(int)); 94 if (zz == NULL) { 95 printf("一次元配列zzのメモリを確保できません。\n"); exit(1); 96 } 97 for (n = 0; n <= N; n++) { 98 zz[n] = 0; 99 } 100 101 int start,next,i,k,j; 102 printf("\n最初の出発都市startを都市番号1~%dより指定してください。...>",N); 103 scanf_s("%d", &start); 104 105 clock_t start_time, end_time; 106 start_time=clock(); 107 108 i = start; 109 110 double tdis, min, dij; 111 tdis = 0.0; 112 113 114 k = 1; 115 116 z[i] = k; 117 zz[k] = i; 118 119 printf("\nk i next min tdis\n"); 120 fprintf(fp3, "\nk,i,next,min,tdis\n"); 121 122 for (k = 2; k <= N; k++) { 123 min = 20000; 124 for (j = 1; j <= N; i++) { 125 if (z[j] == 0) { 126 dij = distance(cityinfodata[i].x, cityinfodata[j].x, cityinfodata[i].y, cityinfodata[j].y); 127 if (dij < min){ 128 next = j; 129 min = dij; 130 } 131 } 132 } 133 z[next] = k; 134 zz[k] = next; 135 tdis = tdis + dij; 136 printf("%d %d %d %lf %lf\n", k, i, next, min, tdis); 137 fprintf(fp3,"%d,%d,%d,%lf,%lf\n", k, i, next, min, tdis); 138 i = j; 139 } 140 141 dij= distance(cityinfodata[i].x, cityinfodata[start].x, cityinfodata[i].y, cityinfodata[start].y); 142 tdis = tdis + dij; 143 144 printf(" %d %d %lf %lf\n",i,start,dij,tdis); 145 fprintf(fp3, ",%d,%d,%lf,%lf\n",i,start,dij,tdis); 146 147 end_time = clock(); 148 149 double searching_time; 150 searching_time = (double)(end_time - start_time) / (double)CLOCKS_PER_SEC; 151 152 printf("都市番号 訪問順序"); 153 fprintf(fp3,"都市番号,訪問順序"); 154 155 for (n = 1; n <= N; n++) { 156 printf("%d,%d", n, z[n]); 157 } 158 159 printf("訪問順序 都市番号"); 160 fprintf(fp3, "訪問順序,都市番号"); 161 162 for (n = 1; n <= N; n++) { 163 printf("%d,%d", n, zz[n]); 164 } 165 166 printf("総移動距離 %lf", tdis); 167 fprintf(fp3,"総移動距離,%lf", tdis); 168 169 printf("探求処理時間 %lf秒", searching_time); 170 fprintf(fp3,"探求処理時間,%lf秒",searching_time); 171 172 fclose(fp3); 173 174 free(cityinfodata); 175 free(z); 176 free(zz); 177 178 return 0; 179} 180 181### 試してみたこと 182zを定義する手前までのプログラムはちゃんと動きました。 183 184### 備考

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

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

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

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

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

y_waiwai

2021/07/04 22:20

このままではコードが見づらいので、質門を編集し、<code>ボタンで、出てくる’’’の枠の中にコードを貼り付けてください
guest

回答1

0

ベストアンサー

「エラー」という言葉は多分に多義的です。とにかくも期待する結果が出ていないのだから、明らかに「エラー」はあるのです。

もし、コンパイルを通ったことを「エラーがない」と言いたいならそれは「文法エラーがなかった」というだけであって、そもそも文法エラーがあるということはC言語としての要件を満たしていないプログラム未満の何かでしかないということで、文法エラーがないのは「当然」です。もし文法エラーがなければ当然期待した動作をするのならint main(void){return 0;}が「最強のプログラム」でなければいけませんが、もちろんそんなことはありません。

とにかく、「エラー」はあるのですから、「エラーはありません」というのもおかしな話。ここは「エラーメッセージ等は出ていません」というのが正確なところでしょう。それくらい察しろ、ということなかれ。間違い/エラーにたどり着くには「事実」を検証するのが有力な手段ですから、そのためには過ぎるくらいに厳密がちょうどいい。

何回も見直しをした

ここはちょっと精神論にもなってしまいますが、「合っているはず」と思ってみると間違いを見逃します。間違っているはず、その間違いを探す、という気持ちで探してください。

で。メッセージもなく途中でプログラムが動作を停止する時、それはしばしばポインタの計算を間違っているか、配列の添字計算を間違っているかであることが多いです。アクセス違反で検出されれば運が良かったというくらいで、スタックを破壊してプログラムの実行が不可能になってただ停止してしまったり。今回はまさにそういう症状なので、ポインタ/配列の添字には特に注意してください。

その目で見ていくと、
z[next] = k;
なんてのはとても気になるところです。

また、「間違っているはず」と考えていれば、いかにも間違いそうでやっぱり間違えている
for (j = 1; j <= N; i++) {
も見えてくるかも知れません。

なお、コンパイラで警告を目一杯出すオプション(Microsoft Cでは/Wall)を入れておくと、

test.c(138) : warning C4701: 初期化されていない可能性のあるローカル変数 'dij' が使用されます test.c(136) : warning C4701: 初期化されていない可能性のあるローカル変数 'next' が使用されます

というのもレポートされます。警告メッセージは有効に活用してください。

余談。
間違いではないですがなんでわざわざcityinfodataを作るのにファイルに書き出したそのファイルをもう一度読み直しているんだろう? というのは疑問に感じるところです。

投稿2021/07/04 23:11

編集2021/07/04 23:13
thkana

総合スコア7703

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

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

MIKE1216

2021/07/05 02:23

ご指摘の通り、質問の不備が多々あるなか、このように丁寧に回答いただきありがとうございました。おっしゃる通り、合っているはずという目で確認を行っていた節が確かにありました。落ち着いて、改めて確認すると、いくつかの間違いを発見することが出来、無事プログラムを完成させることが出来ました。改めて、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問