C++预学习

学习任务:
掌握指针和结构、文件的结合使用。掌握形参与实参
首先通过读书,掌握c语言文本文件的基本概念和基本操作。熟悉文本文件的读写及fopen/fclose,fscanf/fprintf等函数。
作业:使用读写文件的矩阵乘法
要求:读出指定文本文件中各矩阵,计算多矩阵相乘后结果,并将结果写入另一文本文件中。
文件名任意;如输入文件:input.txt; 输出文件out.txt
输入文件格式:将多个矩阵记录在文件中,多个矩阵以空行分隔。类似:
1 3 2
2 5 4

3
8
12

(上述文件包括2个矩阵,分别为2*3和3*1的)
(提示:对于多矩阵,可使用结构数组/结构指针)

头文件 matrix.h

/********************************************************************
头文件中应该包含的内容:
*函数原型
*使用#define或const定义的符号常量
*结构声明
*类声明
*模板声明
*内联函数            P262
*********************************************************************/
#ifndef MATRIX_H_
#define MATRIX_H_

#include<stdio.h>

struct mat                                                        //矩阵结构体
{
    int row;                                                      //矩阵行数
    int column;                                                   //矩阵列数
    int** pointer;                                                //矩阵的头指针
}; 
const char sou_pos[] = "matrix.txt";                              //输入文件位置
const char dst_pos[] = "output.txt";                              //输出文件名(默认在当前目录下)

void   task( );                                                   //任务函数
int    count_mat ( FILE* file );                                  //读取指定文件中矩阵个数
void   eye_create( int N , mat* d_mat );                          //创造一个N*N的单位阵
void   copy_mat  ( mat* s_mat , mat* d_mat );                     //深拷贝一个矩阵到另一个位置 
void   release   ( mat* d_mat );                                  //释放指定位置的row*column内存
void   mat_create( mat* d_mat );                                  //创造一个row*column的矩阵
void   mat_mulp  ( mat* s_mat1 , mat* s_mat2 , mat* d_mat );      //计算两个矩阵的乘积
void   mat_output( FILE* file , mat* d_mat );                     //将矩阵写入到指定文件
void   getfeature( FILE* file , mat* s_mat );                     //得到文件下一个矩阵的行数和列数
void   input_mat ( FILE* file , mat* s_mat );                     //从文本文件中读取一个矩阵的信息到一个mat中



#endif

函数文件 task2_fun.cpp

#include<stdio.h>               //定义输入输出函数
#include<stdlib.h>              //定义杂项函数及内存分配函数
#include<string.h>              //字符串处理
#include"matrix.h"              //自定义函数


/*******************************************************
函数名称:task
函数参数:无
返回参数:无
函数功能:执行整个任务
调用函数:
********************************************************/
void  task( )
{
    FILE* file;                                 //文件指针
    int count = 0;                              //记录矩阵个数
    mat* mat1 , *mat2 , *d_mat;                 //源结构体及结果结构体
    mat1  = ( mat* ) malloc( sizeof( mat ) );
    mat2  = ( mat* ) malloc( sizeof( mat ) );
    d_mat = ( mat* ) malloc( sizeof( mat ) );

    if( fopen_s( &file , sou_pos , "r" ) )       //返回值为1,说明打开文件失败
    {
        printf( "Can't open file!" );
        exit( 0 );
    }
    else
    {
        count = count_mat( file );
        rewind( file );                         //记得一定要重定向,上一次已经改变了file指针的位置!!!!!!!
        getfeature( file , mat2 );              //得到第一个矩阵的信息,getfeature不改变file位置
        eye_create( mat2->row ,mat1);           //mat1先存一个单位阵
        for( int i = 0; i < count;i++ )
        {
            if( i != 0 )
            {
                getfeature( file , mat2 );      //将下一个矩阵的行列信息存入mat2,
            }       
            input_mat ( file , mat2 );          //文件中读取的矩阵存入mat2中
            mat_mulp( mat1 , mat2 , d_mat );    //d_mat = mat1 * mat2
            release ( mat1 );                   //释放mat1的空间
            copy_mat( d_mat , mat1 );           //mat1 = d_mat
            release ( d_mat );                  //释放d_mat的空间
        }
        fclose( file );
    }
    if( fopen_s( &file , dst_pos , "w" ) )      //返回值为1,说明打开文件失败
    {
        printf( "Can't open file!" );
        exit( 0 );
    }
    else
    {
        mat_output( file , mat1 );              //最终的结果在mat1中
    }
    return;
}
/****************************************************************
函数名称:getfeature
函数参数:文件指针位置
返回参数:文件中矩阵的个数
函数功能:读取指定文件中下一个矩阵的行数和列数
调用函数:无
注意:此函数并没有改变file指针的位置!!!
*****************************************************************/
void getfeature( FILE* file , mat* s_mat )
{
    FILE* sub_file = file;
    char buf[1024];
    long offset;

    offset = ftell( file );
    s_mat->row = 0;
    s_mat->column = 0;
    while( fgets( buf , 1024 ,file ) != NULL ) 
    {
        if( buf[0] == '\n' )                   //读到某个矩阵的末尾
        {
            break;
        }
        else
        {
            s_mat->row++;
            if( s_mat->column != 0 )
            {
                continue;                       //列数已读取完毕
            }
            int len = strlen( buf );
            for( int i = 0; i < len; i++ )
            {
                if( buf[i] == ' ' )
                {
                    s_mat->column++;
                }
            }
            s_mat->column++;
        }
    }
    fseek( file , offset , SEEK_SET );   //指针重定向!!!!!!!重点一定要放在这里,不要放在break前面,要不然对最后一个矩阵有问题
    printf( "矩阵为%d X %d" , s_mat->row , s_mat->column );
}

