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

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

ただいまの
回答率

90.62%

  • C

    3573questions

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

  • 配列

    511questions

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

  • ポインタ

    102questions

    ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

  • ファイルI/O

    38questions

    ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

C言語の3次元配列(文字列)の動的確保並びにfgetsによる読み込み

解決済

回答 4

投稿 編集

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

s_clalis

score 0

 前提・実現したいこと

テキストファイルから1行ずつデータをchar型配列に読み込み、int型に変換してから配列の平均を除去・正規化し内積を計算して相関係数を算出するプログラムを作る。
勉強のためにポインタと動的確保を使ってみることとする。

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

4つのファイル別のデータを各配列に入れて利用したいのですが、想定したとおりに構造ができず困っています。(data_raw[]に各4ファイルの階層がありその中のdata_raw[][]に数値が一行づつ入っている構造)
今のところファイルの先頭の行が全てのdata_raw[]に入ってしまいます。これをdata_raw[][]に入れたいです。

whileに入ったの1回目の変数の状況

他の方法を選ぶべきでしたらご教授いただけると幸いです。

 該当のテキストファイル

rdata1.txt

573
577
595
600
598
598
612
608
607
616
618
610
621
620
635
648
675
693
710
740
772
781
781
790
831
843
866
878
918
956
1005
1020
1004
977
954
933
914
915
711
886
829
810
784
773
780
795
773
754
793
821
820
871
918
975
1049
1147
1139
1083
675
718
872
846
869
841
765
664
704
723
716
677
632
623
599
568
530
499
469
436
406
358
300
249
215
187
179
132
[EOF]

 該当のソースコード

#include "targetver.h"

#define _CRT_SECURE_NO_WARNINGS
#define F_C 4 //file_count
#define D_S 85 //data_size

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>


double in_pro(double v1[], double v2[], int size);

int main(void)
{
    FILE *fp;
    int n = 0;
    int sum[F_C], data[F_C][D_S];
    char *filename[F_C] = { "rdata1.txt", "rdata2.txt", "rdata3.txt", "rdata4.txt" };
    char ***data_raw;
    double u1[] = { 1, 0, 0 };
    double u2[] = { 0, sqrt(3) / 2, 0.5 };
    double u3[] = { 0, 0.5, -sqrt(3) / 2 };
    double xn[] = { 2, -1, 1 };
    double a[3];
    double x[6];
    double g[3];

    data_raw = (char ***)malloc(sizeof(char **) * F_C);
    for (size_t i = 0; i < F_C; i++)
    {
        data_raw[i] = (char **)malloc(sizeof(char *) * D_S);
        for (size_t j = 0; j < D_S; j++)
        {
            data_raw[i][j] = (char *)malloc(sizeof(char) * 0x10);
        }
    }

    for (size_t i = 0; i < F_C; i++)
    {
        if ((fp = fopen(filename[i], "r")) == NULL)
        {
            fprintf(stderr, "Failed to opening %s.\n", filename[i]);
            exit(EXIT_FAILURE);
        }

        while (fgets(data_raw[i][n], 0x10, fp) != NULL)
        {
            n++;
            //puts(data_raw[i][n]);
        }
        n = 0;
    }

    for (size_t i = 0; i < F_C; i++)
    {
        for (size_t j = 0; j < D_S; j++)
        {
            data[i][j] = atoi(data_raw[i][j]);
            sum[i] += data[i][j];
        }
        sum[i] /= D_S;
        printf("%d\n", sum[i]);
    }


    printf("***\tH30\tDSP1-3\t23\t***\n\n");

    printf("u1:[%f, %f, %f]\n", u1[0], u1[1], u1[2]);
    printf("u2:[%f, %f, %f]\n", u2[0], u2[1], u2[2]);
    printf("u3:[%f, %f, %f]\n \n", u3[0], u3[1], u3[2]);

    x[0] = in_pro(u1, u1, 3);
    x[1] = in_pro(u1, u2, 3);
    x[2] = in_pro(u1, u3, 3);
    x[3] = in_pro(u2, u2, 3);
    x[4] = in_pro(u2, u3, 3);
    x[5] = in_pro(u3, u3, 3);

    printf("u1 * u1 : %f\n", x[0]);
    printf("u1 * u2 : %f\n", x[1]);
    printf("u1 * u3 : %f\n", x[2]);
    printf("u2 * u2 : %f\n", x[3]);
    printf("u2 * u3 : %f\n", x[4]);
    printf("u3 * u3 : %f\n \n", x[5]);

    a[0] = in_pro(xn, u1, 3);
    a[1] = in_pro(xn, u2, 3);
    a[2] = in_pro(xn, u3, 3);

    printf("a1[%f], a2[%f], a3[%f]\n \n", a[0], a[1], a[2]);

    for (size_t i = 0; i < 3; i++)    g[i] = a[0] * u1[i] + a[1] * u2[i] + a[2] * u3[i];

    printf("g[%f, %f, %f]\n", g[0], g[1], g[2]);


    fclose(fp);
    return 0;
}

