C语言 百炼成钢22

/*
题目58: 编写一个业务函数,实现按行读取文件。把内容按照第三种内存模型打包数据传出,把行数通过函数参数传出。
函数原型有两个,任意选择其一
要求1:请自己任意选择一个接口(函数),并实现功能;70分
要求2:编写测试用例。30分
要求3:自己编写内存释放函数
*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//按行读取文件
int ReadFile(const char *path/*in*/,char ***pout/*out*/,int *row){
    int ERRO_MSG = 0;
    if (path == NULL || pout == NULL || row==NULL)
    {
        ERRO_MSG = 1;
        printf("", ERRO_MSG);
        return ERRO_MSG;
    }
    //定义文件行数
    int index = 1;
    //定义二维数组
    char **parr1 = (char **)malloc(sizeof(char *)*index);
    memset(parr1, 0, sizeof(sizeof(char *)*index));
    if (parr1==NULL)
    {
        ERRO_MSG = 2;
        printf("分配内存失败 erro msg:%d\n", ERRO_MSG);
        return ERRO_MSG;
    }
    //定义文件指针
    FILE *pfr = NULL;
    //打开文件
    pfr = fopen(path, "r");
    if (pfr == NULL)
    {
        ERRO_MSG = 3;
        printf("打开文件失败 文件路径是%s; erro msg:%d\n",path, ERRO_MSG);
        return ERRO_MSG;
    }
    while (!feof(pfr)){
        //定义缓存数组
        char *buf = (char *)malloc(sizeof(char)* 100);
        if (buf==NULL)
        {
            ERRO_MSG = 5;
            printf("分配内存失败 erro msg:%d\n", ERRO_MSG);
            goto FileEND;
        }
        memset(buf, 0, sizeof(char)* 100);
        //fgets()读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋‘\0‘)
        char *pflag= fgets(buf, 100, pfr);
        //ferror()函数:获取文件流状态,如果ferror返回值为0(假),表示未出错。如果返回一个非零值,表示出错。
        if (pflag == NULL || ferror(pfr))
        {
            ERRO_MSG = 4;
            //重置文件流状态,清除错误信号
            clearerr(pfr);
            //注:如果不重置文件流状态,那么下次读取该文件正确状态仍然会报这个错误
            printf("按行读取文件失败 erro msg:%d\n", path, ERRO_MSG);
            goto FileEND;
        }
        //数据加入二维数组
        parr1[index - 1] = buf;
        index++;
        //重新分配内存空间
        parr1 = (char **)realloc(parr1, sizeof(char *)*index);
    }
FileEND:
    //关闭文件指针
    if (pfr!=NULL)
    {
        fclose(pfr);
        pfr = NULL;
    }
    //二维数组最后一个元素置零
    parr1[index - 1] = NULL;
    *pout = parr1;
    *row = index - 1;
    return ERRO_MSG;
}

//打印数据
void PeintfA(char **pin/*in*/){
    if (pin==NULL)
    {
        printf("二维数组指针为空\n");
    }
    printf("以下是读取的数据\n");
    while (*pin){
        printf("%s\n", *pin);
        pin++;
    }
}

//释放内存
int FreeAll(char ***pin/*in*/){
    int ERRO_MSG = 0;
    if (pin == NULL)
    {
        ERRO_MSG = 1;
        printf("", ERRO_MSG);
        return ERRO_MSG;
    }
    char **ptemp = *pin;
    while (*ptemp){
        free(*ptemp);
        *ptemp = NULL;
        ptemp++;
    }
    //报错:触发了一个断点
    //原因:ptemp指针移动位置了
    if (*pin != NULL)
    {
        free(*pin);
        *pin = NULL;
    }

    return ERRO_MSG;
}

void main(){
    char *path = "E:/Look/a.txt";
    //定义返回数组
    char **pres = NULL;
    //定义返回行 测试参数
    int row = 0,ret=0;
    ret = ReadFile(path, &pres, &row);
    if (ret!=0)
    {
        printf("读取文件出错\n");
        goto END;
    }
    //打印文件
    PeintfA(pres);
END:
    FreeAll(&pres);
    system("pause");
}