/**********************************************************
函数名称:count_mat
函数参数:读取文件的指针
返回参数:文件中矩阵的个数
函数功能:读取指定文件中矩阵的个数
调用函数:无
***********************************************************/
int count_mat( FILE* file )
{
    int count = 0;
    char buf[1024];

    while( fgets( buf , 1024 , file ) != NULL )
    {
        if( buf[0] == '\n' )
        {
            count++;
            continue;
        }
    }
    count++;
    printf( "%d个矩阵" , count );
    return count;
}

/*******************************************************************
函数名称:eye_create
函数参数:欲创建的单位阵的行数,创建的矩阵的地址
返回参数:无
函数功能:创建一个N*N的矩阵
调用函数:mat_create(mat* d_mat)
*******************************************************************/
void eye_create( int N , mat* d_mat )
{
    d_mat->row = N;
    d_mat->column = N;
    mat_create( d_mat );
    for( int i = 0; i < N; i++ )
    {
        for( int j = 0; j < N; j++ )
        {
            if( i == j )
            {
                d_mat->pointer[i][j] = 1;
            }
            else
            {
                d_mat->pointer[i][j] = 0;
            }
        }
    }
    return;
}

/*******************************************************************
函数名称:mat_output
函数参数:欲写入的文件指针,欲记录的mat结构体指针
返回参数:无
函数功能:创建一个指定名称的txt文件并将最后计算的矩阵相乘结果记录其中
调用函数:release( mat* d_mat )
*******************************************************************/
void  mat_output( FILE* file , mat* d_mat )
{
    int row = d_mat->row;
    int column = d_mat->column;

    for( int i = 0; i < row; i++ )
    {
        for( int j = 0; j < column; j++ )
        {
            fprintf( file , "%5d" , d_mat->pointer[i][j] );
        }
        fprintf( file , "\n" );
    }
    release( d_mat );
    return;
}
/*******************************************************************
函数名称:release
函数参数:指向欲释放内存的mat结构体指针
返回参数:无
函数功能:释放指定mat结构体中pointer的内存
调用函数:无
*******************************************************************/
void  release( mat* d_mat )
{
    for( int i = 0; i < d_mat->row; i++ )
    {
        if( d_mat->pointer[i] != NULL )
        {
            free( d_mat->pointer[i] );

        }
    }
    if( d_mat->pointer != NULL )
    {
        free( d_mat->pointer );

    }
    d_mat->pointer = NULL;
    d_mat->row = 0;
    d_mat->column = 0;
    return;
}

/*******************************************************************
函数名称:copy_mat
函数参数:源mat结构体指针,目的mat结构体指针
返回参数:无
函数功能:将d_mat结构体初始化并将s_mat完全复制到d_mat中
调用函数:mat_create( mat* )
*******************************************************************/
void  copy_mat( mat* s_mat , mat* d_mat )
{
    d_mat->row = s_mat->row;
    d_mat->column = s_mat->column;
    mat_create( d_mat );
    for( int i = 0; i < d_mat->row; i++ )
    {
        for( int j = 0; j < d_mat->column; j++ )
        {
            d_mat->pointer[i][j] = s_mat->pointer[i][j];
        }
    }
    return;
}

