ページ 1 / 1
行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 15:41
by planet
初めまして、planetです。
学校の宿題で、4行3列の行列ファイルmat1.txt と、3行4列の行列ファイルmat2.txtを読み込み、
行列積を求める課題がでました。
以下のソースコードでビルドしてみると、エラーは出ませんでした。
しかし出力すると、ファイルをオープンできません。が冒頭2行に出てきます。
なので2つのファイルが開けていないことなのかと認識しています。
その下に数が出力されますが、0が多すぎて正直テキストファイルを開けていないことが問題なのか、ソースコードが問題なのか、どこが問題なのかわかりません。
また、テキストファイルはソースコード.cと同じファイルに入れております。
もしもわかる方がいましたら教えてください。
よろしくお願いします。
-------------ソースコード-------------
コード:
#include <stdio.h>
int main(void){
FILE *fp1,*fp2;
int i = 0, n;
char gyou[4][3];
char retu[3][4];
char naiseki[4][4];
int x,y;
fp1 = fopen("mat1.txt", "r");
if(fp1 == NULL){
printf("ファイルをオープンできません。\n");
}
else {
while(fscanf(fp1, "%s %s %s ", &gyou[i][0], &gyou[i][1], &gyou[i][2]) == 3)
{
for (i = 0; i < 4; i++) {
fscanf(fp1, "%s %s %s ", &gyou[i][0], &gyou[i][1], &gyou[i][2]);
}
}
}
fp2 = fopen("mat2.txt", "r");
if(fp2 == NULL){
printf("ファイルをオープンできません。\n");
}
else {
while (fscanf(fp2, "%s %s %s %s\n", &retu[0][i], &retu[1][i], &retu[2][i], &retu[3][i]) == 4) {
for (i = 0; i < 3; i++) {
fscanf(fp2, "%s %s %s %s\n", &retu[0][i], &retu[1][i], &retu[2][i], &retu[3][i]);
}
}
}
for(y = 0;y < 5;y++){
puts("\n");
for(x = 0;x < 5;x++){
for(n = 0; n < 4;n++){
naiseki[y][x] += gyou[y][n]*retu[n][x];
printf("%3d", naiseki[y][x]);
}
}
fclose(fp1);
fclose(fp2);
}
return 0;
}
------------出力結果------------
ファイルをオープンできません。
ファイルをオープンできません。
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 88
88 88 88 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 88
88 88 88 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
-96-96-96-96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96Program ended with exit code: 0
------------テキストファイルmat1.txt------------
1 2 3
1 2 3
4 5 6
4 5 6
------------テキストファイルmat2.txt------------
1 2 3 4
1 2 3 4
4 5 6 7
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 16:57
by かずま
fopen("/usr/tmp/mat.1.txt", "r") などのように
ファイル名をフルパスにしてみてください。
どうなりますか?
ファイルの読み込みは次のコードを参考にしてください。
コード:
#include <stdio.h>
int main(void)
{
double gyou[4][3];
FILE *fp1 = fopen("mat1.txt", "r");
if (fp1 == NULL) { puts("can't open mat1.txt"); return 1; }
for (int i = 0; i < 4; i++)
for (int j = 0; j < 3; j++)
if (fscanf(fp1, "%lf", &gyou[i][j]) != 1) return 1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
printf("%10g", gyou[i][j]);
putchar('\n');
}
}
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 18:43
by planet
コメントしていただきありがとうございます。
ソースコードをこのように変更いたしました。
エラーは出なかったのですが、出力結果がいくら待っても出ませんでした。
コード:
#include <stdio.h>
int main(void){
int n;
double gyou[4][3];
double retu[3][4];
char naiseki[4][4];
int x,y;
FILE *fp1 = fopen("/Users/*/Downloads/プログラミング言語/PROGEN/PROGEN/mat1.txt", "r");
if(fp1 == NULL) { puts("can't open mat1.txt"); return 1; }
for (int i = 0; i < 4; i++)
for (int j = 0; j < 3; j++)
if (fscanf(fp1, "%lf", &gyou[i][j]) != 1) return 1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
printf("%10g", gyou[i][j]);
putchar('\n');
}
FILE *fp2 = fopen("/Users/*/Downloads/プログラミング言語/PROGEN/PROGEN/mat2.txt", "r");
if(fp2 == NULL){ puts("can't open mat2.txt"); return 1; }
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
if (fscanf(fp2, "%lf", &retu[i][j]) != 1) return 1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
printf("%10g", retu[i][j]);
putchar('\n');
}
for(y = 0;y < 5;y++){
puts("\n");
for(x = 0;x < 5;x++){
for(n = 0; n < 4;n++){
naiseki[y][x] += gyou[y][n]*retu[n][x];
printf("%3d", naiseki[y][x]);
}
}
fclose(fp1);
fclose(fp2);
}
return 0;
}
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 19:07
by かずま
planet さんが書きました: ↑6年前
エラーは出なかったのですが、出力結果がいくら待っても出ませんでした。
コード:
FILE *fp1 = fopen("/Users/*/Downloads/プログラミング言語/PROGEN/PROGEN/mat1.txt", "r");
if(fp1 == NULL) { puts("can't open mat1.txt"); return 1; }
パス名に * が入ることは通常ないので、fopen がエラーになり、
can't open mat1.txt と表示されると思うのですが、
それも表示されないのですか?
プログラムが終了せずに、何か入力待ちにでもなっているのですか?
プログラムの実行はどのように行っていますか?
naiseki は char の 2次元配列でいいのですか?
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 19:17
by planet
can't open...というエラーは途中でてきました。調べたところ二回定義?していることが問題と出てきたので、最初のソースコードの宣言部分の
FILE *fp1, *fp2;を消したら、そのエラーは消えました。
プログラムの実行にはXcodeを用いているので、左上に表示されている三角ボタンを押しています。
プログラムを実行したら、通常画面下部に出力結果が出てくるのですが、その画面が出てこないといった感じです。
そして、naisekiについては特に指定がないので、自分で考えてそのように入力していました。
配列を[行][列]という風に捉えてやっていたので、二次元配列のままにしていました。
専門用語に疎く、きちんとした回答になっているか自信がありません。申し訳ございません。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 19:18
by planet
追記です。
また、パス名についてですが、*の部分には自分の名前が入っているため、個人情報保護のため*にしております。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 19:42
by かずま
planet さんが書きました: ↑6年前
プログラムの実行にはXcodeを用いているので、左上に表示されている三角ボタンを押しています。
プログラムを実行したら、通常画面下部に出力結果が出てくるのですが、その画面が出てこないといった感じです。
最初から現象をそのように具体的に報告してください。
次のプログラムを実行すると、hello, world. という出力結果の画面が出ますか?
コード:
#include <stdio.h>
int main(void)
{
puts("hello, world.");
}
それが表示されるのであって、元のプログラムで can't open mat1.txt
が表示されないのであれば、fopen は成功しています。
読み込んだ gyou の値が表示されないのなら、
fscanf が失敗していると考えられます。
if (fscanf(fp, "%lf", gyou[ i][j]) != 1) return 1; を
次のように変更したらどうなりますか?
コード:
if (fscanf(fp, "%lf", gyou[i][j]) != 1) {
puts("fscanf failed");
return 1;
}
mat1.txt の中には本当に 12個の数字が入っていますか?
fopen は 1回ずつ実行しているのに、fclose を for文の中で
5回ずつ実行するのはおかしいと思いませんか?
planet さんが書きました: ↑6年前
また、パス名についてですが、*の部分には自分の名前が入っているため、個人情報保護のため*にしております。
そういう重要なことは質問時に絶対に省略しないでください。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 19:54
by planet
もちろんhelloworldのように、出力はできます。今回のみなぜか出てきません。
if (fscanf(fp, "%lf", gyou[ i][j]) != 1) return 1; を変更しても特に変わりませんでした。
黄色いエラーが出てきました。
Code will never be executed
そして、
FILE *fp1 = fopen("mat1.txt", "r");
パス名を元のように消したところ、出力画面は出てきました。
しかし、can't open mat1.txtと表示されます。
mat1.txtとmat2.txtについては質問投稿の通りに数字が入っております。
省略についてですが、気をつけます。。。
ソースコードです。
コード:
#include <stdio.h>
int main(void){
int n;
double gyou[4][3];
double retu[3][4];
char naiseki[4][4];
int x,y;
FILE *fp1 = fopen("mat1.txt", "r");
if(fp1 == NULL) { puts("can't open mat1.txt"); return 1; }
for (int i = 0; i < 4; i++)
for (int j = 0; j < 3; j++)
if (fscanf(fp1, "%lf", &gyou[i][j]) != 1) return 1;{
puts("fscanf failed");
return 1;
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
printf("%10g", gyou[i][j]);
putchar('\n');
}
FILE *fp2 = fopen("mat2.txt", "r");
if(fp2 == NULL){ puts("can't open mat2.txt"); return 1; }
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
if (fscanf(fp2, "%lf", &retu[i][j]) != 1) return 1;{
puts("fscanf failed");
return 1;
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
printf("%10g", retu[i][j]);
putchar('\n');
}
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 20:03
by かずま
planet さんが書きました: ↑6年前
コード:
if (fscanf(fp1, "%lf", &gyou[i][j]) != 1) return 1;{
puts("fscanf failed");
return 1;
}
こんな風に書けとは言っていません。
{ の前に return 1; を書かないで、
{ } の中の return 1; が実行されるようにしてください。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 20:11
by planet
変更いたしました。
エラーが消えて出力画面も出てきましたが、
can't open mat1.txt
Program ended with exit code: 1
と出力結果が出てきます。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 20:26
by かずま
planet さんが書きました: ↑6年前
エラーが消えて出力画面も出てきましたが、
can't open mat1.txt
Program ended with exit code: 1
と出力結果が出てきます。
fopen が失敗していることが確定しました。
ファイル名を本当にフルパスにしていますか?
パス名に間違いはありませんか?
fclose は修正しましたか?
4行4列の結果を求めるのにソースに 5 があるのはなぜですか?
常に最新のソースを提示してください。
事情が分かったので、パス名に * を入れるのは構いません。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 20:37
by planet
ファイル名、パス名には間違い無いです。きちんと確認いたしました。
ソースコードの5の部分は誤りでした、4に変更いたしました。
そして、fcloseもfor分の中に入っていたので変更しました。
ありがとうございます。
コード:
#include <stdio.h>
int main(void){
int n;
double gyou[4][3];
double retu[3][4];
char naiseki[4][4];
int x,y;
FILE *fp1 = fopen("mat1.txt", "r");
if(fp1 == NULL) { puts("can't open mat1.txt"); return 1; }
for (int i = 0; i < 4; i++)
for (int j = 0; j < 3; j++)
if (fscanf(fp1, "%lf", &gyou[i][j]) != 1) {
puts("fscanf failed");
return 1;
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
printf("%10g", gyou[i][j]);
putchar('\n');
}
FILE *fp2 = fopen("mat2.txt", "r");
if(fp2 == NULL){ puts("can't open mat2.txt"); return 1; }
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
if (fscanf(fp2, "%lf", &retu[i][j]) != 1) {
puts("fscanf failed");
return 1;
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
printf("%10g", retu[i][j]);
putchar('\n');
}
for(y = 0;y < 4;y++){
puts("\n");
for(x = 0;x < 4;x++){
for(n = 0; n < 4;n++){
naiseki[y][x] += gyou[y][n]*retu[n][x];
printf("%3d", naiseki[y][x]);
}
}
}
fclose(fp1);
fclose(fp2);
return 0;
}
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 20:38
by planet
出力結果も変わらず、can't open mat1.txt
Program ended with exit code: 1のままです。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 21:14
by かずま
planet さんが書きました: ↑6年前
出力結果も変わらず、can't open mat1.txt
Program ended with exit code: 1のままです。
念のため次のコードを確認してみてください。
... は適当なものにしてください。
コード:
#include <stdio.h>
int main(void)
{
FIEL *fp = fopen("/.../.../.../mat1.txt", "r");
if (fp == NULL) { puts("fopen failed"); return 1; }
int c;
while ((c = getchar()) != EOF)
putchar(c);
fclose(fp);
return 0;
}
fopen 失敗問題が解決しないので、
それは後回しにして、行列の積の計算を見てみましょう。
コード:
#include <stdio.h>
int main(void)
{
int n;
double gyou[4][3] = {
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 4, 5, 6 },
};
double retu[3][4] = {
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 4, 5, 6, 7 },
};
char naiseki[4][4];
int x,y;
for(y = 0;y < 4;y++){
puts("\n");
for(x = 0;x < 4;x++){
for(n = 0; n < 4;n++){
naiseki[y][x] += gyou[y][n]*retu[n][x];
printf("%3d", naiseki[y][x]);
}
}
}
return 0;
}
どこが間違っているかわかりますか?
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 21:18
by かずま
かずま さんが書きました: ↑6年前
コード:
while ((c = getchar()) != EOF)
すみません。次のように訂正します。
コード:
while ((c = fgetc(fp)) != EOF)
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 22:56
by planet
かずま さん
それで確認して実行してみたところ、成功いたしました、ありがとうございました!
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月26日(日) 23:10
by かずま
planet さんが書きました: ↑6年前
それで確認して実行してみたところ、成功いたしました、ありがとうございました!
fopen も行列の積の計算も全部成功したということでしょうか?
成功したというプログラムを提示してください。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月27日(月) 09:11
by かずま
フルパスでないと fopenが成功しないのだったら
その問題も解決しないといけないでしょう。
私は Xcode のことはよくわかりませんが、
次のようなことを妄想してみました。
プロジェクトディレクトリが
"/Users/planet/Downloads/プログラミング言語/PROGEN/ で、
ソースディレクトリが
"/Users/planet/Downloads/プログラミング言語/PROGEN/PROGEN/ 。
ビルドしたあとの実行ファイルはプロジェクトディレクトリにできる。
したがって、プロジェクトディレクトリに mat1.txt などを置くと、
fopen("mat1.txt", "r") が成功するのでは?
mat1.txt の置き場所を適当に変更して試していただけませんか?
また、OS の漢字コードが Unicode で、ソースファイル中の文字コード
が Shift-JIS などと文字コードが異なると、「プログラミング言語」
という日本語のディレクトリ名が問題となる可能性も考えられます。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月28日(火) 21:25
by Math
gcc 8.2.0 だと
コード:
#include <stdio.h>
int main(void){
FILE *fp1,*fp2;
int i = 0, n;
int gyou[4][3];
int retu[3][4];
int naiseki[4][4]={ };
int x,y;
fp1 = fopen("mat1.txt", "r");
if(fp1 == NULL){
printf("ファイルをオープンできません。\n");
}
for (i = 0; i < 4; i++) {
fscanf(fp1, "%d %d %d", &gyou[i][0], &gyou[i][1], &gyou[i][2]);
printf("%d %d %d\n", gyou[i][0], gyou[i][1], gyou[i][2]);
}
printf("\n-----------------\n\n");
fp2 = fopen("mat2.txt", "r");
if(fp2 == NULL){
printf("ファイルをオープンできません。\n");
}
for (i = 0; i < 3; i++) {
fscanf(fp2, "%d %d %d %d", &retu[0][i], &retu[1][i], &retu[2][i], &retu[3][i]);
printf("%d %d %d %d\n", retu[0][i], retu[1][i], retu[2][i], retu[3][i]);
}
/*
for(y = 0;y < 5;y++){
puts("\n");
for(x = 0;x < 5;x++){
for(n = 0; n < 4;n++){
naiseki[y][x] += gyou[y][n]*retu[n][x];
}
printf("%3d", naiseki[y][x]);
}
}
*/
fclose(fp1);
fclose(fp2);
return 0;
}
実行
http://www2.koyoen.birdview.co.jp/~abcx ... 8-zzz-.PNG
行列の積は 行ベクトルx列ベクトル だからね。添字を間違えずよく考えろ!
エクセルで検算すると
http://www2.koyoen.birdview.co.jp/~abcx ... -28-z-.PNG
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月28日(火) 23:17
by かずま
Math さんが書きました: ↑6年前
コード:
int retu[3][4];
fscanf(fp2, "%d %d %d %d", &retu[0][i], &retu[1][i], &retu[2][i], &retu[3][i]);
printf("%d %d %d %d\n", retu[0][i], retu[1][i], retu[2][i], retu[3][i]);
int retu[3][4]; と宣言されたら、
retu[j][ i] の j は 0, 1, 2 のいずれかでなければなりません。
retu[3][ i] は範囲外です。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月29日(水) 07:54
by Math
int retu[4][3]; に直すなどして 添字にきおつけな!
行列演算は過去ログで何度も答えたから一定の書き方を覚えればいいですよ。
Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて
Posted: 2019年5月29日(水) 07:54
by Math
int retu[4][3]; に直すなどして 添字にきおつけな!
行列演算は過去ログで何度も答えたから一定の書き方を覚えればいいですよ。