C基础学习笔记02

  • 数组类型
int A[5] = {0};
int B[3][5] ={0};
C语言规定[一维数组]:
    数组名(A)是数组首元素的地址
    根据数组名取地址(&A),取出的则是整个数组的地址
C语言规定[二维/多维数组]:
    int * pArr[5] -> B[x][5];
    数组名(B)是指向数组第0行的所有元素地址
    B+1 -> 是指向数组第一行的所有元素的地址
    *(B+1) -> 是指向第一行第一列的元素的地址
    *(B+1)+i <==> &B[i][j]
    B[3][5] <==> *(*(B+3)+5);
    二维数组作为参数传递:function(int (*a)[5]);
    typedef int (MyArray)[5];//为数组定义一个别名
    定义一个数组:MyArray arr ;==> int arr[5];
    定义一个指针数组:MyArray * pArr;==>int * pArr[5];
    typedef int (*pArray)[5];//为指针定义一个别名
    定义一个指针数组:pArray pArr;==> int * pArr[5];
  • 指针数组的自我结束
    char * str[] = {"abc","abc","abc","\0"};// 在数组中["\0" <==> 0 <==> NULL]
    //指针数组的遍历方式(数组元素不确定)
    void show(char ** str){
        int i = 0;
        for (;str[i] != NULL;i++)
            printf("%s\n",str[i]);
    }
  • 结构体
struct Teacher{
    char name[64];
    int age;
};
....
struct Teacher one = {"aaa",16};
struct Teacher two;
memset(&two,0,two);

//操作一[在main函数中拷贝]
two = one;//成功把one的内容拷贝到two的内容中去

//操作二[在自定义函数中拷贝(传递实参的值)]
void copyTeacher(struct Teacher to ,struct Teacher from ){to = from;}
copyTeacher(two,one);//失败,形参的值(to)发生改变,实参的值(two)并没有发生改变

//操作三[在自定义函数中拷贝(传递实参的地址)]
void copyTeacher(struct Teacher * to , struct Teacher * from){*to = *from;}
copyTeacher(&two,&one);//成功
* 结构体与一级指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct Teacher{
 char * Name;
 int age;
}Teacher;

/*分配内存*/
Teacher * createTeacher_01(int num);
int createTeacher_02(Teacher ** teacher ,int num);

/*释放内存*/
void FreeTeacher(Teacher * teacher, int num);

int main()
{

    return 0;
}

/* 函数实现 */
//不建议
Teacher * createTeacher_01(int num/*in*/){

    Teacher * temp = NULL;
    temp = (Teacher *)malloc(sizeof(Teacher) * num);//分配结构体内存[Name的内存并没有分配]
    if (temp == NULL)
        return NULL;
    memset(temp,0,sizeof(Teacher) * num);//初始化
    return temp;
}

int createTeacher_02(Teacher ** t/*out*/,int num/*in*/){

    Teacher * temp = NULL;
    temp = (Teacher *)malloc(sizeof(Teacher) * num);

    if (temp == NULL)
        return -1;
    memset(temp,0,sizeof(Teacher) * num);
    int i = 0;
    for (i = 0;i < num;i++){
        temp[i].Name = (char *)malloc(60);
        //(temp + i)->Name = (char *)malloc(60);
    }

    *t = temp;//间接修改实参的值
    return 0;
}

void FreeTeacher(Teacher * t/*in*/,int num/*in*/){

    if (t == NULL)
        return ;
    int i = 0;
    for (i = 0;i < num;i++){
        if (t[i].Name != NULL){
            free(t[i].Name);
        }
    }
    free(t);
}
* 结构体与二级指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct Teacher{
    int age;
    char * Name;
    char ** StuName;
}Teacher;

/*分配内存*/
int createTeacher(Teacher ** t,int num);

/*回收内存*/
void FreeTeacher(Teacher * t,int num);

