perror
#include <stdio.h>
#include <errno.h>
#include <string.h>
//strerror
//perror与上相关 更加方便直接打印错误信息 上边需要先将错误码转换为错误信息 再用printf打印
//
int main()
{
//打开文件失败的时候,会返回NULL
FILE* pf = fopen("test.txt", "r");
//0 "no error"
if (pf == NULL)
{
//printf("%s\n", strerror(errno)); strerror他会把错误码所对应的错误信息的首字符地址返回来。%s打印可以打印出一个字符串
perror("fopen");//这个括号里是自定义信息 想加什么加什么 会在错误信息前显示
return 1;
}
//读文件
//
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
字符分类函数
int main()
{
char ch = 'a';
//isdigit 如果是数字字符返回非0的值,如果不是数字字符,返回0
if (ch >= 'A' && ch <= 'Z')
{
}
//int ret = isdigit(ch);
//int ret = islower(ch);
//printf("%d\n", ret);
return 0;
}
是想要的就返回非0 不是想要的就返回0
tolower转小写 toupper转大写
int main()
{
char arr[20] = { 0 };
scanf("%s", arr);
int i = 0;
while (arr[i] != '\0')
{
if (isupper(arr[i]))
{
arr[i] = tolower(arr[i]);//转化为小写在放到原位置
}
printf("%c ", arr[i]);
i++;
}
return 0;
}
内存函数
*void memcpy( void dest, const void src, size_t count );
size表示要拷贝多大空间 单位是字节
** memcpy 内存块拷贝函数
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
//01 00 00 00 02 00 00 00 ...
int arr2[20] = { 0 };
//strcpy()
//char* strcpy(char* dest, const char* src)
return 0;
}
如上代码 我们之前所学的字符串拷贝函数肯定是不行的
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20); //把arr1前5个内容拷贝到arr1 因为拷贝单位是字节 一个整型4个字节
return 0;
}
my_memcpy
#include <assert.h>
void* my_memcpy(void* dest, const void*src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)//总共要拷贝的字节数 循环四次 每次搞定四个字节
{
*(char*)dest = *(char*)src;//强制类型转换意思是void不能直接解引用
dest = (char*)dest + 1;//拷贝完一次后往后走
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
return 0;
}
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; 接下来想把12345 放到34567这块空间 源头从1 目的地3开始
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
// 1 2 1 2 3 4 5 8 9 10 应该出现的样子
//my_memmove(arr1+2, arr1, 20);
//memmove(arr1, arr1+2, 20);
memmove(arr1+2, arr1, 20); //加0指向1 加1指向2加2指向3
//memcpy函数应该拷贝不重叠的内存
//memmove函数可以处理内存重叠的情况
return 0;
}
模拟实现 my_memove
void* my_memmove(void* dest, const void*src, size_t num)
{
void* ret = dest;
assert(dest && src);
if (dest < src)
{
//前->后
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后->前
while (num--)
{
//20先进来 减减效果产生来到这已经变成19
*((char*)dest + num) = *((char*)src + num);//从后向前 必须要源头和目标的都是从后开始
}
}
return ret;
}
//可以把元数据 从前向后拷贝 也可以从后向前拷贝
//从低地址往高地址拷贝时, 先拷贝高地址, 再拷贝低地址
//从高地址往低地址拷贝时, 先拷贝低地址, 再拷贝高地址
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
// 1 2 1 2 3 4 5 8 9 10 应该出现的样子
//my_memmove(arr1+2, arr1, 20);
//memmove(arr1, arr1+2, 20);
my_memmove(arr1+2, arr1, 20); //加0指向1 加1指向2加2指向3
//memcpy函数应该拷贝不重叠的内存
//memmove函数可以处理内存重叠的情况
return 0;
}
memcmp (内存比较)
int main()
{
float arr1[] = { 1.0, 2.0,3.0,4.0 };
float arr2[] = { 1.0, 3.0 };
int ret = memcmp(arr1, arr2, 8); //-1 相同返回值0 如果第一个字符串大于第二个返回1 如果第一个小于第二个返回(小于0的)-1
//memcmp - strcmp
printf("%d\n", ret);
return 0;
}
memset
把ptr所指向的那块空间的前num个字节的内容设置成我指定的value值
int main()
{
//40
int arr[10] = { 0 };//20
memset(arr, 1, 20);//以字节为单位设置内存的
//01 00 00 00 这是1
//01 01 01 01 这肯定不是
return 0;
}
自定义类型
结构体声明(结构体是定义一个复杂对象)
struct Book //关键字和标签名
{
char name[20]; //描述所需要的属性
int price;
char id[12];
}b4,b5,b6;//b4,b5,b6是全局的
上面类型如何使用 类型是用来创建变量
int main()
{
//b1,b2,b3是局部变量
struct Book b1;
struct Book b2;
struct Book b3;
类似于 int b1
return 0;
}
圈起来的作用相同 但是作用域不同 局部和全局
特殊声明
匿名结构体类型 用这个类型创建了个变量叫s 这个类型创建好后只能用一次 后面就不能再创建
struct
{
char c;
int i;
char ch;
double d;
} s;
struct
{
char c;
int i;
char ch;
double d;
} s;
struct
{
char c;
int i;
char ch;
double d;
}* ps;
int main()
{
ps = &s;
return 0;
}
编译器认为这是错的
结构体自引用
结构体可以包含结构体
struct A
{
int i;
char c;
};
struct B
{
char c;
struct A sa;
double d;
};
但是结构体里不能包含自己
//struct N
//{
// int d;//4
// struct N n;
//}
//int main()
//{
// struct N sn;//
//
// return 0;
//}
什么叫结构体自引用如下
struct Node //我自己能找到跟自己同类型的下一个元素
{
int data;
struct Node* next;
};
结构体变量的定义和初始化
struct S
{
char c;
int i;
}s1, s2;
struct B
{
double d;
struct S s;
char c;
};
int main()
{
//struct S s3 = {'x', 20};
struct B sb = { 3.14, {'w', 100},'q' };
//. 变量
//-> 指针
printf("%lf %c %d %c\n", sb.d, sb.s.c, sb.s.i, sb.c);
return 0;
}
结构体内存对齐
结构体占多大内存空间
struct S
{
int i;//4
char c;//1
};
struct S2
{
char c1;//1
int i;//4
char c2;//1
};
//结构体内存对齐
int main()
{
struct S s = {0};
printf("%d\n", sizeof(s));//8
struct S2 s2 = { 0 };
printf("%d\n", sizeof(s2));//12
return 0;
}
下篇讲解