【C语言】字符串 清疚 2022-06-12 11:06 250阅读 0赞 1、使用存储区的地址作为返回值可以让调用函数使用被调用函数的存储区 2、这种时候被调用函数需要提供一个指针类型的存储区记录作为返回值的地址数据 3、不可以把非静态局部变量的地址作为返回值使用 4、C语言里的文字信息必须记录在一组连续的字符类型存储区里 5、所有文字信息必须以’\\0’字符做结尾,这个字符的ASCII码就是数字0 6、符合以上两个特征的内容可以用来在C语言程序里表示文字信息,它们叫做字符串 7、字符串里’\\0’字符前面的部分是有效字符 8、所有字符串都可以采用字符类型指针表示 9、字符串字面值是表示字符串的一种方法,用两个双引号中间包含的一组字符表示字符串字面值(例如”dsg”,”^*&*@”等) 10、编译器在编译的时候会自动在字符串字面值的末尾追加’\\0’字符 11、编译器会把字符串字面值替换成第一个字符所在存储区的地址 12、字符串字面值的内容在程序执行过程中不可以改变 13、程序里内容一样的字符串字面值是同一个 14、多个并列的字符串字面值会被合并成一个 15、字符数组也可以用来记录字符串 16、只有包含’\\0’字符的字符数组才可以当作字符串使用 17、可以使用字符串字面值对字符数组进行初始化,编译器会把字符串字面值里的’\\0’字符初始化到字符数组里 18、字符数组里字符串内容可以修改 19、在printf函数调用语句里使用%s做占位符可以把字符串里所有有效字符显示在屏幕上 20、不可以使用操作符对字符串进行操作,应该使用一组标准函数 21、为了使用这组标准函数需要包含string.h头文件 • strlen 用来统计字符串里有效字符的个数和sizeof关键字完全不同 • strcat 用来把两个字符串合并成一个字符串这个函数有可能修改不属于数组的存储区,这会造成严重错误 • strncat 功能和strcat函数类似这个函数可以避免strcat的错误 • strcmp 用来比较两个字符串的大小根据字符ASCII码比较两个字符串的大小 返回值是0表示两个字符串一样大 返回值是1表示第一个参数代表的字符串大 返回值是-1表示第二个参数代表的字符串大 • strncmp 用来比较两个字符串前n个字符的大小 • strcpy 用来把一个字符串的内容复制到字符数组里这个函数也可能修改不属于数组的存储区,这会造成严重错误 • strncpy 功能和strcpy类似只复制字符串里前n个字符,这样可以避免问题有可能不复制’\\0’字符 • memset 用来把字符数组里多个连续的字符类型存储区内容设置成同一个字符 • strstr 从一个大字符串里查找小字符串的位置如果找不到就返回NULL 22、以下两个函数不需要包含string.h头文件 • sprintf 把多个数字按照格式拼凑成字符串并记录到字符数组里 • sscanf 从字符串里获得多个数字并记录到存储区里 23、以下两个函数需要包含stdlib.h头文件 这两个函数可以把字符串里的数字转换成数字类型 • atoi 这个函数可以把字符串里开头的整数部分转换成整数类型 • atof 这个函数可以把字符串里开头的浮点数部分转换成双精度浮点类型 24、在scanf函数调用语句里使用%s做占位符可以把用户在键盘上输入的字符串记录到字符数组里 这种方法有可能造成严重问题 25、fgets函数也可以把键盘上输入的字符串记录到字符数组里,这个函数可以避免scanf函数的问题 这个函数需要三个参数 • 1.数组名称 • 2.数组里的存储区个数 • 3.用stdin表示键盘 26、如果用户输入的内容不能把数组充满就把用户最后输入的回车当作’\\n’字符也放到字符数组里 27、如果用户输入的内容超过数组的范围就把多余的部分留在输入缓冲区里等下次读 28、在每次使用fgets函数从键盘得到字符串以后都应该把可能存在的多余数据清理掉 29、清理多余数据的语句应该放在分支里,分支要保证输入缓冲区里有多余数据的时候才进行清理 ### 字符串处理函数演示: ### /* *字符串处理函数 * * */ #include <stdio.h> #include <string.h> #include <stdlib.h> //统计大小 void exercise_1(void) { char str[10] = "abc"; printf("有限字符串的个数是:%d\n", strlen(str));//返回值是3 printf("sizeof(str):%d\n", sizeof(str));//stelen和sizwof完全无关 } //合并 void exercise_2(void) { char str[10] = "abc"; printf("合并的结果是:%s\n", strcat(str, "xyz"));//返回值就是合并后的结果 printf("合并的结果是(str[]):%s\n", str);//数组内容已经改变了,这个函数可能会修改不是数组区域的数,导致错误,例如填入的数过多了,超出范围后还会继续填 printf("strncat():%s\n",strncat(str, "abcdef", 3));//第3位填的是最多可以填多少个 printf("合并的结果是(str[]):%s\n", str); } //比较 void exercise_3(void) { printf("比较两个字符串abc,abd的大小:%d\n", strcmp("abc","abd")); printf("比较两个字符串abc,abd前2个的大小:%d\n", strncmp("abc","abd",2)); } //复制覆盖 void exercise_4(void) { char str[10] = "abcdefghj"; printf("%s\n", strcpy(str,"abcabc"));//复制并覆盖原来的内容,这个函数在超出范围后也会继续覆盖后面的存储区,造成错误 printf("复制的结果是(str[]):%s\n", str); printf("%s\n",strncpy(str, "gggg", 2));//只复制前n个,不保证会吧\0复制过去 printf("复制的结果是(str[]):%s\n", str); } //将连续区域赋值同样的值 void exercise_5(void) { char str[10] = "abcdefghi"; memset(str, 'h', 9);//将前9个存储区都赋值为h printf("%s\n", str); } // 查找 void exercise_6(void) { printf("找到的:%s\n",strstr("abcdefghijkl","def"));//返回值是找到的地址,结果为defghijkl printf("找不到的:%p\n",strstr("abcdefghijkl","dfe"));//返回值是找到的地址,结果(nil) } //sprintf : 把多个数字按照格式拼凑成字符串并记录在字符数组里 void exercise_7(void) { char str[20] = { 0}; printf("%d %g %c\n", 45, 6.4f, 'I'); sprintf(str,"%d %g %c\n", 45, 6.4f, 'I');//将内容先存在字符数组里 printf("%s", str); } //sscanf : 从字符串里获得多个数字并记录到存储区 void exercise_8(void) { int num = 0; float fnum = 0.0f; char ch = 0; sscanf("T 23 6.5","%c%d%g", &ch, &num, &fnum);//获得数据,并存在变量中 printf("%d %g %c\n", num, fnum, ch); } //atoi:把字符串里开头的整数部分转换成整数类型 //atof:把字符串里开头的浮点数部分转换成双精度的浮点类型 void exercise_9(void) { double dnum = 0.0; int num = atoi("23dasd");//获得整数23赋值给num printf("num是:%d\n", num); dnum = atof("34.62sd");//获得浮点数34.62赋值给dnum printf("dnum是:%g\n", dnum); } int main() { // exercise_1(); // exercise_2(); // exercise_3(); // exercise_4(); // exercise_5(); // exercise_6(); // exercise_7(); // exercise_8(); exercise_9(); return 0; } ### 指针类型返回值练习: ### /* * 编写函数,从数组中找到最大数字所在的存储区,并将存储区传递给调用函数 * */ #include <stdio.h> int *max(const int *arr, int size) { //加const防止存储区内容被修改 const int *p_tmp = NULL; //可以修改指针本身,但不能修改所指向的存储区内容 int *p_max = NULL; for(p_tmp = arr; p_tmp <= arr + size - 1; p_tmp++) { if(!p_max || *p_tmp > *p_max) { //因为p_max没有指定地址,是不能使用的,所以这里先用!p_max进行判断,即第一次循环的时候先进行下面的运算,将第一个传给p_max,然后再进行判断 p_max =(int*) p_tmp;// 强制转换,将const int类型转换为int } } return p_max; } int main() { int arr[5] = {0}; int size = 5; int i = 0; for(i = 0; i <= size - 1; i++) { scanf("%d", &arr[i]); } int *p_max = max(arr,size); printf("最大数为:%d 最大数的地址是 %p\n", *p_max, p_max); return 0; } ### 字符串练习: ### /* *编写程序,从键盘上获得多个程序(不超过10个),把他们按照下面格式拼凑成字符串显示在屏幕上 * 10,20,30,40,50 * */ #include <stdio.h> #include <string.h> int main() { char str[50] = { 0}, tmp[10] = { 0}; int qty = 0, num = 0, grade = 0;//最多 printf("请输入考试成绩个数:\n"); scanf("%d", &qty); for(num = 1; num <= qty; num++) { printf("请输入成绩:\n"); scanf("%d", &grade); sprintf(tmp, "%d,", grade);//将数字转换为字符 strcat(str,tmp);//将数组合并 } str[strlen(str) - 1] = 0;//去掉最后一个逗号,有效字符串最后一个是回车,倒2是逗号 printf("%s\n", str); return 0; } ### 指针练习: ### /* * 输入1 2 3 4 5 * 输出5 4 3 2 1 * */ #include <stdio.h> void AB_BA_1(int *arr, int size) { int i = 0; int tem = 0; for(i = 0; i <= (size-1)/2; i++) { tem = *(arr + i); *(arr + i) = *(arr + (size - 1) - i); *(arr + (size -1) - i) = tem; } } void AB_BA_2(int *arr, int size) { int *p_start = arr, *p_end = arr + size - 1;//地址的地址, int tmp = 0; //考虑到无法确认结束条件,用while更为合适,因为没有必须执行一次的必要,所以不用do...while(); while(p_start < p_end) { //结束条件是没有重合 tmp = *p_start; *p_start = *p_end; *p_end = tmp; p_start++; p_end--; } } int main() { int i = 0, size = 5; int arr[5] = {0}; printf("请输入5个整数:\n"); for(i = 0; i <= 4; i++) { scanf("%d", &arr[i]); } printf("正向输出为:\n"); for(i = 0; i <= 4; i++) { printf("%d ", arr[i]); } printf("\n"); // AB_BA_1(arr,size); AB_BA_2(arr,size); printf("反向输出为:\n"); for(i = 0; i <= 4; i++) { printf("%d ", arr[i]); } printf("\n"); return 0; } ### 字符串的定义和使用: ### /* * 字符串的定义和使用 * */ #include <stdio.h> int main() { char str[5] = {}; scanf("%4s", str);//%4s限制了输入的个数,超过的不会输入,会停留在缓冲区里面,等待下次的输入,需要清除 printf("%s\n", str); return 0; } ### 字符串演示: ### /* * 字符串演示 * */ #include <stdio.h> int main() { char str[] = "abc";//用“”给数组赋初 printf("sizeof(str):%d\n", sizeof(str));//4个字节,3个字符加一个\0 printf("abc的首地址:%p\n", "abc");//编译器会把字符串字面值替换成第一个字符所在存储区的地址 printf("%p\n","abc");//重复运行地址不变 printf("abc x :%c\n",*"abc""x"); printf("abc首地址内容:%c\n", *"abc"); printf("*(“abc+3”):%d\n",*("abc" + 3)); printf("abcdef:%s\n", "abcdef");//用%s可以显示多个存储区的内容显示出来??%s的工作原理 return 0; } ### 字符串输入: ### /* * 字符串输入 * */ #include <stdio.h> #include <string.h> void exercise_1(void) { char str[20] = { 0}; printf("请输入一个字符串:\n"); scanf("%s", str); printf("%s\n", str); } void exercise_2() { char str[10] = { 0}; printf("输入:\n"); fgets(str,10,stdin);//如果输入超过范围,就留在缓冲区中下次用,所以下一个输入无法输入,应该清楚缓存 if(strlen(str) == 9 && str[8] != '\n') { //数组的第10个下标是不可用的,越界了,字符> 串数组的最后一位,即下标为9的是“\0”,在这里输入数据后的回车也是一个字符,用strlen统计后 也算在其中,即回车也是一个有效字符。在这句话中,前一个条件确认了输入的是满的,及有效字> 符是9,但是不确定是不是正好满了,若正好满的话,数组下标为8的正好是回车 scanf("%*[^\n]"); scanf("%*c"); printf("输入:\n"); scanf("%s",str); printf("%s\n", str); } int main() { // exercise_1(); exercise_2(); return 0; } ### 自定义函数实现strlen和函数strcat的功能: ### /* * 自定义函数实现strlen和函数strcat的功能 * 用指针 * */ #include <stdio.h> //用while循环,判断字符串结束的标志是当到最后一个时是\0即0为假推出 int mystrlen(char *str) { int count = 0; while (*str) { count++; str++; } return count; } //先将第一个指针指向字符串的最后,然后将字符一个一个赋值 char* mystrcat(char *s, char *d) { char* old = s; while(*s) s++; while(*d) { *s = *d; s++; d++; } return old; } int main() { char str[100] = "This is "; printf("str的长度为:%d\n", mystrlen(str)); char* str1 = "a string"; mystrcat(str, str1); printf("连接后的字符串为:%s\n", str); return 0; } ### 指针类型返回值: ### /* * 返回一个指针类型的返回值,调用函数就可以使用被调函数的存储区 * */ #include <stdio.h> int *read(void) { //要求返回一个指针类型的返回值,因此需要函数类型也得是指针类型的 static int num = 0; printf("请输入一个数:\n"); scanf("%d", &num); return # } int main() { int *p_num = read(); printf("数字是:%d \n", *p_num); return 0; }
还没有评论,来说两句吧...