七、指针:字符串处理函数:strlen、strcpy、strncpy、strcat、strncat、strcmp、strncmp、sprintf、sscanf、strchr、strstr、strtok、atoi、atof、atol
指针基础知识

指针和指针变量;指针变量的定义与使用;指针的大小; ========================================================================================================== 指针和指针变量 内存区的每一个字节都有一个编号,这就是“地址”。 如果在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并确定它的内存地址(编号) 指针的实质就是内存“地址”。指针就是地址,地址就是指针。 指针是内存单元的编号,指针变量是存放地址的变量。 通常我们叙述时会把指针变量简称为指针,实际他们含义并不一样。 口语上的指针实际上是指针变量 ---------------------------------------------------------------------------------------------------------- //指针变量的定义与使用;指针的大小 int main() { // 指针也是一种数据类型,指针变量也是一种变量 //指针变量指向谁,就把谁的地址赋值给指针变量 //“*”操作符操作的是指针变量指向的内存空间 //我的理解:指针是特殊的变量 // 普通的变量储存的是内容;而指针储存的是地址 // 指针如果是在左边,那么就是用来进行指针指向地址的内容修改,即修改对应的普通变量的内容 // 指针如果是在右边,那么就是用来取值,取出指针指向地址的内容,即取出普通变量的内容 // //int * p //这里的*表示类型描述符,这里是一个指针 //*p : 将p变量的内容取出,当成地址看待,找到该地址对应的内存空间。 // //*p 如果做左值: 存数据到空间中。---存数据 //*p 如果做右值: 取出空间中的内容。---取数据 int a = 10; int* p = &a; //*p = 2000; a = 2000; //效果等同于 "*p = 2000;" printf("%d\n", a); //2000 变量a的内容 printf("%p\n", &a); //000000F7E12FF784 变量a的内存地址 printf("%p\n", p); //000000F7E12FF784 变量a的内存地址,很好理解,因为指针的内容就是普通变量的地址嘛 printf("%p\n", &p); //000000D2A1CFF818 变量p的内存地址,这个是指针变量的地址,当然与普通变量的地址是不同的 printf("%p\n", *p); //00000000000007D0 7D0十六进制,即2000,此处做右值,去除空间的内容 printf("%d\n", *p); //2000 7D0十六进制,即2000,此处做右值,去除空间的内容 //指针的大小与数据类型无关,只与平台的架构有关;32位系统即4字节;64位系统即8字节 //很正常,可以理解,指针就是一种特殊的变量嘛,存的是地址,自然不需要不同的大小 printf("%u\n", sizeof(int *)); //打印出来全是8; printf("%u\n", sizeof(short *)); printf("%u\n", sizeof(char *)); printf("%u\n", sizeof(long *)); printf("%u\n", sizeof(double *)); printf("%u\n", sizeof(void *)); // *p 就是指针的解引用、间接引用;我的理解就是根据纯粹的地址数据找到了地址空间 }

野指针;空指针;万能指针(泛型指针) ========================================================================================================== 指针变量也是变量,是变量就可以任意赋值,不要越界即可(32位为4字节,64位为8字节),但是,任意数值赋值给指针变量没有意义, 因为这样的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此指针指向的内存区域)。 所以,野指针不会直接引发错误,操作野指针指向的内存区域才会出问题。 //【野指针一定要杜绝】 //【空指针要进行强制类型转换后,才能使用】 int main() { //野指针 int* p1; //野指针1 //野指针是肯定需要避免的,因为定义了野指针,却不指定指针的内容,那么意味着指针内容可能是随机数。 //假设这个随机地址指定到了另一个数据的空间,那不就修改了其他数据了。。这种情况肯定是不能被允许的! *p1 = 2000; printf("%d\n",*p1); int* p2 = 10; //野指针2 //因为0-255这个地址段是要留给操作系统使用的,此处给的地址10是非法地址 //所以直接给指针赋值,这种方式也是非法的;你怎么知道你不会指到关键数据上呢。。 //我的猜测:指到关键数据碰到的问题不一定就是修改了关键数据;也可能是非法访问,不被允许,总之就是有问题。。 *p2 = 2000; printf("%d\n", *p1); //正确的使用方式 int m; int* p3; p3 = &m; //int* p3 = &m; //空指针 int* p4 = NULL; //#define NULL ((void *)0); 是一个指向0地址的万能指针 //...一系列操作之后 if (p4 != NULL) { //确定指针地址是有效的,再执行操作 *p4 = 300; printf("%d", *p4); } } ---------------------------------------------------------------------------------------------------------- 万能指针(泛型指针) int main() { //万能指针(泛型指针) void* p; int a = 123; p = &a; //使用万能指针前,需要先强制转换指针类型 printf("%d\n",*((int *)p)); //显示正常,打印123 //printf("%d\n",*p); //错误用法,不允许使用不完整的类型 //普通变量的强制转换 (int)aaa //指针的强制转换 (int *)aaa }

