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

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

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

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

ファイルI/O

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

ポインタ

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

配列

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

Q&A

解決済

4回答

3707閲覧

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

s_clalis

総合スコア17

C

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

ファイルI/O

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

ポインタ

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

配列

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

0グッド

0クリップ

投稿2018/05/30 09:13

編集2018/05/31 00:26

前提・実現したいこと

 テキストファイルから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]

該当のソースコード

C

1#include "targetver.h" 2 3#define _CRT_SECURE_NO_WARNINGS 4#define F_C 4 //file_count 5#define D_S 85 //data_size 6 7#include <math.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <tchar.h> 11 12 13double in_pro(double v1[], double v2[], int size); 14 15int main(void) 16{ 17 FILE *fp; 18 int n = 0; 19 int sum[F_C], data[F_C][D_S]; 20 char *filename[F_C] = { "rdata1.txt", "rdata2.txt", "rdata3.txt", "rdata4.txt" }; 21 char ***data_raw; 22 double u1[] = { 1, 0, 0 }; 23 double u2[] = { 0, sqrt(3) / 2, 0.5 }; 24 double u3[] = { 0, 0.5, -sqrt(3) / 2 }; 25 double xn[] = { 2, -1, 1 }; 26 double a[3]; 27 double x[6]; 28 double g[3]; 29 30 data_raw = (char ***)malloc(sizeof(char **) * F_C); 31 for (size_t i = 0; i < F_C; i++) 32 { 33 data_raw[i] = (char **)malloc(sizeof(char *) * D_S); 34 for (size_t j = 0; j < D_S; j++) 35 { 36 data_raw[i][j] = (char *)malloc(sizeof(char) * 0x10); 37 } 38 } 39 40 for (size_t i = 0; i < F_C; i++) 41 { 42 if ((fp = fopen(filename[i], "r")) == NULL) 43 { 44 fprintf(stderr, "Failed to opening %s.\n", filename[i]); 45 exit(EXIT_FAILURE); 46 } 47 48 while (fgets(data_raw[i][n], 0x10, fp) != NULL) 49 { 50 n++; 51 //puts(data_raw[i][n]); 52 } 53 n = 0; 54 } 55 56 for (size_t i = 0; i < F_C; i++) 57 { 58 for (size_t j = 0; j < D_S; j++) 59 { 60 data[i][j] = atoi(data_raw[i][j]); 61 sum[i] += data[i][j]; 62 } 63 sum[i] /= D_S; 64 printf("%d\n", sum[i]); 65 } 66 67 68 printf("***\tH30\tDSP1-3\t23\t***\n\n"); 69 70 printf("u1:[%f, %f, %f]\n", u1[0], u1[1], u1[2]); 71 printf("u2:[%f, %f, %f]\n", u2[0], u2[1], u2[2]); 72 printf("u3:[%f, %f, %f]\n \n", u3[0], u3[1], u3[2]); 73 74 x[0] = in_pro(u1, u1, 3); 75 x[1] = in_pro(u1, u2, 3); 76 x[2] = in_pro(u1, u3, 3); 77 x[3] = in_pro(u2, u2, 3); 78 x[4] = in_pro(u2, u3, 3); 79 x[5] = in_pro(u3, u3, 3); 80 81 printf("u1 * u1 : %f\n", x[0]); 82 printf("u1 * u2 : %f\n", x[1]); 83 printf("u1 * u3 : %f\n", x[2]); 84 printf("u2 * u2 : %f\n", x[3]); 85 printf("u2 * u3 : %f\n", x[4]); 86 printf("u3 * u3 : %f\n \n", x[5]); 87 88 a[0] = in_pro(xn, u1, 3); 89 a[1] = in_pro(xn, u2, 3); 90 a[2] = in_pro(xn, u3, 3); 91 92 printf("a1[%f], a2[%f], a3[%f]\n \n", a[0], a[1], a[2]); 93 94 for (size_t i = 0; i < 3; i++) g[i] = a[0] * u1[i] + a[1] * u2[i] + a[2] * u3[i]; 95 96 printf("g[%f, %f, %f]\n", g[0], g[1], g[2]); 97 98 99 fclose(fp); 100 return 0; 101} 102 103double in_pro(double v1[], double v2[], int size) 104{ 105 int i; 106 double x = 0; 107 for (i = 0; i < size; i++) x += v1[i] * v2[i]; 108 109 return x; 110}

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

VisualStudio2015
VCコンパイラ

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

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

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

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

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

ardin

2018/05/30 23:38 編集

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

2018/05/31 00:27

画像を追加しました。
a_saitoh

2018/05/31 07:32

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

2018/06/21 10:23

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

回答4

0

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

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

投稿2018/05/31 04:01

編集2018/05/31 04:04
ardin

総合スコア544

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

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

s_clalis

2018/05/31 07:19

データに対して「多い」のではなく「少ない」のではないでしょうか。定義の値を86にしたところ動きました。  `n++;`した後に読んだら確かに意味がないですね。  VCCコンパイラはVSのバージョン如何によって変わるのかわかりませんが、修正の結果2015での動作を確認しました。  ありがとうございました。
ardin

2018/05/31 07:24

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

2018/06/21 10:21

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

0

ベストアンサー

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

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

c