double in_pro(double v1[], double v2[], int size)
{
    int i;
    double x = 0;
    for (i = 0; i < size; i++)    x += v1[i] * v2[i];

    return x;
}

 補足情報(FW/ツールのバージョンなど)

VisualStudio2015
VCコンパイラ

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • ardin

    2018/05/31 08:38 編集

    一応、読み込みたいファイル内容を見せてください。1つだけで構いません

    キャンセル

  • s_clalis

    2018/05/31 09:27

    画像を追加しました。

    キャンセル

  • a_saitoh

    2018/05/31 16:32

    あとで入力したデータは別の用途で使うのですか?文字列での入力データは配列に保管せずに、整数に変換した結果だけを配列に入れるのでも処理はできるのでは?

    キャンセル

  • s_clalis

    2018/06/21 19:23

    ほかの用途で使う予定です。このプログラムだけにおいては整数に変換したものを渡すだけです。fgets()だとフォーマット指定子が使えませんので...

    キャンセル

回答 4

checkベストアンサー

+1

ファイルからの読み込みは問題なくできているようですが。
何をもってしてできていないという判断をしているのでしょうか。

dataに移し変えるところで、data_rawの中身を表示して確認してみました。

    for (size_t i = 0; i < F_C; i++)
    {
        printf("<%d>\n", i);
        for (size_t j = 0; j < D_S; j++)
        {
            printf("%s", data_raw[i][j]);
//            data[i][j] = atoi(data_raw[i][j]);
//            sum[i] += data[i][j];
        }
//        sum[i] /= D_S;
//        printf("%d\n", sum[i]);
    }

オーバーフローについては、sumを初期化していないからかもしれません。
配列の初期値は不定値なので、明示的に初期化してあげましょう。
0で初期化するのであれば、次のような記述が楽です。

int sum[F_C] = {};

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/31 09:49

    回答ありがとうございます。
     ファイルの読み込みができていないと思い込んでいたのはputs()関数にアドレスをchar型として表示させていたからでした。計算結果がオーバーフローするのは式の問題だと思われるので、修正してみます。
     丁寧に確認のソースを掲載していただきありがとうございます。

    キャンセル

  • 2018/05/31 16:11

    ANSI周りをちらちらとみてきた結果、回答の通りになりました。結果、解決したため、もっとも参考になったttyp03氏をベストアンサーに選ばせていただきます。ありがとうございました。

    キャンセル

+1

ソース画像を見ました。
そしてデータを見ました。データは86個あるので1個多いです。
n++の後にputs(data_raw[i][n]);をしたらダメです。
その前に判定した意味がありません。

一応正しく書き直してVS2017でビルド実行してみましたが、
結果まで懸賞はしていませんが、無事実行されました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/31 16:19

    データに対して「多い」のではなく「少ない」のではないでしょうか。定義の値を86にしたところ動きました。
     `n++;`した後に読んだら確かに意味がないですね。

     VCCコンパイラはVSのバージョン如何によって変わるのかわかりませんが、修正の結果2015での動作を確認しました。
     ありがとうございました。

    キャンセル

  • 2018/05/31 16:24

    プログラム内想定データ数が85個に対して、ファイル内には86個のデータがあったので多いとしました。
    (プログラムの方を優先しました)
    実際には多くても少なくてもいいようにプログラムを組むのが良いので次回からは気にかけてみてください。

    キャンセル

  • 2018/06/21 19:21

    そうしてみます。
    ありがとうございました。

    キャンセル

