C语言进阶要点笔记3


目录

  • 四、指针

13、指针作为函数的返回值
14、指针保存函数的地址
15、易混淆的指针
16、特殊指针
17、main函数传参

  • 五、字符串处理 #include <string.h>

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<stdio.h>

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 <stdio.h>
int main(int argc, char *argv[]) // 变量个数   对应数组指针
{
    int i;
    printf("argc=%d\n",argc);
    for(i=0;i<argc;i++)
    {
        printf("argv[%d]=%s\n",i,argv[i]);
    } 
    return 0;
}

  • 五、字符串处理 #include <string.h>

1、strlen函数:测量字符指针指向的字符串中的字符的个数,不包括‘\0’

sizeof 是个关键字, 测量数据的占用内存空间大小

如果测量的是数组的名字, 则测的是数组占多少个字节,数组的容量

如果 sizeof 测的是指针变量, 则测的是指针变量本身占几个字节, 32 平台下结果为 4

#include <stdio.h>
#include <string.h>
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<string.h>
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<i;j++)
    {
        printf("q[%d]: %s\n",j,q[j]);
    } 
    printf("str=%p\n",str);
    printf("q[0]=%p\n",q[0]);
}

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<stdio.h>
int main()
{
    char buf[20];
    sscanf("12345678","%4s ",buf);//从字符串中获取字符串, 只要 4 个字节, 存放在 buf 中
    printf("%s\n",buf);
}

    可以读取指定长度的整数;也可以配合跳过数据使用

#include<stdio.h>
int main()
{
    int num;
    sscanf("12345678","%*3d%3d ",num);//从字符串中获取整数,先跳过3个数字再取3个数字组成一个整数
    printf("%d\n",num);
}

c、支持集合操作: 只支持获取字符串   可以配合跳过数据使用  一旦条件不满足就结束 

     %[a-z] 表示匹配 a 到 z 中任意字符(尽可能多的匹配)

#include<stdio.h>
#include<string.h>
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<stdio.h>
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 去修改

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值