时间: 2024-12-28 12:55:03

C语言 百炼成钢22的相关文章

C语言 百炼成钢21

//题目57:编写一个业务函数,实现字符串(前后各有三个空格,单词前后也均有空格) //" i am student, you are teacher " , //各个单词首字符大写,结果如下" i am student, you are teacher " , //要求1:实现所有接口 70 //要求2:写出测试程序 30 #include<stdio.h> #include<stdlib.h> #include<string.h&g

C语言 百炼成钢27

/* 题目63:编写C++程序完成以下功能: (1)声明一个纯虚函数类Shape(形状),其中包含来计算面积.计算周长的方法: (2)从Shape派生两个类矩形和圆形: (3)从矩形派生正方形: (4)分别实现派生类构造函数.析构函数和其他方法: (5)创建派生类的对象,观察构造函数.析构函数调用次序: (6)利用抽象类做函数参数(基类指针指向子类对象,多态特性),计算不同对象的面积和周长. */ #define _CRT_SECURE_NO_WARNINGS #include<iostream

C语言 百炼成钢17

//题目49:老师将糖果分成若干份,让学生按任意次序领取,第一个领取的,得到1份加上剩余糖果的1/10, //第二个领取的,得到2份加上剩余糖果的1/10,第三个领取的,得到3份加上剩余糖果的1/10,以此类推, //求共有多少个学生,多少份糖果 #include<stdio.h> #include<stdlib.h> //思路:该题的要求是求一个糖果的数量,这个数量必须保证每个学生领取到的糖果都是整份数,并不要求所有学生分的糖果分数一样 //根据多定义变量,简化运算难度规则,定义

C语言 百炼成钢16

//题目46:海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只 //猴子把多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均分成五份,又多了 //一个,它同样把多的一个扔入海中,拿走了一份,第三.第四.第五只猴子都是这样做的, //问海滩上原来最少有多少个桃子? #include<stdio.h> #include<stdlib.h> //分析:最少有多少个桃子,说明是满足条件的最小数:假设有X个桃子,第一个猴子的桃子数量是(X-1)/5,

C语言 百炼成钢11

//题目31:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 //判断第二个字母. #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<math.h> //分析:通过输入的字母判定星期几,可以使用if()else void main(){ char str[7] = { 0 }; scanf("%s",str); switc

C语言 百炼成钢10

//题目28:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁.问第4个人岁数,他说比第 //3个人大2岁.问第三个人,又说比第2人大两岁.问第2个人,说比第一个人大两岁.最后 //问第一个人,他说是10岁.请问第五个人多大? #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<math.h> //分析:经过阅读,发现f(5)=f(4)+2;f(4)=f(3)

C语言 百炼成钢2

//题目5:输入三个整数x,y,z,请把这三个数由小到大输出. #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> void sortnum(int *x,int *y,int *z){ int temp = 0; if (*x>*y) { temp = *x; *x = *y; *y = temp; } if (*y>*z) { temp = *z; *z = *y; *y = te

程序员之---C语言细节22(函数返回指针注意事项&amp;lt;悬空指针&amp;gt;、查看进程能够分配的内存大小)

主要内容:函数返回指针注意事项<悬空指针>.查看进程能够分配的内存大小 #include <stdio.h> char * favorite_fruit() { static char fruit[] = "apple"; // 不加static的话这个函数还回的指针会悬空,由于在函数退出时fruit组数被销毁 // 加了static后fruit数组分配在数据段里,而不是堆栈中.生命期和程序一样长,函数退出时变量 // 依旧有效 return fruit; }

程序猿之---C语言细节22(函数返回指针注意事项&lt;悬空指针&gt;、查看进程可以分配的内存大小)

主要内容:函数返回指针注意事项<悬空指针>.查看进程可以分配的内存大小 #include <stdio.h> char * favorite_fruit() { static char fruit[] = "apple"; // 不加static的话这个函数还回的指针以及悬空,因为在函数退出时fruit组数被销毁 // 加了static后fruit数组分配在数据段里,而不是堆栈中,生命期和程序一样长,函数退出时变量 // 依然有效 return fruit; }