0

   while (fgets(data_raw[i][n], 0x10, fp) != NULL)
{
n++;

これで、すべての行が、 data_raw[0] に入りませんか?
fgets() の仕様を確認しましたか?

それと、同様の質問はしていませんか?
そちらはどうなったでしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/31 09:40

    回答ありがとうございます。
     プログラムを変更して実行してみたところ、先頭データの"573"がすべてのdata_raw[0]に入ってしまいます。nの値が増加していることも確認しました。
     fgets()の仕様はファイルストリームから、一行分改行文字までを読み取って配列もしくはポインタに投げる関数と思っています。

     同様の質問に関しては、ポインタを使うことが不適切だと指摘されたため、質問の趣旨を変更して再掲させていただきました。初めて質問投稿サイトを使うので、勝手がよくわかっていません。不愉快な思いをさせてしまったようでしたらお詫び申し上げます。

    キャンセル

0

*** 最終的に実装したコード

#define F_C 4
#define D_S 86

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>


float inner_pro(int v1[], int v2[], int size);

int main(void)
{
    FILE *fp;
    int n = 0;
    int data[F_C][D_S] = { {0} };
    float ave[F_C] = { 0 }, abs[F_C] = { 0 }, in_pro[3] = { 0 };
    char *filename[F_C] = { "rdata1.txt", "rdata2.txt", "rdata3.txt", "rdata4.txt" };
    char ***data_raw;    //https://fa11enprince.hatenablog.com/entry/2013/09/02/010202


    printf("***\tH30\tDSP1-3\t23\t***\n\n");

    data_raw = (char ***)malloc(sizeof(char **) * F_C);
    for (size_t i = 0; i < F_C; i++)
    {
        data_raw[i] = (char **)malloc(sizeof(char *) * D_S);
        for (size_t j = 0; j < D_S; j++)
        {
            data_raw[i][j] = (char *)malloc(sizeof(char) * 0x10);
        }
    }

    for (size_t i = 0; i < F_C; i++)
    {
        n = 0;

        if ((fp = fopen(filename[i], "r")) == NULL)
        {
            fprintf(stderr, "Failed to opening %s.\n", filename[i]);
            exit(EXIT_FAILURE);
        }
        while (fgets(data_raw[i][n], 0x10, fp) != NULL)    n++;

        fclose(fp);
    }

    for (size_t i = 0; i < F_C; i++)
    {
        for (size_t j = 0; j < D_S; j++)
        {
            data[i][j] = atoi(data_raw[i][j]);
            ave[i] += data[i][j];
        }
        ave[i] /= D_S;
        printf("ave%d : %8.3f\n", i, ave[i]);
    }

    putchar('\n');

    for (size_t i = 0; i < F_C; i++)
    {
        abs[i] = sqrt(inner_pro(data[i], data[i], D_S));
        printf("abs%d : %9.3f\n", i, abs[i]);
    }
    for (size_t i = 0; i < 3; i++)    in_pro[i] = inner_pro(data[0], data[i + 1], D_S);

    printf("rel to H16_female\t: %.3f\n", in_pro[0] / (abs[0] * abs[1]));
    printf("rel to H16_all-jap\t: %.3f\n", in_pro[1] / (abs[0] * abs[2]));
    printf("rel to S24_all-jap\t: %.3f\n", in_pro[2] / (abs[0] * abs[3]));

    putchar('\n');

    for (size_t i = 0; i < F_C; i++)    for (size_t j = 0; j < D_S; j++)    data[i][j] -= ave[i];

    for (size_t i = 0; i < F_C; i++)
    {
        abs[i] = sqrt(inner_pro(data[i], data[i], D_S));
        printf("abs%d : %9.3f\n", i, abs[i]);
    }
    for (size_t i = 0; i < 3; i++)    in_pro[i] = inner_pro(data[0], data[i + 1], D_S);

    printf("rel to H16_female\t: %.3f\n", in_pro[0] / (abs[0] * abs[1]));
    printf("rel to H16_all-jap\t: %.3f\n", in_pro[1] / (abs[0] * abs[2]));
    printf("rel to S24_all-jap\t: %.3f\n", in_pro[2] / (abs[0] * abs[3]));

    return 0;
}

float inner_pro(int v1[], int v2[], int size)
{
    int i;
    float x = 0;

    for (i = 0; i < size; i++)    x += v1[i] * v2[i];

    return x;
}

皆様ありがとうございました。ご指摘などございましたら、追記の程宜しくお願い申し上げます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • C

    3573questions

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

  • 配列

    511questions

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

  • ポインタ

    102questions

    ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

  • ファイルI/O

    38questions

    ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。