前提・実現したいこと
コンソールから数字を読み込み、ソートするプログラムを作っています。
数字以外の文字列が入力された際にエラーを返すために、
getcharでcharとして受け取り、空白を区切りとして文字列から-'0'をして数字か判定しました。
発生している問題・エラーメッセージ
①char型からint型への配列の変換
②作成したソート関数は数値に対するものなので、char型で渡すと結果がおかしくなりました。
③メモリアクセス違反が発生しています。
ハンドルされない例外が 0x7A9CC920 (ucrtbased.dll) で発生しました(sort.exe 内): 0xC0000005: 場所 0x00000001 の読み取り中にアクセス違反が発生しました。 ハンドルされない例外が 0x7A9CC920 (ucrtbased.dll) で発生しました(sort.exe 内): 0xC0000005: 場所 0x00000001 の読み取り中にアクセス違反が発生しました。
該当のソースコード
C
1//コンソールから数値の入力を一行で受けて、小さい順にソートして返すプログラム 2#include <stdio.h> 3#include <time.h> 4#include <stdlib.h> 5#include <math.h> 6#include <limits.h> 7#include <ctype.h> 8 9 10int getnum(char, int); 11int input_num(char, int, long); 12void swap(int* x, int* y); 13/* ソート関数の宣言 14今はchar型になっていますが、これはテストのためです */ 15char bubble(char*, int); 16char quick(char*, int, int); 17char choice(char*, int); 18char insertion(char*, int); 19char kiguu(char*, int); 20//もとはこのようでした 21//long* kiguu(long*, int); 22 23 24 25int main(void) { 26 27 int sorts, keep[4], i = 0, yoso, input=0, count; 28 double start, end, time; 29 char* base, * endptr; 30 31 //入力の受付 32 printf("いくつの数字をソートしますか?1000以下で指定してください。\n"); 33 char str[1000], buf[5000]; 34 long *longnum; 35 int keta, num = 0; 36 37 /* 38 2~1000の間になるまで入力させる 39 */ 40 count = num; 41 printf("num(桁数指定): %d\n", num); 42 43 44 longnum = (long*)malloc(sizeof(long) * count + 1); 45 46 47 num = 0; 48 printf("\n並び変えたい整数を入力してください。\n"); 49 while (input != count) { 50 51 input = input_num(buf, count*8, longnum); //この部分でエラーになります 52 for(i = 0; buf[i] != '\0';i++){ 53 printf("buf[%d]: %d\ninput: %d\n", i, buf[i], input); 54 } 55 56 } 57 58 printf("\nソートの方法を番号で指定してください。\n1.バブルソート 2.クイックソート 3.選択ソート 4.挿入ソート 5.奇偶転置ソート \n"); 59 60 /* 61 ここからソートの関数に入れますが、こちらはscanfで読み込ませて処理を確認しています。 62 */ 63 64 //結果の表示 65 printf("ソート結果:"); 66 for (int i = 0; i < count; i++) { 67 printf(" %d", buf[i]); 68 } 69 printf("\n"); 70 71 end = clock(); 72 time = end - start; 73 printf("処理時間: %f ms\n", time); 74 75 free(longnum); 76 return 0; 77 78} 79 80//入力された要素を空白ごとに要素として区切り、int型数字にする 81int input_num(char s[], int lim, long longs[]){ 82 83 int c, i, count, keep[1000] = {0}, j = 0, p = 0, yoso_num = 0; 84 85 for (i = 0; i < lim - 1 && (c = getchar()) != '\n'; i++) { 86 s[i] = c; 87 88 89 } 90 count = i; 91 for (i = 0; i < count; i++) { 92 s[i] = s[i] - '0'; 93 94 } 95 96 s[i] = EOF; 97/*下のfor文で条件をs[i]!='\0'にしていましたが、入力から0を受け取った時に処理が終了してしまうので、 98EOFを終了点としました。*/ 99 s[i + 1] = '\0'; 100 count = i; 101 i = 0; 102 keep[p] = s[i]; 103 104 for (i = 1; i < count && s[i] != EOF; i++) { 105 106 if (s[i] == -16) { 107 p++; 108 yoso_num++; 109 i++; 110 keep[p] = s[i]; 111 112 }else{ 113 114 keep[p] = keep[p] * 10 + s[i]; 115 116 } 117 118 } 119 yoso_num++; 120 121 keep[p + 1] = '\0'; 122 for(j = 0; j < p + 2; j++) { 123 longs[j] = atol(keep[j]); //ここでエラーが発生します。 124 } 125 126 127 128 return yoso_num; 129} 130
ソースコードが長くなってしまうので、他の関数は表示していませんが、コメントくだされば適宜追加します。
試したこと
・メモリアクセス違反は宣言外のメモリにアクセスしてしまうこと、と分かったのですが、
宣言し、mallocで確保しているlongnumの0番目でなぜエラーが起こるのかわかりません。
・int型に変換するためには配列内の要素を1つずつatoiで変換しようと思ったのですがこれはいかがでしょうか?
ツールのバージョンなど
Windows10 64bitでVisual Studio2017を使用しています。
###補足情報
文字列配列の扱いで、こちら(知恵袋)も参考にしました。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/19 00:09
2020/05/19 00:12
退会済みユーザー
2020/05/19 00:15
2020/05/19 00:16
2020/05/19 00:21
2020/05/19 00:33
退会済みユーザー
2020/05/19 01:50