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

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

ただいまの
回答率

89.07%

char型の配列を文字コード変換し、int型の配列にしたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 299

moorumoru

score 10

前提・実現したいこと

コンソールから数字を読み込み、ソートするプログラムを作っています。
数字以外の文字列が入力された際にエラーを返すために、
getcharでcharとして受け取り、空白を区切りとして文字列から-'0'をして数字か判定しました。

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

①char型からint型への配列の変換
②作成したソート関数は数値に対するものなので、char型で渡すと結果がおかしくなりました。
③メモリアクセス違反が発生しています。

ハンドルされない例外が 0x7A9CC920 (ucrtbased.dll) で発生しました(sort.exe 内): 0xC0000005: 場所 0x00000001 の読み取り中にアクセス違反が発生しました。
ハンドルされない例外が 0x7A9CC920 (ucrtbased.dll) で発生しました(sort.exe 内): 0xC0000005: 場所 0x00000001 の読み取り中にアクセス違反が発生しました。

該当のソースコード

//コンソールから数値の入力を一行で受けて、小さい順にソートして返すプログラム
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <ctype.h>


int getnum(char, int);
int input_num(char, int, long);
void swap(int* x, int* y);
/* ソート関数の宣言
今はchar型になっていますが、これはテストのためです */
char bubble(char*, int);
char quick(char*, int, int);
char choice(char*, int);
char insertion(char*, int);
char kiguu(char*, int);
//もとはこのようでした
//long* kiguu(long*, int);



int main(void) {

        int sorts, keep[4], i = 0, yoso, input=0, count;
        double start, end, time;
        char* base, * endptr;

        //入力の受付
        printf("いくつの数字をソートしますか?1000以下で指定してください。\n");
        char str[1000], buf[5000];
        long *longnum;
        int keta, num = 0;

        /*
        2~1000の間になるまで入力させる
        */
        count = num;
        printf("num(桁数指定): %d\n", num);


        longnum = (long*)malloc(sizeof(long) * count + 1);


        num = 0;
        printf("\n並び変えたい整数を入力してください。\n");
        while (input != count) {

                input = input_num(buf, count*8, longnum); //この部分でエラーになります
                for(i = 0; buf[i] != '\0';i++){
                        printf("buf[%d]: %d\ninput: %d\n", i, buf[i], input);
                }

        }

        printf("\nソートの方法を番号で指定してください。\n1.バブルソート 2.クイックソート 3.選択ソート 4.挿入ソート 5.奇偶転置ソート \n");

       /*
       ここからソートの関数に入れますが、こちらはscanfで読み込ませて処理を確認しています。
       */

        //結果の表示
        printf("ソート結果:");
        for (int i = 0; i < count; i++) {
                printf(" %d", buf[i]);
        }
        printf("\n");

        end = clock();
        time = end - start;
        printf("処理時間: %f ms\n", time);

        free(longnum);
        return 0;

}

//入力された要素を空白ごとに要素として区切り、int型数字にする
int input_num(char s[], int lim, long longs[]){ 

        int c, i, count, keep[1000] = {0}, j = 0, p = 0, yoso_num = 0;

        for (i = 0; i < lim - 1 && (c = getchar()) != '\n'; i++) {
                s[i] = c;


        }
        count = i;
        for (i = 0; i < count; i++) {
                s[i] = s[i] - '0';

        }

        s[i] = EOF;
/*下のfor文で条件をs[i]!='\0'にしていましたが、入力から0を受け取った時に処理が終了してしまうので、
EOFを終了点としました。*/
        s[i + 1] = '\0';
        count = i;
        i = 0;
        keep[p] = s[i];

        for (i = 1; i < count && s[i] != EOF; i++) {

                if (s[i] == -16) {
                        p++;
                        yoso_num++;
                        i++;
                        keep[p] = s[i];

                }else{

                        keep[p] = keep[p] * 10 + s[i];

                }

        }
        yoso_num++;

        keep[p + 1] = '\0';
        for(j = 0; j < p + 2; j++) {
                longs[j] = atol(keep[j]);  //ここでエラーが発生します。
        }



        return yoso_num;
}


ソースコードが長くなってしまうので、他の関数は表示していませんが、コメントくだされば適宜追加します。

試したこと

・メモリアクセス違反は宣言外のメモリにアクセスしてしまうこと、と分かったのですが、
宣言し、mallocで確保しているlongnum[](longs[j])の0番目でなぜエラーが起こるのかわかりません。

・int型に変換するためには配列内の要素を1つずつatoiで変換しようと思ったのですがこれはいかがでしょうか?

ツールのバージョンなど

Windows10 64bitでVisual Studio2017を使用しています。

補足情報

文字列配列の扱いで、こちら(知恵袋)も参考にしました。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

文字コード変換とか難しいこと考えなくても、そのまま代入すればいいだけです。
char型というのは文字型ではありません
1バイト幅の整数型です


                longs[j] = atol(keep[j]);  //ここでエラーが発生します。

atolという関数は文字列のアドレスを引数に取り、数値変換した結果を返す関数です。
エラーが出るのはアドレスではなく数値データを引数に与えているせいです

#質問の意図に合うように追記

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/19 09:21

    atoiは、数字以外の文字が入ってるとエラーになります
    EOFが入ってると当然エラーですわな

    #って質問の論点はこっちだった

    キャンセル

  • 2020/05/19 09:33

    ああ、ちゃうやんw
    atolの引数は文字列のアドレスですよ

    キャンセル

  • 2020/05/19 10:50

    引数に&をつけることで解決できました!ありがとうございます!!

    キャンセル

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

  • ただいまの回答率 89.07%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る