int main()
{

    int result = 0;
    Teacher * Tarr = NULL;
    result = createTeacher(&Tarr,3);
    if (result){
        printf("memery error!");
        return 0;//结束程序
    }

    int i = 0 ,j = 0;
    char name[20] = {0};
    for (i = 0;i < 3;i++){
        Tarr[i].age = (i+1);//age

        sprintf(name,"%s%d","name:",i);
        strcpy(Tarr[i].Name,name);//name

        for(j = 0;j < 3;j++){
            sprintf(name,"%s%d%d","sname:",i,j);
            strcpy(Tarr[i].StuName[j],name);//stuname
        }
    }

    for (i = 0;i < 3;i++){
        printf("age = %d\n",Tarr[i].age);
        printf("name = %s\n",Tarr[i].Name);
        for (j = 0;j < 3;j++){
            printf("\tstuname = %s\n",Tarr[i].StuName[j]);
        }
        printf("=================\n");
    }

    FreeTeacher(Tarr,3);

    return 0;
}

/*函数实现*/
int createTeacher(Teacher ** t/*out*/,int num/*in*/){

    Teacher * temp = NULL;
    //分配结构体数组
    temp = (Teacher *)malloc(sizeof(Teacher) * num);
    if (temp == NULL){
        return -1;
    }
    memset(temp,0,sizeof(Teacher) * num);
    int i = 0, j = 0;
    for (i = 0;i < num;i++){
        //分配一级指针
        temp[i].Name = (char *)malloc(60);
        //分配二级指针
        char ** pt = (char ** )malloc(sizeof(char *) * 3);
        for (j = 0;j < 3;j++){
            pt[j] = (char *)malloc(60);
        }
        temp[i].StuName = pt;
    }
    *t = temp;
    return 0;
}

void FreeTeacher(Teacher * t/*in*/,int num/*in*/){
    if (t == NULL){
        return ;
    }
    int i = 0, j = 0;
    for (i = 0;i < num;i++){
        //释放一级指针
        if (t[i].Name != NULL){
            free(t[i].Name);
        }
        //释放二级指针
        char ** ptr = t[i].StuName;
        for (j = 0;j < 3;j++){
            if (ptr[i] != NULL){
                free(ptr[i]);
            }
        }
        free(ptr);
        t[i].StuName = NULL;
    }
    free(t);
}
* 数组合并
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/*合并*/
int strArray(char ** str1,int len1,char (*str2)[10],int len2,char *** strArr,int * Arrlen);

/*内存回收*/
void FreeArray(char ** arr,int len);
void FreeArray_02(char *** arr,int len);

int main()
{
    //char *str1[10] ={"xxx","yyy","zzz"};//char *str[] ==> char ** str
    //char str2[3][10] = {"aaa","bbb","ccc"};//char str[][] ==> char (*str)[]

    //int arrlength = 0;
    //char ** strArr = NULL;//strArr = str1 + str2(将str1和str2的内容放进strArr)

    //strArray(str1,3,str2,3,&strArr,&arrlength);
    //FreeArray_02(&strArr,arrlength);

    return 0;
}

/*函数实现*/
int strArray(char ** str1/*in*/,int len1/*in*/,char (*str2)[10]/*in*/,int len2/*in*/,char *** strArr/*out*/,int * Arrlen/*out*/){

    char ** ArrayList = NULL;
    int i = 0 , j = 0;

    /*分配内存*/
    ArrayList = (char **)malloc(sizeof(char *) * (len1 + len2));
    if (ArrayList == NULL){
        return -1;
    }

    memset(ArrayList,0,sizeof(char*) * (len1 + len2));

    int length = 0;//计算每个字符串的大小

    /*拷贝str1->ArrayList*/
    for (i = 0;i < len1;i++){
        length = strlen(str1[i]) + 1;//"\0"
        ArrayList[i] = (char *)malloc(length);
        strcpy(ArrayList[i],str1[i]);
    }

    /*拷贝str2->ArrayList*/
    for(j = 0;j < len2;j++,i++){//"i++"
        length = strlen(str2[j]) + 1;
        ArrayList[i] = (char *)malloc(length);
        strcpy(ArrayList[i],str2[j]);
    }

    /*赋值*/
    *strArr = ArrayList;
    *Arrlen = (len1 + len2);

    return 0;
}

