strtok
char * strtok ( char * str , const char * sep );
sep参数是个字符串,定义了作分隔符的字符合集。
第一个参数指定一个字符串,他包含了0个或者多个由sep字符中一个或者多个分隔符的标记。
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "zpengwei@yeah.net";
char buf[30] = {0};
strcpy(buf,arr);
const char *sep ="@.";
strtok(buff,sep);
//只找第一个标记。
strtok(NULL,sep);
//从保存好的位置继续找。
printf("%s\n", strtok(buf, sep));//只找第一个标记
printf("%s\n", strtok(NULL, sep));//是从保存的好的位置开始继续往后找
printf("%s\n", strtok(NULL, sep));//是从保存的好的位置开始继续往后找
return 0;
}
//strtok函数找到str中的下一个标记,并用‘\0’做结尾,返回一个指向这个标记的指针。
//在上面的代码就会把@替换成\0,然后返回最开始的地址也就是z的地址。
//strtok函数会改变被操纵的字符串,使用一般使用一个临时拷贝内容去操作而不是源内容。(buf的创建。)
//第一个参数,也就是现在的buf不为空指针的时候,会找到str的第一个标记,也就是@,改成\0后返回z。并记住@所在地址。
//第一个参数为空指针时
int main()
{
char arr[] = "zpengwei@yeah.net.hehe@haha nihao";
char buf[50] = { 0 }
strcpy(buf, arr);
const char* sep = "@. ";
char* str = null;
for (str=strtok(buf, sep); str!=null; str=strtok(null, sep))
//赋值判断在操作。
{
printf("%s\n", str);
}
return 0;
}
//上面代码的另类写法。
strerror
char * strerror ( int errnum );
返回错误码锁定的错误信息。
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
//可以直接打印错误码信息。
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(INT_MAX);//想堆区申请内存的
if (p == NULL)
{
printf("%s\n", strerror(errno));
//如果内存申请失败,返回错误信息。
//perror("Malloc"); 这个函数也会打印错误信息,打印格式为双引号之间的内容
//加冒号也就是"Malloc":(错误信息),但是strerror没有,只有错误信息。
return 1;
}
return 0;
}
字符分类函数简介
//如果参数符合以下就返回真。不是就返回假。
iscntrl 任何控制字符
isspace 空白字符:空格'',换页'\f',换行'\n',回车'\r',制表符'\t',垂直制表符'\v'
isdigit 十进制数字0-9
isxdigit 十六进制数字,包括所以十进制数字,小写字母a-f,大写字母A-F
islower 小写字母a-z
isupper 大写字母A-Z
isalpha 字母a-z或者A-z
isalnum 数字或者字母,a-z,A-Z,0-9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符
大小写转换:
int main()
{
char ch = 'A';
putchar(toupper(ch));//转大写。
putchar(tolower(ch));//转小写。
return 0;
}
内存操作函数
memcpy
void *memcpy(void * dest, const void * src, size_t count);
//一个目标,一个源,一个拷贝字节大小。
//void*是为了适应各种类型,因此需要进行强制转换。
模拟实现
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
char arr1[] = "1234abcd ";
char arr2[32];
my_memcpy(arr2, arr1, strlen(arr1) + 1);
printf("arr2数组元素为:%s\n", arr2);
return 0;
}
memmove
void *memmove( void *dest, const void *src, size_t count );
可以实现重叠内存的拷贝。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
void* my_memmove(void* dest, const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
//1
if (dest < src)
{
while (count--)
{
*(char*)dest = *(char*)(src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
//2
if (dest > src && dest < ((char*)src + count))
{
//后->前
}
else
{
//前->后
}
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 20);
int i = 0;
int sz = sizeof(arr1) / sizeof(arr1[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
模拟实现
void* my_memmove(void* dest, const void*src, size_t count)
{
assert(dest && src);
void* ret = dest;
//1
if (dest < src)
{
//前->后
while (count--)
{
*(char*)dest = *(char*)(src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后->前
while (count--)
{
*((char*)dest+count) = *((char*)src + count);
}
}
return ret;
//2
if (dest > src && dest < ((char*)src + count))
{
//后->前
}
else
{
//前->后
}
}
memcmp
int memcmp ( const void * ptr1.
const void * ptr2,
size_t num );
比较从ptr1和ptr2指针开始的num个字节。
大于是返回>1的数字。
等于则返回0。
小于是返回<1的数字。
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,3,4,0x11223305 };
int ret = memcmp(arr1, arr2, 18);
//比较第18个字节
printf("%d\n", ret);
return 0;
}
memset
void *memset( void *dest, int c, size_t count );
int main()
{
int arr[] = { 0x11111111,0x22222222,3,4,5 };
memset(arr, 6, 20);//memset是以字节为单位来初始化内存单元的,6是想设置成的数字,20是字节单位。
return 0;
}
匿名结构体
struct
{
char name[20];
char id[12];
}ss;
struct
{
char name[20];
char id[12];
}*ps;
int main()
{
ps = &ss;
struct Book b1;
struct Stu s2, s3;
return 0;
}
//匿名结构体如果成员用于,在编译器看来也是不同的两个类型结构体。
typedef 类型重命名。
typedef struct Node
{
int data;//数据
struct Node* next;//指针
} Node ,*pNode;
//这样不用谢struct Node直接写Node就行了。
struct Node* pNode
结构体嵌套
struct Book
{
char name[20];
float price;
char id[12];
}s = {"汪汪汪", 55.5f, "PGC001"};
struct Node
{
struct Book b;
struct Node* next;
};
int main()
{
struct Book s2 = { "嗡嗡嗡", 66.6f, "HG001" };
struct Node n = { {"哇哇哇", 66.8, "TG001"}, NULL};
return 0;
}