(五)C语言之联合体,枚举与IO

一、联合体(共用体)

1、定义

不同类型的变量共同占用一段内存(相互覆盖),联合变量任何时刻只有一个成员存在,节省内存

2、大小

联合体变量的大小=最大的成员所占的字节数

 union MyValue{
     int x;
     int y;
     double z;
 };

 void main(){
     union MyValue d1;
     d1.x = 90;
     d1.y = 100;
     printf("%d,%d,%lf\n",d1.x,d1.y,d1.z);
     d1.z = 25.8;
     printf("%d,%d,%lf\n",d1.x,d1.y,d1.z);
     getchar();
 }

输出结果为:

100,100,-92559592117433135502616407313071917486139351398276445610442752.000000
-858993459,-858993459,25.800000

根据上面代码可得出结论:在联合体中,最后一次赋值有效

二、枚举

1、定义

“枚举”就是把可能的值(固定的数据)一一的列举出来,变量的值只限于列举出来的值的范围

例如:

enum Day{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

void main(){
    enum Day d = Wednesday;
    printf("Today is %d,%#x\n",d,&d);
    getchar();
}

三、IO操作

1、读取文本文件

参考文档

读取文件的方法为:

FILE * fopen(char * path,char * model)

void main(){
    char path[] = "D:\\test.txt";
    //打开 
    FILE *fp = fopen(path,"r");
    if(fp == NULL){
        printf("文件打开失败...\n");
        return;
    }
    //读取
    char buff[50];//缓冲
    while(fgets(buff,50,fp)){
        printf("%s",buff);
    }
    //关闭
    fclose(fp);
    getchar();
}

2、写入文本文件

参考文档

写入文件的方法为:

fputs(char * text,FILE * _file)

void main(){
    char path[] = "D:\\test_new.txt";
    //打开 
    FILE *fp = fopen(path,"w");
    if(fp == NULL){
        printf("文件打开失败...\n");
        return;
    }
    //写入
    char *text = "How are you?\nI am fine,Thank You!";
    fputs(text,fp);
    //关闭
    fclose(fp);
    getchar();
}

3、操作二进制文件

  • 计算机的文件存储在物理上都是二进制;文本文件和二进制之分,其实是一个逻辑之分

  • C读写文本文件与二进制文件的差别仅仅体现在回车换行符

  • 写文本时,每遇到一个’\n’,会将其转换成’\r\n’,(回车换行)

  • 读文本时,每遇到一个’\r\n’,会将其转换成’\n’

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
参考文档
参数:

  • ptr :
    指向大小至少为(size * count)个字节的内存块的指针,转换为void *。
  • size :
    要读取的每个元素的大小(以字节为单位)。
    size_t是无符号整数类型。
  • count :
    元素数量,每个元素的大小为字节大小。
    size_t是无符号整数类型。
  • stream:
    指向指定输入流的FILE对象的指针。

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
参考文档
参数:

  • ptr :
    指向大小至少为(size * count)个字节的内存块的指针,转换为void *。

  • size :
    要读取的每个元素的大小(以字节为单位)。
    size_t是无符号整数类型。

  • count :
    元素数量,每个元素的大小为字节大小。
    size_t是无符号整数类型。

  • stream:
    指向指定输入流的FILE对象的指针。

    void main(){
      char read_path[] = "D:\\avatar.jpg";
      char write_path[] = "D:\\avatar_new.jpg";
      //读的文件,b字符表示操作二进制文件(binary)
      FILE *read_fp = fopen(read_path,"rb");
    
      //写的文件
      FILE *write_fp = fopen(write_path,"wb");;
      //复制
      int buff[50];//缓冲区域
      int len = 0;//每次读到的内容的长度
      while((len = fread(buff,sizeof(int),50,read_fp))!=0){
          //将读取到的内容写入新文件
          fwrite(buff,sizeof(int),50,write_fp);
      }
      //关闭
      fclose(read_fp);
       fclose(write_fp);
      getchar();
    }

4、获取文件的大小

重新定位文件指针:

int fseek ( FILE * stream, long int offset, int origin );

参数:

