练习:
#include <stdio.h>
int *reverse(int *p_num,int size){
int *p_start = p_num,*p_end=p_num+size-1;
int temp=0;
while(p_start < p_end){
temp = *p_start;
*p_start = *p_end;
*p_end = temp;
p_start++;
p_end--;
}
return p_num;
}
int main(){
int array[]={1,2,3,4,5};
int *p_num = reverse(array,5);
for(int i=0;i<5;i++){
printf("%d ",array[i]);
printf("%d ",*(p_num+i));
}
printf("\n");
return 0;
}
输出结果:
int *p_num = NULL;这条声明语句里*号是用来表示p_num的类型是指针类型
*p_num = num;这条语句里*号表示p_num指针捆绑的存储区。这句语句表示我们把num变量里面的数字赋值给p_num指针里捆绑的存储区里。
1.C语言规定所有文字信息必须记录在一组连续的字符类型存储区里。
所有文字信息必须用'\0'字符做结尾,这个字符的ASCII码就是0
符合以上两个特征的内容叫做字符串。
字符串里'\0'字符前面的部分是有效文字信息。
所有的字符串都可以采用字符类型指针表示。
![](/qrcode.jpg)
字符串字面值是一种字符串,例如"abc"、"^&*^"
编译器在边缘的时候自动在字符串字面值的末尾加上'\0'字符
编译器在编译的时候会把字符串字面值替换成第一个字符所在存储区的地址。
例子:
输出结果:
字符串字面值的内容在程序执行过程中不可以改变。
例子:
运行结果:运行出错
程序里内容一样的字符串字面值在内存里其实是同一个。
例子:
运行结果:abc两个字符串的地址一样
多个并列的字符串字面值会被自动合并成一个。
例子:
运行结果:"abc"与"ab""c"的地址一样
2.字符数组也可以作为字符串使用。
只有包含'\0'字符的字符数组才可以作为字符串使用。
可以使用字符串字面值对字符数组进行初始化(计算机会把字符串字面值里的'\0'字符也初始化到字符数组里)
例子:
运行结果:char str[]="xyz"; str数组的sizeof是4
字符数组里字符串的内容可以修改。
在printf函数调用语句里使用%s做占位符,可以把字符串里所有的文字显示在屏幕上
例子:
运行结果:语句 printf("%s\n","abcdef"); 输出结果为 abcdef
不可以使用操作符操作字符串
C语言里提供一组标准函数用来操作字符串。
为了使用这些标准函数需要包含string.h头文件
strlen | 用来统计字符串里有效字符的个数,和sizeof计算结果不同 |
strcat | 用来合并两个字符串,需要两个字符串做参数,第一个参数必须是字符数组里的字符串,把第二个参数里的所有有效字符追加到第一个参数有效字符的后面。返回值就是第一个参数,可以用来表示合并后的字符串。如果合并后的字符串超过数组的范围,函数就会修改不属于数组的存储区,这会造成严重的错误 |
strncat | 功能和strcat类似,可以避免出现错误。 |
stcmp | 用来比较两个字符串的大小,从前向后依次比较每对字符,ASCII码大的字符所在的字符串就大。函数有两个参数各表示一个字符串。返回值表示比较结果,返回值为1表示前一个字符串大;返回值为-1表示后一个字符串大;返回值为0表示一样大。 |
strncmp | 功能和strcmp类似,只能比较两个字符串的前n个字符 |
strcpy | 把一个字符串里的有效字符复制到字符数组里,如果字符串的长度超过字符数组的长度就会修改不属于数组的存储区,这样会出现严重错误。 |
strncpy | 功能和strcpy类似,但是可以避免出问题,有可能不复制'\0'字符 |
memset | 用来把字符数组里多个存储区的内容设置成同一个字符。 |
strstr | 用来在一个字符串里查找另外一字符串的位置,如果找不到则返回值是NULL |
例子:strlen
运行结果:
例子:strcat
运行结果:
例子:strncat
运行结果:strncat(str,"sdagsdgsd",2);里面的2表示插入字符的数量为2即sd
例子:strcmp
运行结果:
例子:strncmp
运行结果:
例子:strcpy
运行结果:
例子:strncpy
输出结果:strncpy(str,"abcdefiopsadg",2);将字符串"abcdefiopsadg"的前面2个字符复制到str字符里。所以输出abz
例子:memset
输出结果:memset(str,'h',9);这条语句就是把复制9个h字符到str字符数组里
例子:strstr
运行结果:strstr("abcdefghijklmn","def");以字符串%s显示就是从def字符开始显示
以下两个字符串相关的函数使用的时候不需要包含string.h头文件
sprintf | 按照格式把多个数字合并成一个字符串并记录到字符数组里 |
sscanf | 按照格式从字符串里获得多个数字,并记录到存储区里 |
例子:sprintf
输出结果:
例子:sscanf
运行结果:
以下两个字符串相关的函数可以把字符串里的数字转换成数字类型
为了使用这个两个函数需要包含stdlib.h头文件
atoi | 用来把字符串里开头的整数部分转换成整数类型 |
atof | 用来把字符串里开头的浮点数部分转换成双精度浮点类型 |
例子:atoi
运行结果: 例子:atof
运行结果:
2.在scanf函数调用语句里使用%s做占位符可以从键盘得到一个字符串并记录到字符数组里。这种方法有可能造成严重的错误。
例子:
运行结果:
如果在输入字符串中间加上空格 ,就会丢失空格后面的字符串:
当输入字符串超过数组长度,程序运行就会崩溃:
3.fgets函数也可以从键盘得到一个字符串,并记录到字符数组里,这个函数可以避免scanf函数的问题。
这个函数有三个参数:fgets(第一个参数;第二个参数;第三个参数);
1.数组名称
2.数组里存储区个数
3.用stdin表示键盘
如果输入的内容不能把数组充满就会把用户最后输入的换行字符当作'\n'字符也读到数组里。
如果输入的内容过多就无法处理的字符都留在输入缓冲区里等下次读取。
例子:
运行结果:
fgets函数的问题当 我们输完字符串后会按回车字符,回车字符也会保存到字符串中,其实输入了4个字符
例子: 如果输入的内容过多就无法处理的字符都留在输入缓冲区里等下次读取。
运行结果:
在每次使用fgets函数从键盘得到字符串以后,都应该删除输入缓冲区里可能存在的多余数据。
只有确定输入缓冲区里包含多余数据的时候才应该去删除这些多余数据。
可以使用以下两句语句进行删除:
scanf("%*[z^\n]");
scanf("%*c);
例子:
改造上面的语句:当输入字符数组到第九个字符和当输入'\n'字符时才删除
练习:
#include <stdio.h>
#include <string.h>
int *myatoi(const char *p_ch){
int ret = 0;
const char *p_temp = p_ch;
// while(*p_temp >= '0' && * p_temp<= '9'){
// ret = 10 * ret + *p_temp - '0';
// p_temp++;
// }
while(1){
if(*p_temp >= '0' && * p_temp<= '9'){
ret = 10 * ret + *p_temp - '0';
}
else{
break;
}
p_temp++;
}
return ret;
}
int main(){
char str[10]={0};
printf("请输入字符串:");
fgets(str,10,stdin);
if(strlen(str) == 9 && str[8] != '\n'){
scanf("%*[^\n]");
scanf("%*c");
}
int num = myatoi(str);
printf("数字是%d\n",num);
return 0;
}
运行结果:
练习:
#include <stdio.h>
#include <string.h>
int main(){
char str[30]={0},temp[10]={0};
int grade = 0;
while(1){
printf("请输入一个考试成绩:");
scanf("%d",&grade);
if(grade >= 0 && grade <= 100){
sprintf(temp,"%d,",grade);
strcat(str,temp);
}
else{
break;
}
}
str[strlen(str)-1] = 0;//把最后一个字符','变成'\0'
printf("%s\n",str);
return 0;
}
运行结果: