数据类型
实例1
各数据类型对应的占位符
#include <stdio.h>
int main2() {
printf("T2的世界!\n");
int i=100;
double d=200;
long l=200;
short a=100;
float s=200;
char c='d';
char * str="World Hello";
printf("i的值为%d\n",i);
printf("d为%lf\n",d);
printf("s为%f\n",s);
printf("c为%c\n",c);
printf("str为%s\n",str);
return 0;
}
非0即true 除了0之外都是true
实例2
字节长度 使用sizeof获取
#include <stdio.h>
int main3() {
printf("int数据的字节:%d\n", sizeof(int));
printf("double数据的字节:%d\n", sizeof(double ));
printf("char数据的字节:%d\n", sizeof(char));
return 0;
}
实例3
取地址符&
#include <stdio.h>
int main4(){
int num1=10001;
printf("此number1变量的地址是%p\n",&num1);
return NULL;
}
C语言中万物皆地址
#include <stdio.h>
int main5(){
int int_num=100;
double double_num=200;
printf("intnum的值为:%d\n",int_num);
printf("intnum的值为:%lf\n",double_num);
printf("地址取intnum的值为:%d\n",*(&int_num));
printf("地址取intnum的值为:%lf\n",*(&double_num));
int * intP=&int_num;
double * pDouble=&double_num;
printf("intnum的值为:%d\n",*intP);
printf("intnum的值为:%lf\n",*pDouble);
return NULL;
}
如int_num的地址为001H 而 &int_num=001H ,*为获取地址的值,如 * (&int_num)获取&int_num的值,即获取地址为001H的值,100
操作变量值,需要对地址进行操作
#include <stdio.h>
int main6(){
int i = 100;
int *p = &i;
*p +=100;
printf("i的值为:%d\n",i);
}
函数
#include <stdio.h>
// void change(int i); C不能函数重载
void changea(int * i);
int main7(){
int i = 100;
changea(&i);
printf("%d\n",i);
return 0;
}
//void change(int i){
// i=200;
//}
//使用指针
void changea(int * i){
*i=666;
}
函数体在main()函数前可不用声明,在main函数后需要声明。
注:
- 声明可以不带参数,因为c语言不支持函数重载,函数名唯一
- 操作变量赋值,需要传入变量的地址,如void change(int i)传入的为数值不能修改i值,而void changea(int * i)能修改i的值
参数交换实例
#include "stdio.h"
//由于C不支持重载,不需要写参数,根据名字即可找到对应
void change(int *pInt, int *pInt1);
int main() {
int a = 100;
int b = 200;
change(&a, &b);
printf("交换后a=%d,b=%d\n",a,b);
}
void change(int *pInt, int *pInt1) {
int numA= *pInt;
*pInt=*pInt1;
*pInt1=numA;
}
指针和数组
#include <stdio.h>
int main2() {
int num = 999;
//最多三级指针
int * num_p = #
int ** num_p_p = &num_p;
int *** num_p_p_p = &num_p_p;
printf("num_p的值:%p, num_p_p的值是:%p, num_p_p的值是:%p\n",num_p,num_p_p,num_p_p_p);
printf("获取最终的值:%d\n",***num_p_p_p);
return 0;
}
指针自身也有地址,于是存在嵌套,多级指针便是嵌套,使用*获取下一层的值如 *** num_p_p_p的获取流程:先获取到num_p_p所对应的值&num_p再获取&num所对应的值,再获取这个地址所对应的值
#include "stdio.h"
int main() {
int arr[]={1,2,3,4};
// for (int i = 0; i < 4; ++i) {
//
// }
int i=0;
for (i = 0; i < 4; ++i) {
printf("数组%d的值%d\n",i,arr[i]);
}
printf("arr = %p \n",arr);
printf("&arr = %p \n",&arr);
printf("&arr[0] = %p \n",&arr[0]);
}
//数组的内存地址 == 第一个元素的内存地址 == &arr
//数组的内存地址 == 第一个元素的内存地址,不是其他元素的
int * arr_p=arr;
printf("%d\n",*arr_p);
取到的也是数组第一个的值
int i=0;
for (int i = 0; i < 4; ++i) {
printf("数组%d的值%d\n",i,arr[i]);
}
为兼容写法,c语言不同java一处编译处处可行,c语言编译器不同环境不同语法有差异
指针位移
int * arr_p=arr;
printf("%d\n",*arr_p);//1
arr_p++;
printf("%d\n",*arr_p);//2
arr_p += 2;
printf("%d\n",*arr_p);//4
arr_p -= 3;//挪到到元素1
printf("%d\n",*arr_p);//1
arr_p += 3000;
printf("%d\n",*arr_p);//输出系统值 不会越界 野值
指针遍历数组
#include "stdio.h"
int main() {
int arr[] = {1,2,3,4};
int * arr_p = arr;
int i=0;
for (i = 0; i < 4; ++i) {
printf("位置%d的值为:%d\n",i,*(arr_p+i));
printf("位置%d的内存地址值为:%d\n",i,(arr_p+i));
}
}
输出为
位置0的值为:1
位置0的内存地址值为:15989356
位置1的值为:2
位置1的内存地址值为:15989360
位置2的值为:3
位置2的内存地址值为:15989364
位置3的值为:4
位置3的内存地址值为:15989368
地址每次加4,因为int 的字节为4
**结论:**数组为连续的内存空间(没有断层,有规律),每次挪动的是数组类型的大小,如int 每次挪动4个字节
循环给数组赋值
#include <stdio.h>
int main() {
int arr[4];
int *arrp = arr;
int i = 0;
//sizeof(arr) == sizeof arr
for (i = 0; i < sizeof arr / sizeof(int); ++i) {
//拿到数组元素地址
*(arrp + i) = (i + 10000);
}
//遍历输出
for (int j = 0; j < sizeof arr / sizeof(int); ++j) {
printf("位置%d的值为:%d\n",j,*(arrp+j));
}
return 0;
}
sizeof arr=16 ,sizeof(int)=4
数组指针操作的几种方式
#include <stdio.h>
int main() {
int arr[] = {123,22,33,44214};
int *arrp = arr;
int i = 0;
for (int i = 0; i < sizeof arr / sizeof(int); ++i) {
// printf("%d\n",arrp[i]);
printf("%d\n",*(arrp+i));//挪动到元素 i 再取元素i内存地址所对应的值
// printf("%d\n",*arrp+i);//
}
return 0;
}
指针类型的用处
- 任何类型的指针占用的空间大小都是相同的(32位CPU是4字节;64位CPU是8字节)
- 既然任何类型的指针占用的空间大小都是相同的,为什么指针还需要类型呢?指针只是指向了一个内存地址,但是当存内存中取值的时候,系统不知道你要从当前指针指向的地址,取几个字节,指定了指针的类型后,系统就知道取几个字节了。char类型取1个字节,short类型取2个字节,int类型去4个字节。
指针函数
#include <stdio.h>
void add(int num1,int num2) {
printf("num1 + num2 = %d\n", (num1 + num2));
}
void del(int num1,int num2) {
printf("num1 - num2 = %d\n", (num1 - num2));
}
//操作回调
//void (*method)(int,int)声明好 函数指针
//void 返回值
// (*method) 函数名
//(int,int)两个参数
void opreate(void (*method)(int,int),int num1,int num2){
method(num1, num2);
}
int main() {
opreate(add,10,20);
opreate(del,100,20);
return 0;
}
原理:
add()和del()函数进栈,有各自的内存地址,如add()内存地址为100H,del为200H,void (*method)(int,int)可以接受地址传递, opreate(add,10,20)时传入地址100H, method(num1, num2)找到对应的函数,并且传入值进行操作,指向回调。
注:add和&add是同一地址
#include "stdio.h"
void callBackMethod(char * fileName, int current,int total){
printf("图片%s压缩的进度是:%d/%d",fileName,current,total);
}
//定义函数指针 返回值(* 名称)(参数类型,参数类型...)
void compress(char * fileName, void (*callBackP)(char *,int,int)){
callBackP(fileName,5,100);
}
int main() {
//先定义 再赋值
void (* call)(char *,int,int) ;
call = callBackMethod;//相同call = &callBackMethod;
compress("海贼王",call);
compress("derry.png",callBackMethod);
}
定义临时变量,不破坏原本的值,只破坏临时的值
静态开辟内存与动态开辟内存
随机数生成
#include <stdio.h>
#include "stdlib.h"
#include "time.h"
int main() {
//时间单位
srand((unsigned ) time(NULL));
//传入 &t &p可以直接传递 NULL尝试
int i=10;
for (i = 0; i <10 ; ++i) {
printf("随机数%d\n",rand() % 100);
}
return (0);
}
c语言开发也需要看开发文档
字符拷贝
#include <stdio.h>
#include "string.h"
int main2() {
char string[10];
char *str1="asdfghjkz";
strcpy_s(string,2,str1);
printf("%s\n",string);
}
C中的布尔类型非0即1,0是false ,除外的都是true
静态开辟
main()函数执行在栈内,开始执行进栈,执行结束,弹栈
栈区平台大概2M 大于2M会栈溢出,如
#include "stdio.h"
//静态开辟
int main() {
int arr[10*1024*1024]; //10M *4 =40M
return (0);
}
就会发生栈溢出
堆区占用内存最大值大概是windows给编译器分配的空间的80%
#include "stdio.h"
#include <Windows.h>
//进栈
void staticAction() {
int arr[5]; //栈区静态开辟
for (int i = 0; i < 5; ++i) {
arr[i] = i;
printf("%d , %p\n",*(arr+i),arr+i);
}
}
//执行完毕 弹栈
//静态开辟
int main() {
while (1){
Sleep(100);
staticAction();
}
return (0);
}
main函数执行到 staticAction() , staticAction()会进栈,执行结束弹栈释放,因为死循环的原因 staticAction()会一直进栈弹栈
动态开辟
在堆区开辟内存都是动态的范畴
#include "stdlib.h"
#include <Windows.h>
//进栈
void sAction() {
//void * 可以任意转换
int * arr= malloc(1 * 1024 * 1024);
}
int main(){
while (2){
Sleep(100);
sAction();
}
}
使用malloc在堆区动态开辟,栈区回收,堆不会自动回收内存,内存会持续占用
内存会越来越大
释放free(arr);
如果不释放每次开辟的内存地址都不同,释放则会有相同的内存地址,如果释放只会不赋位null则会出现指针悬空
#include "stdlib.h"
#include <Windows.h>
//进栈
void sAction() {
//void * 可以任意转换
int * arr= malloc(1 * 1024 * 1024);
free(arr);
arr=NULL;//指向0x000000
}
int main(){
while (2){
Sleep(100);
sAction();
}
}
动态开辟的使用场景
#include "stdlib.h"
#include "stdio.h"
int main(){
int num;
printf("请输入一个数:");
scanf("%d",&num);
int * arr =(int *)malloc(sizeof(int) * num);
int i=0;
for (; i < num; ++i) {
arr[i] = (i + 1001);
}
printf("开辟的内存指针:%p\n", arr);
int j =0;
for (; j < num; ++j) {
printf("元素的值:%d, 内存地址:%p\n",*(arr+j),(arr+j));
//在堆区开辟新的空间,加长空间大小
//新增
}
int new_num;
printf("请输入一个数:");
scanf("%d",&new_num);
//原来的那块内存大小+新增的大小
int * new_arr =(int *)realloc(arr,sizeof(int) * (num + new_num));
if(new_arr){
i=0;
for (; i < num + new_num; ++i) {
arr[i]=(1001 + i);
}
printf("新开辟的内存指针:%p\n", new_arr);
int k=0;
for (; k < num + new_num; ++k) {
printf("新元素的值:%d, 内存地址:%p\n", *(arr + k), (arr + k));
}
}
if(new_arr){
free(new_arr);
new_arr = NULL;
arr = NULL;
} else{
free(arr);
arr = NULL;
}
return 0;
}
空间复用,第二个数组指针位置还是第一个数组,如果内存地址不同则可能是新的数组开辟空间时被系统占用,从而开辟新的内存地址,若内存不足则返回NULL。最后释放的时候,如果新开辟成功了,则释放新的内存,但是两个指针都指向同一地址,都为悬空,若开辟失败则只释放原始数组即可。
操作字符串
两种方式
int main(){
char str[] ={'H','E','L','L','O'};
str[2] = 'M';
printf("第一种方式%s\n",str); //printf 必须遇到 \0才结束 后边会出现系统值
char * str2 = "HELLO";
str2[2] = 'M';
printf("第二种方式%s",str2);
return 0;
}
结果
第一种方式HEMLO烫烫烫坛D蕳澉╔?I
第二种方式HEMLO
#include "stdio.h"
int main(){
char str[] ={'H','E','L','L','O','\0'};
str[2] = 'M';
printf("第一种方式%s\n",str); //printf 必须遇到 \0才结束 后边会出现系统值
char * str2 = "HELLO";
str2[2] = 'M';
printf("第二种方式%s",str2);
return 0;
}
则正常,第二种是隐式自动加上\0
注意
char * str2 = "HELLO";
str2[2] = 'M';
printf("第二种方式%s",str2);
会造成崩溃,因为str2指向的是一个内存地址,没有权限修改值,而第一种是把全局区域的值copy到了栈区,可以修改,但是高版本的clion自动兼容了第二种写法,但是在语法上是不允许的
指针挪动获取字符串信息
#include "stdio.h"
int getLen(char *string){
int count = 0;
while (*string) {
string++;
count++;
}
return count;
}
int main(){
char string[] = {'A','B','C','D','E','\0'};
int r = getLen(string);
//方式二 int rr = sizeof(string)/ sizeof(int);
printf("长度是%d \n",r);
return 0;
}
数组作为参数传递不能使用
int getLen(char *string1){
int count = 0;
while (*string1) {
string1++;
count++;
}
return sizeof(string1)/ sizeof(char *);
}
返回值会一直是1,把数组作为了一个整体
#include <stdio.h>
void getLen(int * result,int intarr[]){
int count = 0;
//手动计算
while (*intarr){
intarr++;
count++;
}
*result = count;
}
int main(){
int intarr[] = {1,2,3,4,5,6,7,'\0'};
int len= sizeof(intarr) / sizeof(int);
printf("长度是%d",len);
int result; //&取出result遍历的地址给函数
getLen(&result , intarr);
printf("getLen长度是%d",result);
return 0;
}
一般写法函数无返回值,传入一个地址接受最后的结果,然后再拿到这个结果,int数组建议使用sizeof(intarr) / sizeof(int)因为无法区分0和’\0’,有冲突
字符串的比较和转换
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(){
//字符串转换
char *num = "1";
int result = atoi(num);
if(result){
printf("转换成功,%d\n",result);
}
num="123.456";
double result2 = atof(num);
if(result2){
printf("转换成功,%lf\n",result2);
}
//字符串比较
char * str1 = "ABC";
char * str2 = "abc";
// int res = strcmp(str1 , str2); //相等则0 不等则非0 区分大小写
int res = strcmpi(str1 , str2); //相等则0 不等则非0 不区分大小写
if(!res){
printf("相等");
} else {
printf("不相等");
}
}
字符串查找,拼接,包含
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(){
char * test = "Hello World!";
char * tag = "l";
char * pop = strstr(test , tag); //从第二个参数的的第一次出现的位置截取到最后
if(pop){ //非NULL就查找到了
printf("找到了 ,pop的值是%s\n",pop); //找到即是包含
} else {
printf("未找到!");
}
//求取位置
int index = pop - test; // 指针相减
printf("第一次出现的位置是%d\n",index);
//字符拼接
char des[25]; //容器
char * blank = "到", *bj="北京" , *sh = "上海";
strcpy(des,bj); //先copy到数组中
strcat(des, blank); //再拼接数组
strcat(des, sh); //继续拼接
printf("拼接后的结果: %s \n",des);
return 0;
}
大小写转换
#include "stdio.h"
#include "ctype.h"
void change(char *tran,char * name) {
//定义临时变量防止破环指针
char * temp =name;
while (* temp){
*tran = tolower(*temp);
temp++;
tran++; //转换 挪动 赋值
}
*tran = '\0'; //避免打印系统值
}
int main(){
char * name = "ZhangSan";
char tran[20];
change(tran , name);
printf("小写转换后的:%s",tran);
return 0;
}
自定义截取指定位置
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void AtoB(char * res,char * str,int star,int end){
int t = end - star;
while (star--){
str++;
}
while (t--){
*res = *str;
str++;
res++;
}
* res = '\0';
printf("t=%d,star=%d,end=%d\n",t,star,end);
}
//利用堆和栈
void AtoB2(char ** res,char * str,int star,int end){
char *tmp = str;
char rest[end-star];
int count = 0;
for (int i=star; i<end; ++i){
rest[count] = * (tmp +i);
count++;
}
//*res = rest; 防止容器回收 为空
strcpy(*res,rest);//第一种解决方案
//第二种 rest= malloc(end - star); 栈区变成堆区 尽量不用 需要手动回收
}
void AtoB3(char * res,char * str,int star,int end){
for (int i = star; i < end; ++i) {
*(res++) = *(str + i);
}
}
void AtoB4(char * res,char * str,int star,int end){
strncpy(res,str+star,end-star);
}
int main(){
char *str = "ABCDEF";
char * result = (char *)malloc(sizeof(char) * *str);
AtoB(result,str,2,5);
//AtoB2(&result,str,2,5); 传入一级指针地址,二级指针接受,直接给一级指针赋值 但是函数弹栈会回收所有栈成员 包括 rest[end-star]
printf("截取后:%s",result);
}
结构体与结构体指针
写法1
#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include "stdlib.h"
struct Dog{
char name[10];
int age;
char sex;
};//必须写;结束
int main(){
struct Dog dog;//暂未初始化 是系统值 必须写 struct标识
//赋值
strcpy(dog.name,"旺财"); //不可直接赋值
dog.age = 1;
dog.sex = 'G';
printf("name=%s,age=%d,sex=%c",dog.name,dog.age,dog.sex);
}
写法2 初始化的时候直接赋值
#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include "stdlib.h"
struct Person{
char *name;
int age;
char sex;
}
p1 = {"张三",18,'W'},
p2 = {"A",25,'M'},
p3
;
int main(){
printf("name=%s,age=%d,sex=%c",p1.name,p1.age,p1.sex);
};
也可以先初始化实例,后续再赋值
常规嵌套
#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include "stdlib.h"
struct Study{
char * course;
};
struct Student{
char *name;
int age;
char sex;
struct Study study;
struct play{
char * playgame;
}game;
};
int main(){
struct Student st1 = { "张三",18,'m',{"安卓"},{"篮球"}};
printf("name=%s,age=%d,sex=%c,学习=%s,玩=%s",st1.name,st1.age,st1.sex,st1.study.course,st1.game.playgame);
}
结构体指针
#include "stdio.h"
#include "string.h"
struct Cat{
int name[10];
int age;
};
int main(){
struct Cat cat1={"叮当",1};
struct Cat * cap = &cat1;
cap->age = 3; //.是结构体 ->调用一级指针
strcpy(cap->name,"兰兰");
printf("name=%s,age=%d\n",cap->name,cap->age);
printf("name=%s,age=%d\n",cat1.name,cat1.age);
}
使用堆区
#include <stdio.h>
#include "string.h"
#include "stdlib.h"
struct Cat1{
char name[10];
int age;
};
int main() {
struct Cat1 *cat = malloc(sizeof(struct Cat1));
strcpy(cat->name,"金吉拉");
cat->age = 1;
printf("名字%s,年龄%d\n",cat->name,cat->age);
free(cat);
cat = NULL;
return 0;
}
结构体数组
#include <stdio.h>
#include "string.h"
#include "stdlib.h"
struct Cat3{
char name[10];
int age;
};
int main() {
//栈区
struct Cat3 cat [10] = {
{"叮当",1},
{"喵喵",2},
{"猫猫",2},
};
struct Cat3 cat9 = {"啊黄",2};
//cat [9] = cat9;
*(cat + 9) = cat9;
printf("name%s,age%d\n",cat9.name,cat9.age);
//堆区 动态开辟
struct Cat3 *cat2 = malloc(sizeof(struct Cat3) * 10);
strcpy(cat2->name,"大橘");
cat2->age = 5;
printf("name%s,age%d\n",cat2->name,cat2->age);
//给第八个元素赋值
cat2 += 7;
strcpy(cat2->name,"小黑");
cat2->age = 3;
printf("name%s,age%d\n",cat2->name,cat2->age);
free(cat2);
cat2 = NULL;
return 0;
}
结构体别名 解决兼容性问题
#include "stdio.h"
#include "stdlib.h"
struct DAO {
char name[10];
int age;
char sex;
};
typedef struct DAO DAO;
typedef DAO * DAO_;
int main(){
DAO_ *dao = malloc(sizeof(DAO));
}
使用typedef起别完别名后 不需要引用的时候加struct关键字,就实现了不同平台代码一致
进阶
#include "stdio.h"
#include "stdlib.h"
//匿名结构体的别名 源码
//给结构体AV取别名AV
typedef struct {
char name[10];
int age;
char sex;
} AV;
int main(){
AV av = {
};
AV *pav = malloc(sizeof(AV));
}
枚举
#include "stdio.h"
typedef enum{
TEXT = 10,
TEXT_IMAGE,
IMAGE
} CommenType;
int main(){
//Clion写法
// enum CommenType commenType = TEXT;
//VS写法
// CommenType commenType = TEXT;
CommenType commenType = TEXT;
CommenType commenType2 = TEXT_IMAGE;
CommenType commenType3 = IMAGE;
printf("%d,%d,%d \n" , commenType , commenType2 , commenType3);
}
游戏破解与文件加解密
对于C拿到内存地址即可修改一切,最难的是地址的寻找
文件读写操作
读取
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(){
//参数1 文件路径 ,参数2 模式 r读 w写 rb二进制文件读 wb二进制文件写
// 返回值是结构体
//fopen();
char * fileNameStr = "D:\\aaa.txt";
FILE * file= fopen(fileNameStr,"r");
if(!file){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
//定义缓冲区
char buff[1024];
//缓冲区buff 长度 文件指针变量
while (fgets(buff, 1024, file)){
printf("%s",buff);
}
//关闭文件
fclose(file);
}
写入
#include <stdlib.h>
#include "stdio.h"
int main(){
char * fileNameStr = "D:\\aaa.txt";
//不存在会自动生成文件 无需判断
FILE * file= fopen(fileNameStr,"w");
if(!file){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
fputs("This is C code",file);
fclose(file);
return 0;
}
文件复制
#include <stdlib.h>
#include "stdio.h"
// 二进制文件复制
int main(){
char * fileNameStr = "D:\\aaa.txt"; //来源
char * fileNameCopy = "D:\\acopy.txt"; //目标
//读取二进制数据
FILE * file= fopen(fileNameStr,"rb");
FILE * file2= fopen(fileNameCopy,"wb");
if(!file || !file2){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
int buffer[512];
int len; //每次接收长度
//参数1 容器buff 参数2 每次偏移多少 参数3 容器大小 参数4文件指针
while ((len = fread(buffer,sizeof(int), sizeof(buffer)/sizeof (int),file))!=0){
fwrite(buffer,sizeof(int),len,file2);
}
fclose(file);
fclose(file2);
}
文件大小获取
没有专门的API 用获取头指针,挪动位置,挪动到最后即可求得文件大小
#include <stdlib.h>
#include "stdio.h"
// 二进制文件复制
int main() {
char *fileNameStr = "D:\\aaa.txt"; //来源
FILE * file= fopen(fileNameStr,"rb");
if(!file ){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
//SEEK_SET(开头) SEEK_CUR(当前) SEEK_END(结尾)
fseek(file, 0, SEEK_END);//文件指针,起始点 结尾
//执行后file有了更丰富的值
//读取刚刚给file赋值的信息
long file_seze= ftell(file);
fclose(file);
printf("%s文件的字节大小是:%ld",fileNameStr,file_seze);
}
文件加解密
加密
#include <stdlib.h>
#include "stdio.h"
// 二进制文件复制
int main() {
char *fileNameStr = "D:\\tx.jpg"; //来源
char *fileNameStrEncode = "D:\\tx_encode.jpg"; //加密的目标
FILE * file= fopen(fileNameStr,"rb");
FILE * fileEncode= fopen(fileNameStrEncode,"wb");
if(!file || !fileNameStrEncode){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
//加密==破坏文件 解密==还原文件
//加密 :把每个字节都拿出来 对一个字节都处理(全部加密)。(处理部分内容)
//TODO 加密
//while 每个字节取出来 10
//10^异或5
//TODO 解密
//while 再 异或5还原
int c; //接收读取的值
//fgetc 返回值 EOF=-1 结束
while ((c = fgetc(file)) != EOF) {
//加密
fputc(c^5,fileEncode);
}
fclose(file);
fclose(fileEncode);
return 0;
}
解密
#include <stdlib.h>
#include "stdio.h"
// 二进制文件复制
int main() {
char *fileNameStrEncode = "D:\\tx_encode.jpg"; //解密的目标
char *fileNameStr = "D:\\tx_encode_sol.jpg"; //解密后
FILE * file= fopen(fileNameStrEncode,"rb");
FILE * fileEncode= fopen(fileNameStr,"wb");
if(!file || !fileEncode){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
//加密==破坏文件 解密==还原文件
//加密 :把每个字节都拿出来 对一个字节都处理(全部加密)。(处理部分内容)
//TODO 加密
//while 每个字节取出来 10
//10^异或5
//TODO 解密
//while 再 异或5还原
int c; //接收读取的值
//fgetc 返回值 EOF=-1 结束
while ((c = fgetc(file)) != EOF) {
//加密
fputc(c^5,fileEncode);
}
fclose(file);
fclose(fileEncode);
return 0;
}
使用密钥
加密
#include <stdlib.h>
#include "stdio.h"
#include "string.h"
// 使用
int main() {
char *fileNameStr = "D:\\tx.jpg"; //来源
char *fileNameStrEncode = "D:\\tx_encode.jpg"; //加密的目标
FILE * file= fopen(fileNameStr,"rb");
FILE * fileEncode= fopen(fileNameStrEncode,"wb");
if(!file || !fileEncode){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
// 密钥
char * password = "123456";
int c;
int index = 0;
int pass_len = strlen(password);
while ((c = fgetc(file) != EOF)){
char item = password[index % pass_len];
printf("intm:%c\n",item);
fputc(c ^ item,fileEncode);
index ++;
}
fclose(file);
fclose(fileEncode);
}
解密
#include <stdlib.h>
#include "stdio.h"
#include "string.h"
// 使用
int main() {
char *fileNameStr = "D:\\tx_encode.jpg"; //加密的来源
char *fileNameStrEncode = "D:\\tx_encode_cx.jpg"; //解密
FILE * file= fopen(fileNameStr,"rb");
FILE * fileEncode= fopen(fileNameStrEncode,"wb");
if(!file || !fileEncode){
printf("文件打开失败,请检测文件路径%s\n",fileNameStr);
exit(0);
}
// 密钥
char * password = "123456";
int c;
int index = 0;
int pass_len = strlen(password);
while ((c = fgetc(file) != EOF)){
fputc(c ^ password[index%pass_len],fileEncode);
index ++;
}
fclose(file);
fclose(fileEncode);
}