void FreeArray(char ** arr/*in*/,int len/*in*/){
    if (arr == NULL){
        return;
    }
    char ** pstr = arr;
    int i = 0;
    for (i = 0;i < len;i++){
        if (pstr[i] != NULL){
            free(pstr[i]);
        }
    }
    free(pstr);
}

void FreeArray_02(char *** arr/*in*/,int len/*in*/){
    if (arr == NULL){
        return;
    }
    char ** pstr = *arr;
    int i = 0;
    for (i = 0;i < len;i++){
        if (pstr[i] != NULL){
            free(pstr[i]);
        }
    }
    free(pstr);
    *arr = NULL;
}
* 结构体中的浅拷贝和深拷贝
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct Temp{
    int data;
    char * text;
}Temp;

void copyTemp(Temp * to,Temp * from);

int main()
{

    Temp temp1,temp2;

    memset(&temp1,0,sizeof(temp1));
    memset(&temp2,0,sizeof(temp2));

    temp1.data = 10;
    temp1.text = (char *)malloc(60);
    strcpy(temp1.text,"aaaaaa");

    //将temp1 -> temp2
    copyTemp(&temp2,&temp1);

    //释放内存(temp1)
    if (temp1.text != NULL){
        free(temp1.text);
        temp1.text = NULL;
    }

    //释放内存(temp2)
    if (temp2.text != NULL){
        //1.
        printf("[%s]\n",temp2.text);
        //2.
        free(temp2.text);

        /*执行浅拷贝时
        代码段1会打印出一堆垃圾值
        代码段2则会引发异常[不同的编译器可能处理方式不同]
        原因:
            执行浅拷贝,temp1.text只是将只是将自己的内存地址拷贝给temp2.text,并没有为temp2.text重新分配一块内存,即
            temp1.text -> 0x100;//假设temp1.text指向的内存地址是[0x100("aaaaaa")]
            *to = *from ==> temp2.text = temp1.text ==>temp2.text ->0x100//并未重新为temp2.text分配内存
         :在结构体中"="操作符是一种浅拷贝
        */

        //执行深拷贝时重新为[temp2.text]分配了内存则不会出问题

        temp2.text = NULL;
    }

    return 0;
}

void copyTemp(Temp * to/*out*/,Temp * from/*in*/){
    //结构体中的浅拷贝方式===================
    //浅拷贝1
    *to = *from;
    //浅拷贝2
    //memcpy(to,from,sizeof(Temp));
    //===================================

    //结构体中的深拷贝===================
    //深拷贝
    *to = *from;
    to->text = (char *)malloc(60);
    strcpy(to->text,from->text);
    //===================================
}
* 结构体中的偏移量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct Adv{
    char name[64];
    int age;
    char * text;
}Adv;

int main()
{

    Adv * p = NULL;
    //age在结构体中的偏移量
    int offsize = (int)(&(p->age));
    //offsize = 64因为name的长度为64(不考虑大端对齐与小端对齐)

    //将"0"地址强制解释为[Adv*]类型然后求出age相对p的偏移量
    offsize = (int)(&(((Adv*)0)->age));

    //初始化
    p = (Adv*)malloc(sizeof(Adv));
    strcpy(p->name,"芦苇微微");
    p->age = 16;
    p->text = (char *)malloc(64);
    strcpy(p->text,"一笑奈何");

    //定义一个无符号类型的指针
    void * pstr = NULL;
    pstr = (int)(&(p->age)) - offsize;     //指向p首地址

    printf("%s\n",((Adv*)pstr)->name);
    printf("%s\n",((Adv*)pstr)->text);
    printf("%d\n",((Adv*)pstr)->age);

    return 0;
}
* 文件操作(fgetc & fputc[单个字符读取/写入])
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//写文件
int writeFile(const char * path,char * data);
//读文件
int readFile(const char * path);

int main()
{

    char * data = "Talent is continuing patience!\n";//写入内容
    char * path = "D:/Test/1.txt";//文件内容
    writeFile(path,data);
    readFile(path);
    return 0;
}

