目录
13、指针作为函数的返回值
14、指针保存函数的地址
15、易混淆的指针
16、特殊指针
17、main函数传参
1、strlen函数
2、字符串拷贝函数
3、字符串追加函数
4、字符串比较函数
5、字符查找函数
6、字符串匹配函数
7、字符转数字
8、字符串切割函数
9、格式化字符串操作函数
10、sscanf的高级用法
11、const关键字
13、指针作为函数的返回值
返回指针的被调函数,函数名前需要加上*;返回的指针不能是局部变量的指针,局部变量内存会被释放,如需返回局部需加static
但是可以返回文字常量区的指针,文字常量区的内存不会被释放 *p = "hello world"
返回堆区的地址
char * fun()
{
char *str;
str = (char *)malloc(100);
strcpy(str,"hello world");
return str;
}
int main()
{
char *p;
p = fun();
printf("%s\n",p);//hello world
free(p);
}
原因是堆区的内容一直存在, 直到 free 才释放。
14、指针保存函数的地址
函数指针变量用来存放函数的地址,C语言规定函数名就是函数的首地址
函数指针变量的定义方法:返回追类型 (*函数指针变量名)(形参列表);
int (*p)(int, int);//定义了一个函数指针变量p,p指向的函数必须由一个整形返回值,有两个整形参数
调用函数的方法:
a:通过函数名直接调用(最常用)
b:通过函数指针变量调用
int max(int x,int y)
{ }
int main()
{
int num;
int (*p)(int ,int);
p=max;
num=(*p)(3,5);
}
函数指针数组:int(*p[10])(int,int);
定义了一个函数指针数组, 有 10 个元素 p[0] ~p[9], 每个元素都是函数指针变量,
指向的函数, 必须有整型的返回值, 两个整型参数。
#include
int add(int x,int y)
{
return x+y;
}
int sub(int x,int y)
{
return x-y;
}
int mux(int x,int y)
{
return x*y;
}
int dive(int x,int y)
{
return x/y;
}
int process(int (*p)(int ,int),int a,int b)
{
int ret;
ret = (*p)(a,b);
return ret;
}
int main()
{
int num;
num = process(add,2,3);
printf("num =%d\n",num);
num = process(sub,2,3);
printf("num =%d\n",num);
num = process(mux,2,3);
printf("num =%d\n",num);
num = process(dive,2,3);
printf("num =%d\n",num);
return 0;
}
15、易混淆的指针
第一组:a:int *a[10]; 这是个指针数组, 数组 a 中有 10 个整型的指针变量a[0]~a[9]
b:int (*a)[10]; 数组指针变量, 它是个指针变量。 它占 4 个字节, 存地址编号。
c:int **p; 这个是个指针的指针, 保存指针变量的地址。常用在保存指针的地址
第二组:a:int *f(void); *f 没有用括号括起来 它是个函数的声明, 声明的这个函数返回值为 int *类型的。
b:int (*f)(void); *f 用括号括起来了 必须有一个 int 型的返回值, 没有参数。
16、特殊指针
void * 通用指针,任何类型的指针都可以给void *类型的指针赋值,不需要强制类型转换
NULL 空指针,常用来给指针初始化
17、main函数传参
#include
int main(int argc, char *argv[]) // 变量个数 对应数组指针
{
int i;
printf("argc=%d\n",argc);
for(i=0;i
1、strlen函数:测量字符指针指向的字符串中的字符的个数,不包括‘\0’
sizeof 是个关键字, 测量数据的占用内存空间大小
如果测量的是数组的名字, 则测的是数组占多少个字节,数组的容量
如果 sizeof 测的是指针变量, 则测的是指针变量本身占几个字节, 32 平台下结果为 4
#include
#include
int main()
{
char str1[20]="hello";
char *str2 ="hello";
printf("%d\n",sizeof(str1)); //20
printf("%d\n",sizeof(str2));//4
printf("%d\n",strlen(str1));//5
printf("%d\n",strlen(str2));//5
return 0;
}
2、字符串拷贝函数 返回目的内存首地址
char *strcpy(char *dest, const char *src);
拷贝 src 指向的字符串到 dest 指针指向的内存中, ’\0’也会拷贝 必须保证 dest 指向的内存空间足够大, 否则会出现内存污染。
char *strncpy(char *dest, const char *src, size_t n);
将 src 指向的字符串前 n 个字节, 拷贝到 dest 指向的内存中;不拷贝 ‘\0’,
如果 n 大于 src 指向的字符串中的字符个数, 则在 dest 后面填充 n-strlen(src)个 ’\0
目的数组如果原本有字符,则只将前n个字符覆盖,剩下的不变
3、字符串追加函数 返回目的内存首地址
char *strcat(char *dest, const char *src);
追加 src 字符串到 dest 指向的字符串的后面。 追加的时候会追加’\0’;dest 指向的内存空间要足够大;从\0后开始追加
char *strncat(char *dest, const char *src, size_t n);
追加 src 指向的字符串的前 n 个字符, 到 dest 指向的字符串的后面。 追加的时候会追加’\0’;
4、字符串比较函数
int strcmp(const char *s1, const char *s2);
比较 s1 和 s2 指向的字符串的大小,逐个字符去比较 ascII 码, 一旦比较出大小返回。
如果 s1 指向的字符串大于 s2 指向的字符串 返回 1
如果 s1 指向的字符串小于 s2 指向的字符串 返回-1
如果相等的话返回 0
int strncmp(const char *s1, const char *s2, size_t n);
比较 s1 和 s2 指向的字符串中的前 n 个字符
5、字符查找函数
char *strchr(const char *s, int c); // 首次匹配
在字符指针 s 指向的字符串中, 找 ascii 码为 c 的字符
首次匹配, 如果过说 s 指向的字符串中有多个 ASCII 为 c 的字符, 则找的是第 1 个字符
找到了返回找到的字符的地址,找不到返回 NULL
char *strrchr(const char *s, int c); // 末次匹配
在 s 指向的字符串中, 找最后一次出现的 ASCII 为 c 的字符
6、字符串匹配函数
char *strstr(const char *haystack, const char *needle);
在 haystack 指向的字符串中查找 needle 指向的字符串, 也是首次匹配
找到了: 找到的字符串的首地址 两个指针相减可以得到所查找字符串在数组中的位置
7、字符转数字
atoi/atol/atof //字符串转换功能
int atoi(const char *nptr); 将 nptr 指向的字符串转换成整数
long atol(const char *nptr); 长整形
double atof(const char *nptr); 浮点型
8、字符串切割函数(这函数有点牛B)
char *strtok(char *str, const char *delim);
在str指向的字符串中只要出现了delim指向的字符串中的任意字符,则将该字符变成‘\0’;
调用一次该函数只进行一次切割;从第二次切割开始第一个参数传NULL(此函数会记住切割位置)
str 字符串中出现了连续的几个 delim 中的字符, 则只将第一个字符变成’\0’
#include
int main()
{
char str[100]="小明:21,,,.男.女,北京:haidian";
char *p=":,.";
char *q[7];
int i=0,j;
q[i]=strtok(str,p);
while(q[i]!=NULL)
{
i++;
q[i]=strtok(NULL,p);
}
for(j=0;j
9、格式化字符串操作函数
int sprintf(char *buf, const char *format, …); \\输出到 buf 指定的内存区域。输出目的地由屏幕变为buf指向的内存
char buf[20];
sprintf(buf,"%d:%d:%d",2013,10,1);
printf(“buf=%s\n”,buf);
int sscanf(const char *buf,const char *format, …); \\从 buf 指定的内存区域中读入信息
int a, b, c;
sscanf("2013:10:1", "%d:%d:%d", &a, &b, &c);
printf(“%d %d %d\n”,a,b,c);
10、sscanf的高级用法(相当于Python的正则表达式)
a、跳过数据: %*s 或%*d //加*相当于跳过
sscanf("1234 5678", "%*d %s", buf);//跳过 1234 ,然后隔一个空格获取字符串
b、读指定宽度的数据: %[width]s
#include
int main()
{
char buf[20];
sscanf("12345678","%4s ",buf);//从字符串中获取字符串, 只要 4 个字节, 存放在 buf 中
printf("%s\n",buf);
}
可以读取指定长度的整数;也可以配合跳过数据使用
#include
int main()
{
int num;
sscanf("12345678","%*3d%3d ",num);//从字符串中获取整数,先跳过3个数字再取3个数字组成一个整数
printf("%d\n",num);
}
c、支持集合操作: 只支持获取字符串 可以配合跳过数据使用 一旦条件不满足就结束
%[a-z] 表示匹配 a 到 z 中任意字符(尽可能多的匹配)
#include
#include
int main()
{
char buf[20];
sscanf("agcd32DajfDdFF","%[a-z]",buf);//从字符串中获取输入只要’ a’ 和’ z’
//之间的字符, 碰到不在范围内的, 就终止了
printf("%s\n",buf);//结果为 agcd
}
%[aBc] 匹配 a、 B、 c 中一员, 贪婪性
%[^aFc] 匹配非 a Fc 的任意字符, 贪婪性
%[^a-z]表示读取除 a-z 以外的所有字符
使用 sscanf 两个#号之间的字符串 abc#def@ghi
#include
int main()
{
char buf[20];
sscanf("asdf#sdjd@djfkd","%*[^#]%*c%[^@]",buf);
printf("%s\n",buf);
}
11、const关键字
a、修饰普通变量, 代表只读的意思
const int a=100;//定义了一个只读变量 a 值为 100 以后在程序中, 不能再给 a 赋值了
b、const 修饰指针
const char *str 意思是 str 指向的内存的内容不能通过 str 来修改 用来保护 str 指向的内存的内容
但是 str 的指向是可以改变的
char * const str 意思是 str 是只读的变量, str 不能指向别的地方,
但是 str 指向的内存的内容, 是有可能可以修改的
const char * const str str 不能指向别的地方, 指向的内存的内容也不能通过 str 去修改