目的:
- ポインター、構造体、ファイルの組み合わせ使用をマスターします。マスターフォーム参加引数
- まず、C言語のテキストファイルの基本的な概念と基本的な操作を読んで習得します。テキストファイルの読み取りと書き込み、fopen / fclose、fscanf / fprintfおよびその他の機能に精通している。
- 実践演習1:いくつかの数字と文字列をファイルに書き込みます。読み上げて表示します。
- 読むことを通して、構造の基本的な概念を習得します;構造配列、構造ポインタの概念を学び、実践します。
- 実践演習2:マトリックスを構造体として表現します。メンバーには、マトリックスの行と列の数、およびマトリックスの特定の要素へのポインターが含まれます。次に、最初の演習をやり直します。
操作:
読み取りファイルと書き込みファイルを使用した行列の乗算
請求:
指定されたテキストファイルの各行列を読み取り、複数行列の乗算の結果を計算して、その結果を別のテキストファイルに書き込みます。
ファイル名は任意です。たとえば、入力ファイル:input.txt、出力ファイルout.txtなどです。
入力ファイル形式:ファイルに複数の行列を記録し、複数の行列を空白行で区切ります。同様:
1 3 2
2 5 4
3
8
12
(上記のファイルには、それぞれ2 * 3と3 * 1の2つの行列が含まれています)(ヒント:複数の行列の場合、構造体配列/構造体ポインターを使用できます)
#include
#include
#include
using namespace std;
struct mat /*结构体,包含每个矩阵自身的信息,以及下一个矩阵的存储位置*/
{
int rows = 0;
int columns = 0;
int **a = NULL;
struct mat *next = NULL;
}result;
void input() /*向矩阵中输入数据*/
{
int i, j, num = 0, flag = 0;
char ch;
struct mat *p=NULL;
FILE *fp;
/*打开文件*/
if ((fp = fopen("input.txt", "r")) == NULL){
cout << "Error.";
exit(1);
}
p = result.next;
while (p != NULL){
/*开括矩阵空间*/
if ((p->a = (int **)malloc(p->rows*sizeof(int *))) == NULL){
cout << "ERROR!";
exit(1);
}
for (i = 0; i < p->rows; i++)
if ((p->a[i] = (int *)malloc(p->columns*sizeof(int))) == NULL){
cout << "ERROR!";
exit(1);
}
for (i = 0; i < p->rows; i++)
for (j = 0; j < p->columns; j++){
while (1){
ch = fgetc(fp);
/*将数值记录下来*/
if (ch >= '0' && ch <= '9'){
num = num * 10 + (int)(ch - '0');
flag = 0;
}
else{
if (ch == 10)
flag++;
if (flag == 2){
flag = 0;
continue;
}
p->a[i][j] = num;
num = 0;
break;
}
}
}
p = p->next;
}
fclose(fp);
/*创建存结果的矩阵*/
if ((result.a = (int **)malloc(result.rows*sizeof(int *))) == NULL){
cout << "ERROR!";
exit(1);
}
for (i = 0; i < result.rows; i++)
if ((result.a[i] = (int *)malloc(result.columns*sizeof(int))) == NULL){
cout << "ERROR!";
exit(1);
}
}
/*释放空间*/
void freespace()
{
struct mat *p1 = NULL, *p2 = NULL;
int i;
p1 = result.next;
while (p1!=NULL){
p2 = p1;
p1 = p1->next;
for (i = 0; i < p2->rows; i++)
free(p2->a[i]);
free(p2->a);
free(p2);
}
}
void calculate() /*计算矩阵乘法*/
{
struct mat *p = NULL, temp;
int i, j, k;
p = result.next;
for (i = 0; i < p->rows; i++) /*第一个矩阵可以直接把数据给result矩阵*/
for (j = 0; j < p->columns; j++)
result.a[i][j] = p->a[i][j];
result.rows = p->rows; /*记录现在的矩阵的行列数*/
result.columns = p->columns;
p=p->next;
/*创建一个临时矩阵,用于计算*/
if ((temp.a = (int **)malloc(result.rows*sizeof(int *))) == NULL){
cout << "ERROR!";
exit(1);
}
for (i = 0; i < result.rows; i++)
if ((temp.a[i] = (int *)malloc(result.columns*sizeof(int))) == NULL){
cout << "ERROR!";
exit(1);
}
while (p != NULL){
for (i = 0; i < result.rows; i++) /*把result矩阵里的数给临时矩阵,并将result矩阵清零*/
for (j = 0; j < result.columns; j++){
temp.a[i][j] = result.a[i][j];
result.a[i][j] = 0;
}
temp.rows = result.rows;
temp.columns = result.columns;
for (i = 0; i < temp.rows; i++) /*进行临时矩阵和当前矩阵的乘法运算,将结果保存在result矩阵*/
for (j = 0; j < p->columns; j++){
for (k = 0; k < temp.columns; k++)
result.a[i][j] += temp.a[i][k] * p->a[k][j];
}
result.columns = p->columns; /*记录当前的矩阵列数,行数则不变*/
p = p->next;
}
}
int main(void)
{
FILE *fp;
char ch;
int flag = 0, r = 0, c = 0;
struct mat *p = NULL, *temp = NULL;
p = &result;
/*打开文件*/
if ((fp = fopen("input.txt", "r")) == NULL){
cout << "Error.";
exit(1);
}
do /*一直读到文件结束为止*/
{
ch = fgetc(fp);
if (ch >= '0' && ch <= '9') /*记录有多少个元素*/{
flag = 0;
continue;
}
r++;
/*记录连续的换行符的个数,若有连续两个换行符,说明下面是一个新的矩阵*/
if (ch == 10){
flag++;
c++;
}
/*将每个矩阵的行列数记录下来*/
if (flag == 2 || ch == EOF){
temp = (struct mat*)malloc(sizeof(struct mat));
temp->rows = c + 1 - flag;
temp->columns = (r - 1) / temp->rows;
temp->next = NULL;
if (temp->rows > result.rows)
result.rows = temp->rows;
if (temp->columns > result.columns)
result.columns = temp->columns;
p->next = temp;
p = p->next;
flag = 0;
c = 0;
r = 0;
}
} while (ch != EOF);
fclose(fp);
input();
calculate();
/*打开文件*/
if ((fp = fopen("out.txt", "w")) == NULL){
cout << "Error.";
exit(1);
}
/*输出运算结果*/
for (int i = 0; i < result.rows; i++){
for (int j = 0; j < result.columns; j++)
fprintf(fp,"%d\t",result.a[i][j]);
fprintf(fp,"\n");
}
fclose(fp);
freespace();
return 0;
}
/*
本程序要求input.txt具有如下格式:
1 3 2(每行最后一个数后面的字符为换行符)
2 5 4
(矩阵之间空一行,且这一行只有一个换行符)
3
8
12
(文件结束标志“EOF”必须在最后一个数的下一行,且这一行只有这一个字符)
*/