int writeFile(const char * path/*in*/,char * data/*in*/){

    FILE * fp = NULL;
    fp = fopen(path,"r+");
    if (fp == NULL){
        return -1;
    }

    int i = 0;
    for (i = 0;i < strlen(data);i++){
        fputc(data[i],fp);
    }

    if (fp != NULL){
        fclose(fp);
    }
    return 0;
}

int readFile(const char * path /*in*/){

    FILE * fp = NULL;
    if ((fp = fopen(path,"r+")) == NULL){
        return -1;
    }

    while (!feof(fp)){
        char str = fgetc(fp);
        printf("%c",str);
    }

    /*
    char str = NULL;
    while ((str = fgetc(fp)) != EOF) printf("%c",str);
    */

    if (fp != NULL)
    {
        fclose(fp);
    }
    return 0;
}
r   以只读方式打开文件,只允许读取,不允许写入。该文件必须存在。
r+  以读/写方式打开文件,允许读取和写入。该文件必须存在。
rb+ 以读/写方式打开一个二进制文件,允许读/写数据。
rt+ 以读/写方式打开一个文本文件,允许读和写。
w   以只写方式打开文件,若文件存在则长度清为0,即该文件内容消失,若不存在则创建该文件。
w+  以读/写方式打开文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a   以追加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)。
a+  以追加方式打开可读/写的文件。若文件不存在,则会建立该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(原来的EOF符 不保留)。
wb  以只写方式打开或新建一个二进制文件,只允许写数据。
wb+ 以读/写方式打开或建立一个二进制文件,允许读和写。
wt+ 以读/写方式打开或建立一个文本文件,允许读写。
at+ 以读/写方式打开一个文本文件,允许读或在文本末追加数据。
ab+ 以读/写方式打开一个二进制文件,允许读或在文件末追加数据。
* 文件操作(fgets [按行读取])
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int readFile(const char * path);

int main()
{

    char * path = "D:/Test/1.txt";
    readFile(path);
    return 0;
}

int readFile(const char * path/*in*/){

    FILE * fp = NULL;

    if ((fp = fopen(path,"r+")) == NULL){
        return -1;
    }

    char buf[1024] = {0};//缓冲区
    char * pstr = NULL;

    while ((pstr = fgets(buf,1024,fp)) != NULL){
        printf("%s",pstr);
    }

    if (fp != NULL){
        fclose(fp);
    }
    return 0;
}
* 文件操作(fread & fwrite[按结构体格式读取/写入内容])
typedef struct Teacher{
    char name[12];
    int age;
}Teacher;

int readFile(char * path);
int writeFile(const char * path,Teacher * t);

int main()
{

    char * path = "D:/Test/2.txt";
    Teacher t[3] ;
    memset(&t,0,sizeof(Teacher) * 3);
    int i = 0;
    for (i = 0;i < 3;i++){
        sprintf(t[i].name,"%d%d%d",(i+3),(i+3),(i+3));
        t[i].age = (i+5);
    }

    writeFile(path,t);
    readFile(path);

    return 0;
}

int writeFile(const char * path/*in*/,Teacher * t/*in*/){

    FILE * fp = NULL;
    if ((fp = fopen(path,"wb")) == NULL){
        return -1;
    }

    int i= 0;
    int count = 1;
    for (i = 0;i < 3;i++){
        if (count != fwrite(&t[i],sizeof(Teacher),count,fp)){
           return -1;
        }
    }
    if (fp != NULL){
        fclose(fp);
    }

    return 0;
}

int readFile(char * path/*in*/){
    FILE * fp = NULL;
    if ((fp = fopen(path,"rb+")) == NULL){
        return -1;
    }

    Teacher t[3];
    memset(&t,0,sizeof(Teacher) * 3);

    int i = 0;
    int count = 1;
    for (i = 0;i < 3;i++){
        if (count != fread(&t[i],sizeof(Teacher),count,fp)){
            return -1;
        }
    }
    for (i = 0;i < 3;i++){
        printf("%s - %d\n",t[i].name,t[i].age);
    }

    if (fp != NULL){
        fclose(fp);
    }
    return 0;
}
    //fread & fwrite参数解释
    //_Check_return_opt_ _CRTIMP size_t __cdecl 
    //  fwrite(_In_count_x_(_Size*_Count) const void * _Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE * _File);
    //函数参数
    //_Str : 从内存块的开始
    //_Size  //内存打包技术
    //_Count 写多少次
    //_File : 写入到 文件指针 所指向的文件中
