行列ファイルを読み込んで、行列積を出力するプログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
planet
記事: 9
登録日時: 2週間前

行列ファイルを読み込んで、行列積を出力するプログラムについて

#1

投稿記事 by planet » 2週間前

初めまして、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: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#2

投稿記事 by かずま » 2週間前

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');
	}
}

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#3

投稿記事 by planet » 2週間前

コメントしていただきありがとうございます。
ソースコードをこのように変更いたしました。
エラーは出なかったのですが、出力結果がいくら待っても出ませんでした。

コード:

#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: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#4

投稿記事 by かずま » 2週間前

planet さんが書きました:
2週間前
エラーは出なかったのですが、出力結果がいくら待っても出ませんでした。

コード:

    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次元配列でいいのですか?

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#5

投稿記事 by planet » 2週間前

can't open...というエラーは途中でてきました。調べたところ二回定義?していることが問題と出てきたので、最初のソースコードの宣言部分の
FILE *fp1, *fp2;を消したら、そのエラーは消えました。

プログラムの実行にはXcodeを用いているので、左上に表示されている三角ボタンを押しています。
プログラムを実行したら、通常画面下部に出力結果が出てくるのですが、その画面が出てこないといった感じです。

そして、naisekiについては特に指定がないので、自分で考えてそのように入力していました。
配列を[行][列]という風に捉えてやっていたので、二次元配列のままにしていました。


専門用語に疎く、きちんとした回答になっているか自信がありません。申し訳ございません。

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#6

投稿記事 by planet » 2週間前

追記です。
また、パス名についてですが、*の部分には自分の名前が入っているため、個人情報保護のため*にしております。

かずま

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#7

投稿記事 by かずま » 2週間前

planet さんが書きました:
2週間前
プログラムの実行には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 さんが書きました:
2週間前
また、パス名についてですが、*の部分には自分の名前が入っているため、個人情報保護のため*にしております。
そういう重要なことは質問時に絶対に省略しないでください。

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#8

投稿記事 by planet » 2週間前

もちろん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: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#9

投稿記事 by かずま » 2週間前

planet さんが書きました:
2週間前

コード:

            if (fscanf(fp1, "%lf", &gyou[i][j]) != 1) return 1;{
                puts("fscanf failed");
                return 1;
            }
こんな風に書けとは言っていません。
{ の前に return 1; を書かないで、
{ } の中の return 1; が実行されるようにしてください。

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#10

投稿記事 by planet » 2週間前

変更いたしました。
エラーが消えて出力画面も出てきましたが、
can't open mat1.txt
Program ended with exit code: 1
と出力結果が出てきます。

かずま

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#11

投稿記事 by かずま » 2週間前

planet さんが書きました:
2週間前
エラーが消えて出力画面も出てきましたが、
can't open mat1.txt
Program ended with exit code: 1
と出力結果が出てきます。
fopen が失敗していることが確定しました。
ファイル名を本当にフルパスにしていますか?
パス名に間違いはありませんか?

fclose は修正しましたか?
4行4列の結果を求めるのにソースに 5 があるのはなぜですか?
常に最新のソースを提示してください。
事情が分かったので、パス名に * を入れるのは構いません。

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#12

投稿記事 by planet » 2週間前

ファイル名、パス名には間違い無いです。きちんと確認いたしました。

ソースコードの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;
}



planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#13

投稿記事 by planet » 2週間前

出力結果も変わらず、can't open mat1.txt
Program ended with exit code: 1のままです。

かずま

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#14

投稿記事 by かずま » 2週間前

planet さんが書きました:
2週間前
出力結果も変わらず、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: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#15

投稿記事 by かずま » 2週間前

かずま さんが書きました:
2週間前

コード:

	while ((c = getchar()) != EOF)
すみません。次のように訂正します。

コード:

	while ((c = fgetc(fp)) != EOF)

planet
記事: 9
登録日時: 2週間前

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#16

投稿記事 by planet » 2週間前

かずま さん

それで確認して実行してみたところ、成功いたしました、ありがとうございました!

かずま

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#17

投稿記事 by かずま » 2週間前

planet さんが書きました:
2週間前
それで確認して実行してみたところ、成功いたしました、ありがとうございました!
fopen も行列の積の計算も全部成功したということでしょうか?
成功したというプログラムを提示してください。

かずま

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#18

投稿記事 by かずま » 2週間前

フルパスでないと fopenが成功しないのだったら
その問題も解決しないといけないでしょう。

私は Xcode のことはよくわかりませんが、
次のようなことを妄想してみました。

プロジェクトディレクトリが
"/Users/planet/Downloads/プログラミング言語/PROGEN/ で、
ソースディレクトリが
"/Users/planet/Downloads/プログラミング言語/PROGEN/PROGEN/ 。
ビルドしたあとの実行ファイルはプロジェクトディレクトリにできる。
したがって、プロジェクトディレクトリに mat1.txt などを置くと、
fopen("mat1.txt", "r") が成功するのでは?
mat1.txt の置き場所を適当に変更して試していただけませんか?

また、OS の漢字コードが Unicode で、ソースファイル中の文字コード
が Shift-JIS などと文字コードが異なると、「プログラミング言語」
という日本語のディレクトリ名が問題となる可能性も考えられます。

Math

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#19

投稿記事 by Math » 2週間前

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: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#20

投稿記事 by かずま » 2週間前

Math さんが書きました:
2週間前

コード:

    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] は範囲外です。

Math

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#21

投稿記事 by Math » 2週間前

int retu[4][3]; に直すなどして 添字にきおつけな!

行列演算は過去ログで何度も答えたから一定の書き方を覚えればいいですよ。

Math

Re: 行列ファイルを読み込んで、行列積を出力するプログラムについて

#22

投稿記事 by Math » 2週間前

int retu[4][3]; に直すなどして 添字にきおつけな!

行列演算は過去ログで何度も答えたから一定の書き方を覚えればいいですよ。

返信

“C言語何でも質問掲示板” へ戻る