const修饰的指针变量; ========================================================================================================== const修饰的指针变量 int main() { //const 修饰变量 const int a = 100; printf("%d\n", a); //100 //a = 200; //只读变量,不能修改 int* p = &a; *p = 200; printf("%d %d\n", a,*p); //200 200;只读变量虽然不能直接修改,但是可以通过指针来间接修改 //const 修饰指针 const int* p1; int const* p2; int* const p3; const int* const p4; int aa = 50; p1 = &aa; //这种方式可以修改;"*p1 = 500;"这种方式不能修改 p2 = &aa; //同上, "*p1 = 500;"会报错 *p3 = 500; //这里的现象不同了,"p3 = &aa;"这种形式会报错; //p4,两种方式都不能修改。 //结论:const向右进行修饰,被修饰则无法修改,变成只读 //p1p2锁的是指针指向的内存空间,即造成指向的变量不能修改,即 *p 无法修改; //p3锁的是指针变量的内容,但是指向的内存空间,即指向的变量并没有被锁定,可以修改。 //p是指针变量本身,储存的只是内存地址这种数据;*p则是指相应的内存空间,相当于是变量了。。 //int fputs(const char * str, FILE * stream); //以上为常用方式,const用在函数形参中,限制指针所指向的内存空间变为只读。 //此处添加了const是为了函数的健壮性: } ------------------------------------------------------------------------------ int main() { // const 测试 int a1 = 1; int a2 = 2; int a3 = 3; const int* p1 = &a1; int const* p2 = &a2; int* const p3 = &a3; printf("%d\n", a1); //打印1 printf("%d\n", *p1); //打印1 a1 = 100; printf("%d\n", a1); //打印100 printf("%d\n", *p1); //打印100 //*p1 = 1000; 指针变量的解引用被锁,无法修改 p1 = &a2; printf("%d\n", a1); //打印100 printf("%d\n", *p1); //打印2 指针变量内容被修改为a2的地址,解引用后取出a2的数据 printf("++++++++++++++++++++++++++++++++++++++++\n"); printf("%d\n", a3); //打印3 printf("%d\n", *p3); //打印3 //p3 = &a1; 指针变量内容被锁,无法修改 *p3 = 300; printf("%d\n", a3); //打印300 printf("%d\n", *p3); //打印300 a3 = 3000; printf("%d\n", a3); //打印3000 printf("%d\n", *p3); //打印3000 }
指针和数组、多级指针

指针与数组;指针操作数组元素 ---------------------------------------------------------------------------------------------------------- 指针与数组;指针操作数组元素 int main() { //指针与数组;指针操作数组元素 //数组名是地址【常量】 那不就是相当于 * const p 么。。。 int arr[] = { 1,2,3,4,5 }; printf("%d\n", arr[2]); //打印3 printf("%d\n", sizeof(arr[2])); //4字节 printf("%p\n", arr); //打印00000067D5CFF638 printf("%p\n", arr + 1); //打印00000067D5CFF63C //这个地方+1,并不是地址+1,而是+1地址段。。 printf("%p\n", arr + 2); //打印00000067D5CFF640 printf("%d\n", *(arr + 2)); //打印3 //这种方式也能完成取地址,【重点理解!!!!】 printf("=========================================================\n"); double arr2[] = { 1,2,3,4,5 }; printf("%lf\n", arr2[2]); //打印3.000000 printf("%d\n", sizeof(arr2[2])); //8字节 printf("%p\n", arr2); //打印00000067D5CFF668 printf("%p\n", arr2 + 1); //打印00000067D5CFF670 printf("%p\n", arr2 + 2); //打印00000067D5CFF678 printf("%f\n", *(arr2 + 2)); //打印3.000000 printf("=========================================================\n"); int arr3[] = { 1,2,3,4,5 }; int* p3 = arr3; printf("%d\n", arr3[3]); //打印4,获取数组元素的方式1 printf("%d\n", *(arr3 + 3)); //打印4,获取数组元素的方式2 printf("%d\n", p3[3]); //打印4,获取数组元素的方式3 printf("%d\n", *(p3 + 3)); //打印4,获取数组元素的方式4 // arr3[3] == *(arr3+3) == p3[3] == *(p3 + 3) 看起来指针和数组很相似。。。 //指针与数组名的区别 //1.指针是变量;数组名是常量 //2.sizeof(指针)= 4/8(取决于平台);sizeof(数组名)= 数组的长度 //数组名是地址常量,对数组名进行取地址'&'操作,得到的地址仍是这个地址常量 //指针是保存地址的变量,对指针变量进行取地址'&'操作,得到的是指针变量所在内存空间的地址 }

指针加减运算;数组地址的加减;指针加减指针 ========================================================================================================== 指针加减运算 加法运算 指针计算不是简单的整数相加 如果是一个int *,+1的结果是增加一个int的大小 如果是一个char *,+1的结果是增加一个char大小 int main() { //指针变量的加减 int a = 0x12345678; int* p1 = &a; char* p2 = &a; printf("%p\n", *p1); //0000000012345678 printf("%p\n", *p2); //0000000000000078 猜到了只会读取1字节,但是没猜到是从低地址位开始读。。 //所以在内存中的实际存储可能并不是想象的0000000010101010,可能实际是倒序存储的??? //指针类型影响了读取数据的长度 printf("%p\n", p1); //0000005C3A72F934 printf("%p\n", p1 + 1); //0000005C3A72F938 //指针变量内容的+1,并不是直接+1,而是+1个指针类型长度的字节数 printf("%p\n", p2); //0000005C3A72F934 printf("%p\n", p2 + 1); //0000005C3A72F935 //我的理解: //指针变量的加减逻辑和普通变量的加减逻辑是不一样的! //指针变量的加减关乎于指针类型以及加减值 //普通变量的加减,只在于数据本身 printf("=========================================================\n"); //使用指针获取数组元素 int arr[] = { 1,2,3,4,5,6,7,8,9 }; int* p3 = arr; for (size_t i = 0; i < 9; i++) { printf("%d ", *p3); //打印:1 2 3 4 5 6 7 8 9 p3++; } printf("数组的元素数量:%d\n",(p3-arr)); //数组的元素数量:9 (指针变量的加减还是得取决于变量类型!!!) printf("数组的元素数量:%d\n", (&arr[8] - &arr[0] + 1)); //数组的元素数量:9 //指针变量是不能进行乘除的 } ----------------------------------------------------------------------------------------------------- int main() { //数组地址的加减 int a[] = { 1,2,3,4,5,6,7,8,9, }; printf("%p\n", a); //000000791B12F5D8 printf("%p\n", a + 1); //000000791B12F5DC 移动4字节 printf("%p\n", &a); //000000791B12F5D8 printf("%p\n", &a + 1); //000000791B12F5FC 移动36字节,因为数组中有9个元素;若改变数组中的元素个数,那么&a + 1移动的字节数也会发生变化 } ----------------------------------------------------------------------------------------------------- int main() { //指针加减指针 int a = 10,b = 20; int* p1 = &a, * p2 = &b; p1 - p2; //指针指针相减 //p1 + p2; 不支持指针相加 printf("%p\n", p1); //00000027DB2FF744 printf("%p\n", p2); //00000027DB2FF764 printf("%d\n", p1 - p2); //-8,相差8个单位(元素),即32字节 printf("%p\n", p1 - p2); //FFFFFFFFFFFFFFF8,相差8个单位(元素),即32字节 printf("%p\n", p2 - p1); //0000000000000008,相差8个单位(元素),即32字节 if (p1 < p2) //指针地址是可以相比较的 printf("p2指向的地址靠后"); else printf("p1指向的地址靠后"); }

指针数组;多级指针 ============================================================================================== 指针数组,它是数组,数组的每个元素都是指针类型。 int main() { //指针数组 int a = 1, b = 2, c = 3, d = 4, e = 5; int* arr[] = { &a, &b, &c, &d, &e, }; printf("%d\n", *arr[0]); //打印:1 printf("%d\n", *arr[1]); //打印:2 printf("%d\n", *arr[2]); //打印:3 printf("%d\n", **arr); //打印:1 数组名解引用后,获取到储存的地址;对该地址解引用,则获取到数据内容 printf("%d\n", *(*(arr))); //打印:1 数组名解引用后,获取到储存的地址;对该地址解引用,则获取到数据内容 printf("%d\n", *(*(arr+0))); //打印:1 数组名解引用后,获取到储存的地址;对该地址解引用,则获取到数据内容 printf("%d\n", *(*(arr+1))); //打印:2 数组名解引用后,获取到储存的地址;对该地址解引用,则获取到数据内容 printf("%d\n", *(*(arr+1))); //打印:3 数组名解引用后,获取到储存的地址;对该地址解引用,则获取到数据内容 //双* 就是二级指针 printf("%p\n", arr[0]); //打印:000000C5909DF464 printf("%p\n", arr[1]); //打印:000000C5909DF484 printf("%p\n", arr[2]); //打印:000000C5909DF4A4 int aaa = arr[0]; //printf("%d\n", *aaa); //不能这么操作,提示 *后面跟的必须是指针 } ------------------------------------------------------------------------------------------------ 多级指针 C语言允许有多级指针存在,在实际的程序中一级指针最常用,其次是二级指针。 二级指针就是指向一个一级指针变量地址的指针。 三级指针基本用不着,但考试会考。 int main() { //多级指针 //多级指针不能跳跃定义,比如在没有一级指针的前提下,不能直接定义二级指针 int a = 100; int* p = &a; int** pp = &p; int*** ppp = &pp; int**** pppp = &ppp; printf("%d\n",a); //打印输出都是100 printf("%d\n",*p); printf("%d\n",**pp); printf("%d\n",***ppp); printf("%d\n",****pppp); printf("%p\n",***pppp); //00000099C299F914 printf("%p\n",&a); //00000099C299F914 }
指针和函数

指针和函数;传数值和传地址;函数形参改变实参的值 ================================================================================= 指针和函数: 栈 帧: 当函数调用时,系统会在 stack 空间上申请一块内存区域,用来供函数调用,主要存放 形参 和 局部变量(定义在函数内部)。 当函数调用结束,这块内存区域自动被释放(消失)。 ------------------------------------------------------------------------------------------------- 传值和传址: 传数值:函数调用期间,实参将自己的值,拷贝一份给形参。 传地址:函数调用期间,实参将地址值,拷贝一份给形参。 【重点】 (地址值 --》 在swap函数栈帧内部,修改了main函数栈帧内部的局部变量值) ------------------------------------------------------------------------------------------------- //栈帧:当调用函数时,系统会在stack空间申请一块内存区域,用来供函数调用,主要存放形参和局部变量 // 当函数调用结束,这块内存区域自动被释放 //swap1函数过程梳理: //1.调用main函数,系统为main函数在stack空间申请一块内存区域,main函数定义了2个变量m/n //2.main函数运行期间,调用自定义swap1函数,系统为swap1函数申请一块内存区域,实参传递给形参【m/n的值复制给形参a/b】 //(所以在函数调用期间进行数据交换,不影响位于swap1函数外部的变量m/n) //3.swap1函数调用结束,占用的内存被释放 //4.回到main函数 int swap1(int a, int b) { int tmp; printf("swap函数:a = %p;b= %p\n", &a, &b); //swap函数:a = 000000B1C453F760; b = 000000B1C453F768 tmp = a; a = b; b = tmp; return 0; //在swap函数内部,a/b确实进行了数据交换 } //swap2函数过程梳理: //1.调用main函数,系统为main函数在stack空间申请一块内存区域,main函数定义了2个变量m/n //2.main函数调用swap2函数,传入2个地址, //3.swap2进行接收,在swap2函数的内存空间创建了2个指针变量a,b,并保存了传入的2个地址 //4.swap2函数对2个指针变量进行解引用操作,修改了m,n的数据。swap2函数调用结束,释放内存空间 //5.main函数继续运行,直到结束 //经过验证,main函数的m,n数据确实被调换了 int swap2(int* a, int* b) { int tmp; tmp = *a; //此时a,b就是指针变量,里面保存了m,n的内存地址 *a = *b; *b = tmp; } int main() { int m = 11, n = 22; printf("交换前m = %p;n= %p\n", &m, &n); //交换前m = 000000B1C453F784;n= 000000B1C453F7A4 swap1(m,n); printf("交换后m = %d;n= %d\n", m, n); //虽然swap函数进行了数据交换,但是不影响m/n,m/n的值无变化 swap2(&m, &n); printf("swap2交换后m = %d;n= %d\n", m, n); //swap2交换后m = 22;n= 11;数据发生了交换 }

数组名作为函数参数;指针做为函数的返回值;数组做函数返回值 ======================================================================================================== 数组名作为函数参数 数组名做函数参数,函数的形参会退化为指针 //数组做参数时,传递的不是数组,而是数组首地址 //所以数组做函数参数时,一般要传递2个参数,1个地址,1个数组元素数量; //数组作为函数参数时,存在3种写法:int sort1(int *arr) ;int sort1(int arr[]);int sort1(int arr[10]) int sort1(int arr[],int len) { //等效于int sort1(int *arr) int tmp; //int len1 = sizeof(arr) / sizeof(arr[0]); //这种方式求len存在问题,此时arr就是一个指针,sizeof(arr) 求的指针的长度,而不是数组的长度 for (size_t i = 0; i < 10 -1; i++) { for (size_t j = 0; j < 10 - i -1; j++) { if (arr[j] < arr[j + 1]) { tmp = arr[j]; arr[j] = arr[j +1]; arr[j+1] = tmp; }; }; }; } int main() { int arr[] = { 18,32,773,4444,45,6,997,888,74239,63420 }; sort1(arr,sizeof(arr) / sizeof(arr[0])); for (size_t i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) { printf("%d ", arr[i]); }; } ---------------------------------------------------------------------------------------------------- 指针做函数返回值 //指针做函数返回值 //不能返回局部变量的地址!!! int *test(int a) { a = 333; return &a; } int main() { int m = 11; printf("%p\n", test(m)); //000000D3854FF630 printf("%d\n", *test(m)); //333 虽然test函数内存地址被回收了,但是内容没有被改变,所以仍然可以打印出来;这种方式显然是不安全的 } ---------------------------------------------------------------------------------------------------- 数组做函数返回值 C语言中,不允许数组作为函数的返回值;只能写成指针形式
指针和字符串

指针方式定义字符串数组;(练习)实现字符串比较功能;(练习)字符串去空格;(练习)统计字符串2 在字符串1 出现的次数 ======================================================================================================== int main() { char str1[] = "hello"; char* str2 = "hello2"; //这种方式定义出来的是字符串常量! str1[0] = 'H'; str2 = str1; printf("%s\n", str1); //Hello printf("%s\n", str2); //Hello printf("===============================================================\n"); char* str3 = "hello3"; char* str4 = "hello3"; printf("%p\n", str3); //00007FF697BF9C24,因为是常量,可以共用;所以str4没有去开辟新的内存空间 printf("%p\n", str4); //00007FF697BF9C24 } ------------------------------------------------------------------------------------------------------ 实现字符串比较功能 int func1(char arr1[], int len1 , char arr2[], int len2) { int len; len = len1 > len2 ? len2 : len1; for (size_t i = 0; i < len; i++) { if (*arr1 > *arr2) { //if (arr1[i] > arr2[i]) return 1; } else if (*arr1 < *arr2) { return -1; } else { arr1++; arr2++; } } return 0; } int main() { char str1[] = "hello41"; char str2[] = "hello51"; int abc = func1(str1, sizeof(str1) / sizeof(str1[0]), str2, sizeof(str2) / sizeof(str2[0])); printf("%d", abc); } ------------------------------------------------------------------------------------------------------ //字符串去空格 int func1(char arr1[]) { char* p = arr1; while (*arr1) { if (*arr1 != ' ') { *p = *arr1; p++; arr1++; } else { arr1++; } } *p = '\0'; } int main() { char str1[] = " h e l l o 4 1"; func1(str1); printf("%s", str1); } ------------------------------------------------------------------------------------------------------ (练习)统计字符串2 在字符串1 出现的次数 int my_strstr(char arr1[],char arr2[] ) { //视频思路是在使用strstr函数的基础上- -,,,, //我的思路,使用指针在两个字符串逐个比较字符,并设置了标志位flag //单个字符相同,则flag++,不同则将flag置0;若连续相同,flag位等于5,则判断存在一个相同字符串,count+1,同时将flag置0 int arr2_len = 0; while (arr2[arr2_len]) { arr2_len++; //只要arr2字符串数组的元素不为‘\n’,arr2_len++ } printf("arr2_len:%d\n", arr2_len); int count = 0; int flag = 0; while (*arr1) { if (*arr1 == *(arr2 + flag)) { flag++; } else { flag = 0; } if (flag == arr2_len) { count++; flag = 0; } arr1++; } return count; } int main() { char arr1[] = "hellollollololollollollollo"; char arr2[] = "llo"; int a = my_strstr(arr1, arr2); printf("%d\n", a); }

指针数组做为main函数的形参 ======================================================================================================== 指针数组做为main函数的形参 int main(int argc, char *argv[]); main函数是操作系统调用的,第一个参数标明argc数组的成员数量,argv数组的每个成员都是char *类型 argv是命令行参数的字符串数组 argc代表命令行参数的数量,程序名字本身算一个参数 main函数 无参数:int main(void) == int main() 有参数:int main(int arg1,char *arr[]) == int main(int arg1,char **arr[) 【固定写法】 参数1:表示给main函数传递的参数总个数 参数2:一个指针数组,每一个数组元素都是字符串 char * //带参数的main函数 int main(int argc, char* argv[]) { for (size_t i = 0; i < argc; i++) { printf("%s %p\n", argv[i], &argv[i]); } } /* C:\Users\Allen\source\repos\C_day01\x64\Debug>C_day01.exe 1 22 333 4444 C_day01.exe 000001B741B25D20 1 000001B741B25D28 22 000001B741B25D30 333 000001B741B25D38 4444 000001B741B25D40 */

字符串处理函数:strlen、strcpy、strncpy、strcat、strncat、strcmp、strncmp、sprintf、sscanf、strchr、strstr、strtok、atoi、atof、atol ======================================================================================= strlen() #include <string.h> size_t strlen(const char *s); 功能:计算指定指定字符串s的长度,不包含字符串结束符‘\0’ 参数: s:字符串首地址 返回值:字符串s的长度,size_t为unsigned int类型 ----------------------------------------------------------------------------------------- strcpy() #include <string.h> char *strcpy(char *dest, const char *src); 功能:把src所指向的字符串复制到dest所指向的空间中,'\0'也会拷贝过去 参数: dest:目的字符串首地址 src:源字符首地址 返回值: 成功:返回dest字符串的首地址 失败:NULL 注意:如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误情况。 ----------------------------------------------------------------------------------------- strncpy() #include <string.h> char *strncpy(char *dest, const char *src, size_t n); 功能:把src指向字符串的前n个字符复制到dest所指向的空间中,是否拷贝结束符看指定的长度是否包含'\0'。 参数: dest:目的字符串首地址 src:源字符首地址 n:指定需要拷贝字符串个数 返回值: 成功:返回dest字符串的首地址 失败:NULL ----------------------------------------------------------------------------------------- strcat() #include <string.h> char *strcat(char *dest, const char *src); 功能:将src字符串连接到dest的尾部,‘\0’也会追加过去 参数: dest:目的字符串首地址 src:源字符首地址 返回值: 成功:返回dest字符串的首地址 失败:NULL ----------------------------------------------------------------------------------------- strncat() #include <string.h> char *strncat(char *dest, const char *src, size_t n); 功能:将src字符串前n个字符连接到dest的尾部,‘\0’也会追加过去 参数: dest:目的字符串首地址 src:源字符首地址 n:指定需要追加字符串个数 返回值: 成功:返回dest字符串的首地址 失败:NULL ----------------------------------------------------------------------------------------- strcmp() #include <string.h> int strcmp(const char *s1, const char *s2); 功能:比较 s1 和 s2 的大小,比较的是字符ASCII码大小。 参数: s1:字符串1首地址 s2:字符串2首地址 返回值: 相等:0 大于:>0 在不同操作系统strcmp结果会不同 返回ASCII差值 小于:<0 ----------------------------------------------------------------------------------------- strncmp() #include <string.h> int strncmp(const char *s1, const char *s2, size_t n); 功能:比较 s1 和 s2 前n个字符的大小,比较的是字符ASCII码大小。 参数: s1:字符串1首地址 s2:字符串2首地址 n:指定比较字符串的数量 返回值: 相等:0 大于: > 0 小于: < 0 ----------------------------------------------------------------------------------------- sprintf() #include <stdio.h> int sprintf(char *str, const char *format, ...); 功能:根据参数format字符串来转换并格式化数据,然后将结果输出到str指定的空间中,直到出现字符串结束符 '\0' 为止。 参数: str:字符串首地址 format:字符串格式,用法和printf()一样 返回值: 成功:实际格式化的字符个数 失败: - 1 ----------------------------------------------------------------------------------------- sscanf() #include <stdio.h> int sscanf(const char *str, const char *format, ...); 功能:从str指定的字符串读取数据,并根据参数format字符串来转换并格式化数据。 参数: str:指定的字符串首地址 format:字符串格式,用法和scanf()一样 返回值: 成功:参数数目,成功转换的值的个数 失败: - 1 ----------------------------------------------------------------------------------------- strchr() #include <string.h> char *strchr(const char *s, int c); 功能:在字符串s中查找字母c出现的位置 参数: s:字符串首地址 c:匹配字母(字符) 返回值: 成功:返回第一次出现的c地址 失败:NULL ----------------------------------------------------------------------------------------- strstr() #include <string.h> char *strstr(const char *haystack, const char *needle); 功能:在字符串haystack中查找字符串needle出现的位置 参数: haystack:源字符串首地址 needle:匹配字符串首地址 返回值: 成功:返回第一次出现的needle地址 失败:NULL ----------------------------------------------------------------------------------------- strtok() #include <string.h> char *strtok(char *str, const char *delim); 功能:来将字符串分割成一个个片段。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时, 则会将该字符改为\0 字符,当连续出现多个时只替换第一个为\0。 参数: str:指向欲分割的字符串 delim:为分割字符串中包含的所有字符 返回值: 成功:分割后字符串首地址 失败:NULL ----------------------------------------------------------------------------------------- atoi() #include <stdlib.h> int atoi(const char *nptr); 功能:atoi()会扫描nptr字符串,跳过前面的空格字符,直到遇到数字或正负号才开始做转换,而遇到非数字或字符串结束符('\0')才结束转换,并将结果返回返回值。 参数: nptr:待转换的字符串 返回值:成功转换后整数 类似的函数有: atof():把一个小数形式的字符串转化为一个浮点数。 atol():将一个字符串转化为long类型
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!