  • stream:
    指向标识流的FILE对象的指针。
  • offset:
    二进制文件:从原点偏移的字节数。
    文本文件:零或ftell返回的值
  • origin:
    位置用作偏移的参考。 它由中定义的以下常量之一指定,专门用作此函数的参数:
Constant Reference position
SEEK_SET 文件开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件结束
*允许库实现无意义地支持SEEK_END(因此,使用它的代码没有真正的标准可移植性)。

返回当前的文件指针,相对于文件开头的位移量:

long ftell ( FILE * stream);

void main(){
    char read_path[] = "D:\\avatar.jpg";
    FILE *fp = fopen(read_path,"r");
    //重新定位文件指针
    fseek(fp,0,SEEK_END);
    //返回当前的文件指针,相对于文件开头的位移量
    long filesize = ftell(fp);
    printf("filesize = %d\n",filesize);
    getchar();
}

5、文本文件的加密解密

//加密
void crpypt(char normal_path[], char crypt_path[]) {
    //打开文件
    FILE *normal_fp = fopen(normal_path, "r");
    FILE *crypt_fp = fopen(crypt_path, "w");
    //一次读取一个字符
    int ch;
    while ((ch = fgetc(normal_fp)) != EOF) {//End of FILE
        //加密
        fputc(ch ^ 9, crypt_fp);
    }
    fclose(normal_fp);
    fclose(crypt_fp);
}

//解密
void decrpypt(char crypt_path[], char decrpypt_path[]) {
    //打开文件
    FILE *crypt_fp = fopen(crypt_path, "r");
    FILE *decrpypt_fp = fopen(decrpypt_path, "w");
    //一次读取一个字符
    int ch;
    while ((ch = fgetc(crypt_fp)) != EOF) {//End of FILE
        //加密
        fputc(ch ^ 9, decrpypt_fp);
    }
    fclose(crypt_fp);
    fclose(decrpypt_fp);
}

void main() {
    char normal_path[] = "D:\\test.txt";
    char crypt_path[] = "D:\\test_crypt.txt";
    char decrypt_path[] = "D:\\test_decrypt.txt";
    crpypt(normal_path, crypt_path);
    decrpypt(crypt_path, decrypt_path);
    getchar();
}

6、二进制文件的加密解密

读取二进制文件中的数据时,一个一个字符读取
密码:qazwsx

//加密
void crpypt(char normal_path[], char crypt_path[], char password[]) {
    //打开文件
    FILE *normal_fp = fopen(normal_path, "rb");
    FILE *crypt_fp = fopen(crypt_path, "wb");
    //一次读取一个字符
    int ch;
    int i = 0;
    int pwd_len = strlen(password);
    while ((ch = fgetc(normal_fp)) != EOF) {//End of FILE
        //加密
        fputc(ch ^ password[i % pwd_len], crypt_fp);
        i++;
    }
    fclose(normal_fp);
    fclose(crypt_fp);
}

//解密
void decrpypt(char crypt_path[], char decrpypt_path[], char password[]) {
    //打开文件
    FILE *crypt_fp = fopen(crypt_path, "rb");
    FILE *decrpypt_fp = fopen(decrpypt_path, "wb");
    //一次读取一个字符
    int ch;
    int i = 0;
    int pwd_len = strlen(password);
    while ((ch = fgetc(crypt_fp)) != EOF) {//End of FILE
        //加密
        fputc(ch ^ password[i % pwd_len], decrpypt_fp);
        i++;
    }
    fclose(crypt_fp);
    fclose(decrpypt_fp);
}

void main() {
    char password[] ="qazwsx";
    char normal_path[] = "D:\\avatar.jpg";
    char crypt_path[] = "D:\\avatar_crypt.jpg";
    char decrypt_path[] = "D:\\avatar_decrypt.jpg";
    crpypt(normal_path, crypt_path,password);
    decrpypt(crypt_path, decrypt_path,password);
    getchar();
}