1 for (size_t i = 0; i < F_C; i++) 2 { 3 printf("<%d>\n", i); 4 for (size_t j = 0; j < D_S; j++) 5 { 6 printf("%s", data_raw[i][j]); 7// data[i][j] = atoi(data_raw[i][j]); 8// sum[i] += data[i][j]; 9 } 10// sum[i] /= D_S; 11// printf("%d\n", sum[i]); 12 } 13

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

c

1int sum[F_C] = {};

投稿2018/05/31 00:15

編集2018/05/31 04:40
ttyp03

総合スコア16996

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

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

s_clalis

2018/05/31 00:49

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

2018/05/31 07:11

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

0

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

C

1#define F_C 4 2#define D_S 86 3 4#include <math.h> 5#include <stdio.h> 6#include <stdlib.h> 7#include <tchar.h> 8 9 10float inner_pro(int v1[], int v2[], int size); 11 12int main(void) 13{ 14 FILE *fp; 15 int n = 0; 16 int data[F_C][D_S] = { {0} }; 17 float ave[F_C] = { 0 }, abs[F_C] = { 0 }, in_pro[3] = { 0 }; 18 char *filename[F_C] = { "rdata1.txt", "rdata2.txt", "rdata3.txt", "rdata4.txt" }; 19 char ***data_raw; //https://fa11enprince.hatenablog.com/entry/2013/09/02/010202 20 21 22 printf("***\tH30\tDSP1-3\t23\t***\n\n"); 23 24 data_raw = (char ***)malloc(sizeof(char **) * F_C); 25 for (size_t i = 0; i < F_C; i++) 26 { 27 data_raw[i] = (char **)malloc(sizeof(char *) * D_S); 28 for (size_t j = 0; j < D_S; j++) 29 { 30 data_raw[i][j] = (char *)malloc(sizeof(char) * 0x10); 31 } 32 } 33 34 for (size_t i = 0; i < F_C; i++) 35 { 36 n = 0; 37 38 if ((fp = fopen(filename[i], "r")) == NULL) 39 { 40 fprintf(stderr, "Failed to opening %s.\n", filename[i]); 41 exit(EXIT_FAILURE); 42 } 43 while (fgets(data_raw[i][n], 0x10, fp) != NULL) n++; 44 45 fclose(fp); 46 } 47 48 for (size_t i = 0; i < F_C; i++) 49 { 50 for (size_t j = 0; j < D_S; j++) 51 { 52 data[i][j] = atoi(data_raw[i][j]); 53 ave[i] += data[i][j]; 54 } 55 ave[i] /= D_S; 56 printf("ave%d : %8.3f\n", i, ave[i]); 57 } 58 59 putchar('\n'); 60 61 for (size_t i = 0; i < F_C; i++) 62 { 63 abs[i] = sqrt(inner_pro(data[i], data[i], D_S)); 64 printf("abs%d : %9.3f\n", i, abs[i]); 65 } 66 for (size_t i = 0; i < 3; i++) in_pro[i] = inner_pro(data[0], data[i + 1], D_S); 67 68 printf("rel to H16_female\t: %.3f\n", in_pro[0] / (abs[0] * abs[1])); 69 printf("rel to H16_all-jap\t: %.3f\n", in_pro[1] / (abs[0] * abs[2])); 70 printf("rel to S24_all-jap\t: %.3f\n", in_pro[2] / (abs[0] * abs[3])); 71 72 putchar('\n'); 73 74 for (size_t i = 0; i < F_C; i++) for (size_t j = 0; j < D_S; j++) data[i][j] -= ave[i]; 75 76 for (size_t i = 0; i < F_C; i++) 77 { 78 abs[i] = sqrt(inner_pro(data[i], data[i], D_S)); 79 printf("abs%d : %9.3f\n", i, abs[i]); 80 } 81 for (size_t i = 0; i < 3; i++) in_pro[i] = inner_pro(data[0], data[i + 1], D_S); 82 83 printf("rel to H16_female\t: %.3f\n", in_pro[0] / (abs[0] * abs[1])); 84 printf("rel to H16_all-jap\t: %.3f\n", in_pro[1] / (abs[0] * abs[2])); 85 printf("rel to S24_all-jap\t: %.3f\n", in_pro[2] / (abs[0] * abs[3])); 86 87 return 0; 88} 89 90float inner_pro(int v1[], int v2[], int size) 91{ 92 int i; 93 float x = 0; 94 95 for (i = 0; i < size; i++) x += v1[i] * v2[i]; 96 97 return x; 98}

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

投稿2018/05/31 07:14

s_clalis

総合スコア17

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

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

0

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

{ n++;

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

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

投稿2018/05/30 12:27

pepperleaf

総合スコア6383

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

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

s_clalis

2018/05/31 00:40

回答ありがとうございます。  プログラムを変更して実行してみたところ、先頭データの"573"がすべてのdata_raw[0]に入ってしまいます。nの値が増加していることも確認しました。  fgets()の仕様はファイルストリームから、一行分改行文字までを読み取って配列もしくはポインタに投げる関数と思っています。  同様の質問に関しては、ポインタを使うことが不適切だと指摘されたため、質問の趣旨を変更して再掲させていただきました。初めて質問投稿サイトを使うので、勝手がよくわかっていません。不愉快な思いをさせてしまったようでしたらお詫び申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問