/*******************************************************************
函数名称:mat_create
函数参数:目的mat结构体指针
返回参数:无
函数功能:申请d_mat结构体的二级指针的内存
调用函数:无
*******************************************************************/
void mat_create( mat* d_mat )
{
    d_mat->pointer = ( int** ) malloc( d_mat->row * sizeof( int* ) );
    for( int i = 0; i < d_mat->row; i++ )
    {
        d_mat->pointer[i] = ( int* ) malloc( d_mat->column * sizeof( int ) );
    }
    return;
}

/*******************************************************************
函数名称:mat_mulp
函数参数:包含相乘的两矩阵的结构体指针,目的结构体指针
返回参数:无
函数功能:计算两矩阵相乘结构并存入目的结构体中
调用函数:mat_create(mat* d_mat)
*******************************************************************/
void mat_mulp( mat* s_mat1 , mat* s_mat2 , mat* d_mat )
{
    int result = 0;

    d_mat->row = s_mat1->row;
    d_mat->column = s_mat2->column;
    mat_create( d_mat );
    for( int i = 0; i < s_mat1->row; i++ )
    {
        for( int j = 0; j < s_mat2->column; j++ )
        {
            result = 0;
            int m = 0;
            for( int k = 0; k < s_mat2->row; k++ )
            {
                result = result + s_mat1->pointer[i][m] * s_mat2->pointer[k][j];
                m++;
            }
            d_mat->pointer[i][j] = result;
            printf( "%d " , d_mat->pointer[i][j] );
        }
        printf( "\n" );
    }
}

/*******************************************************************
函数名称:input_mat
函数参数:文件指针,输入结构体指针
返回参数:无
函数功能:将文件指针指向的矩阵写入一个mat结构体中
调用函数:mat_create(mat* d_mat)
*******************************************************************/
void input_mat( FILE* file , mat* s_mat )
{
    mat_create( s_mat );
    printf( "\n" );
    for( int i = 0; i < s_mat->row; i++ )
    {
        for( int j = 0; j < s_mat->column; j++ )
        {
            fscanf( file , "%d" , &s_mat->pointer[i][j] );
            printf( "%d " , s_mat->pointer[i][j] );
        }
        printf( "\n" );
    }
    if( !feof( file ) )
    {
        fseek( file , 4L , SEEK_CUR );   //一个\n占两个字节0D0A  对Windows系统
    }
}

主函数文件 main.cpp

/**********************************************************************
关于文件指针的操作http://www.cnblogs.com/whiteyun/archive/2009/08/08/1541822.html
可以使用fun(const int* a[])防止指针内容被修改
函数指针
double pam(int)
double (*pf)(int)
pf=pam
引用必须在声明时就将它初始化,而不能像指针一样先声明后赋值
返回指向结构的引用效率更高 P234
默认参数一定要在最右边  P241
int fseek(FILE *stream, long offset, int fromwhere) 函数设置文件指针stream的位置
函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:
文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)
个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。

long ftell(FILE *stream) 用于得到文件位置指针当前位置相对于文件首的偏移字节数

rewind()  将文件内部的位置指针重新指向一个流(数据流/文件)的开头
*******************************************************************/
#include<stdio.h>               //定义输入输出函数
#include<stdlib.h>              //定义杂项函数及内存分配函数
#include"matrix.h"              //自定义函数

int main( )
{
    task( );

    return 0;
}

这是我写的作业的2.0版本吧。第一次写的太渣,内存占用过多,还没有释放,程序结构、可读性、可维护性太差,好多功能都耦合在一起,于是重新写了一遍,这次结构应该算比较清晰的。
遇到的最大的问题就是文件指针的操作。当我调用count_mat()函数之后,不知道指针已经移动了(到文件尾为NULL),导致我以为是后面的参数传不进去,调试了好久,后面的读取矩阵的时候,也要注意文件指针的定位问题。这个确实的自己调试才能真正弄明白。
知识点:文件指针操作,浅拷贝与深拷贝,矩阵的计算

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值