* 按(key=value)的形式读写文件
====>MAIN.C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "readCFG.h"
int main()
{
    /*读===========================
    char * path = "D:/Test/3.txt";
    char * key = "love";
    char str[12] = {0};
    int  length = 0;
    getReadCFGFile(path,key,str,&length);
    printf("str = %s\n",str);
    ==============================*/

    /*写=============================
    char * path = "D:/Test/3.txt";
    char * key = "love";
    char * value = "yurisa";
    setReadCFGFile(path,key,value);
    ================================*/
    return 0;
}

====>READCFG.H
#ifndef READCFG_H_INCLUDED
#define READCFG_H_INCLUDED
//读取配置文件
int getReadCFGFile(const char * path,const char * key,char * value,int * valuelength);
//写入/修改配置文件
int setReadCFGFile(const char * path,const char * key,const char * value);
#endif // READCFG_H_INCLUDED

====>READCFG.C
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX 1024

int getReadCFGFile(const char * path/*in*/,const char * key/*in*/,char * value/*out*/,int * valuelength/*out*/){

    FILE * fp = NULL;
    char * pTmp = NULL;
    char * pstr = NULL;
    char BUF[MAX] = {0};
    int flag = 0;

    if ((fp = fopen(path,"r+")) == NULL){
        return -1;
    }

    while ((pstr = fgets(BUF,MAX,fp)) != NULL){
        //判断是否有"="和key是否在这一行
        if ((pstr = strchr(BUF,'=')) == NULL || (pstr = strstr(BUF,key)) == NULL){
            continue;
        }

        flag = 1;//[找到key]
        //指针移动到value的位置
        pTmp = BUF + strlen(BUF) - 1;//"key = value\n"==>"\n"
        pstr = BUF + strlen(key) + 1; //"key = value\n" ==>"v"
        //获取value,剔除空格
        for (;*pstr == ' ';pstr++);
        for (;*pTmp == ' ' || *pTmp == '\n';pTmp--);

        break;
    }

    if (!flag){
        return -1;
    }

        //赋值
    *valuelength = (int)(pTmp - pstr) + 1;
    memcpy(value,pstr,*valuelength);

    if (fp != NULL){
        fclose(fp);
    }

    return 0;

}

int setReadCFGFile(const char * path/*in*/,const char * key/*in*/,const char * value/*in*/){

    if(path == NULL || key == NULL || value == NULL){
        return -1;
    }

    FILE * fp = NULL;
    char * pstr = NULL;
    char BUF[MAX] = {0};
    char FILEBUF[MAX * 8] = {0};
    int length = 0;
    int flag = 0;

    if ((fp = fopen(path,"r+")) == NULL){
        return -1;
    }

    fseek(fp,0,SEEK_END);//文件指针移动到文件末尾
    length = ftell(fp);
    fseek(fp,0,SEEK_SET);//文件指针移动到文件头

    if(length > MAX * 8){
        return -1;
    }

    while ((pstr = fgets(BUF,MAX,fp)) != NULL){
        //判断key是否存在
        if ((pstr = strstr(BUF,key)) != NULL){
                flag = 1;
            sprintf(BUF,"%s = %s\n",key,value);
            strcat(FILEBUF,BUF);
        }else{
            strcat(FILEBUF,BUF);
        }
    }

    if (!flag){
        sprintf(BUF,"%s = %s\n",key,value);
        strcat(FILEBUF,BUF);
    }

    //关闭文件流并重新写入
    if(fp != NULL){
        fclose(fp);
        fp = NULL;
    }

    fp = fopen(path,"wt+");
    fputs(FILEBUF,fp);

    if(fp != NULL){
        fclose(fp);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值