目录
3.malloc和free函数
3.1malloc函数
3.2free函数
1.初始字符串
C语言中里面没有专门的字符串变量,通常用一个字符数组来存放一个字符串,定义字符串并初始化的方式有下面四种方式:
第一种,在数组里面用单引号将字符一个个写出来:
char str[] = {'h','e','l','l','o'};
第二种,在数组里面使用双引号,在双引号里面写一组字符串:
char str[] = {"hello"};
第三种,在例2的基础上去掉大括号:
char str[] = "hello";
第四种,用指针定义字符串:
char *p = "helloc";
那么方法3和方法4有什么区别呢?我们可以用方法3和方法4定义并初始化一个字符串,然后在后面对字符串里面的内容太进行修改,在输出修改之后的内容看一下。
方法3示例:
#include <stdio.h>
int main()
{
char str[] = "hello";
char *p = "hello";
str[0] = 'H';
printf("字符串str:%s\n",str);
p[0] = 'H';
printf("字符串str1:%s\n",str1);
return 0;
}
说明:当我们需要遍历字符串里面的内容时,不需要使用循环,直接使用占位符“%s”就行了。
运行结果:
最后的运行结果,可以发现最后根本没有输出用指针定义字符串的内容,而字符串str首字符h已经被改成了大写。这是为什么?
是因为字符串str是字符串变量,里面的字符允许修改。而指针变量定义的字符串是字符串常量,里面的字符不允许修改。
2.字符串结束方式
先来看一下这个案例:
打印出不同方式定义字符串字符个数,代码:
#include <stdio.h>
int main()
{
char str[] = {'h','e','l','l','o'};
char str1[] = {"hello"};
char str2[] = "hello";
char *p = "hello";
int size = sizeof(str)/sizeof(str[0]);
int size1 = sizeof(str1)/sizeof(str1[0]);
int size2 = sizeof(str2)/sizeof(str2[0]);
int size3 = sizeof(p)/sizeof(p[0]);
printf("字符串str字符个数:%d\n",size);
printf("字符串str1字符个数:%d\n",size1);
printf("字符串str2字符个数:%d\n",size2);
printf("指针定义字符串字符个数:%d\n",size3);
return 0;
}
运行结果:
最后运行结果可以发现,字符串str里面的确有5个字符,最后输出的结果也都是5。但是剩下的字符串str1,str2和用指针定义字符串输出字符个数都不是5,这是为什么呢?
字符串str1,str2的赋值方式比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志’\0’。实际存放情况为:
‘\0’是由 C 编译系统自动加上的。由于采用了‘\0’标志,所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。所以str1和str2比str多了一个字符‘\0’。
但是为什么用指针定义的字符串会是8个了?原有是在window X64以上系统任何一个指针变量都是占8个字节,而p[0]代表一个字符所占字节,所以最终输出的个数是8。
3.malloc和free函数
3.1malloc函数:
malloc函数原型为 void *malloc(size_t size) ,是一个无类型的指针函数,分配所需的内存空间,并返回一个指向它的指针,形参为申请的内存大小。野指针不能直接解引用赋值,现在我们可以用malloc函数先为指针申请空间然后解引用赋值。
示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p = (char *)malloc(1);//需要和指针变量类型一样
*p = 'a';
printf("%c\n",*p);
return 0;
}
运行结果:
使用函数malloc需要包含头文件<stdlib.h>,函数malloc是没有类型,申请内存时,最好要强制转换成和指针变量一个类型。
3.2free函数:
使用malloc开辟空间时,使用完成一定要释放空间,如果不释放会造内存泄漏。这时候需要free函数,函数原型为:void free(void *ptr) 。
示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p = (char *)malloc(1);
if(p == NULL)//判断申请内存是否成功;
{
puts("malloc error");//输出错误;
exit(-1);//退出程序;
}
*p = 'a';
printf("内容:%c\n",*p);
free(p);//释放内存;
p = NULL;//让指针指向NULL,防止野指针;
return 0;
}
运行结果:
在申请完内存以后,应该进行判断防止申请失败。exit退出程序,使用时要包含都头文件<stdlib.h>。free释放之前申请的内存,释放完毕要让指针变量指向NULL(NULL就是系统定义特殊的0,用于指针,初始化的指针指向它,可以防止“野指针”)。
4.字符串常用的函数
1.put和putchar
说明:1.put直接输出字符串,不需要占位符。
2.putchar时输出一个字符。
示例:
#include <stdio.h>
int main()
{
char str[] = "hello";
char c = 'a';
puts(str);
putchar(c);
return 0;
}
2.get和getchar
说明:1.get得到输入字符串,不需要占位符,跟“scanf(“%s”,字符串名);”等价。
2.getchar得到输入一个的字符,用法有点特别。格式为:字符变量名 = getchar();
示例:
#include <stdio.h>
int main()
{
char str[128];
char c;
puts("请输入字符串:");
gets(str);
puts("请输入字符:");
c = getchar();
puts("输出结果:");
puts(str);
putchar(c);
return 0;
}
运行结果:
3.strlen
说明:在前面小节字符串结束方式讲到,字符串字符个数使用关键字sizeof计算,不准确。但可以用函数strlen在一般情况下得到准确字符个数。
示例:
#include <stdio.h>
#include <string.h>//使用关于字符串的函数都需要含头文件<string.h>
int main()
{
char *p = "abcde";
char str1[] = "hello";
char str2[] = "abcdefg";
int len1 = strlen(p);
int len2 = strlen(str1);
int len3 = strlen(str2);
printf("指针p定义字符串长度%d\n",len1);
printf("字符串str1长度:%d\n",len2);
printf("字符串str2长度:%d\n",len3);
return 0;
}
运行结果:
补充:函数strlen是判断是否到达字符串末尾结束字符‘\0’,如果遇到字符‘\0’停止计算字符长度,也就说字符串中间有字符‘\0’,strlen计算出的字符个数不准确。
将上面例子中间加一个字符‘\0’看一下运行结果:
代码:
#include <stdio.h>
#include <string.h>
int main()
{
char *p = "a\0bcde";
char str1[] = "he\0llo";
char str2[] = "abc\0defg";
int len1 = strlen(p);
int len2 = strlen(str1);
int len3 = strlen(str2);
printf("指针p定义字符串长度%d\n",len1);
printf("字符串str1长度:%d\n",len2);
printf("字符串str2长度:%d\n",len3);
return 0;
}
运行结果:
4.strcpy和strncpy
说明:
1.strcpy函数原型为char* strcpy(char* dest, const char *src);功能是将指针src指向的字符串全部复制到指针dest所指向的字符串。
2.strnpy函数原型为char *strncpy(char *dest, const char *src, int n);功能是将指针src指向的字符串前n个字符复制到指针dest所指向的字符串。
示例:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[128];
char str2[128];
char *p = "hello word !";
strcpy(str1,p);
strncpy(str2,p,5);
puts("strcpy:");
puts(str1);
puts("strcnpy:");
puts(str2);
return 0;
}
运行结果:
5.strcat
说明:函数原型char * strcat(char * dest, const char * src);把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除* dest原来末尾的“\0”)。要保证* dest足够长,以容纳被复制进来的*src。
示例:
#include <stdio.h>
#include <string.h>
int main()
{
char *p = " word !";
char str[128] = "hello";
strcat(str,p);
puts(str);
return 0;
}
运行结果:
6.strcmp和strncmp
说明:
strcmp和strncmp的函数原型分别为:**int strcmp(const char *s1,const char *s2); ,int strncmp ( const char * str1, const char * str2, size_t n )。strmp就是比较两个字符串是否相同,相等返回0,不相等返回正整数和负整数。strncmp就是比较前n个字符。
示例:
#include <stdio.h>
#include <string.h>
int main()
{
char *p = "abcdefg";
char *p2 = "abcdefi";
if(!strcmp(p,p2)){
puts("两字符串相同");
}
else{
puts("两字符串不相同");
}
if(!strncmp(p,p2,6)){
puts("两字符串前六个字符相同");
}
else{
puts("两字符串前六个字符不相同");
}
return 0;
}
运行结果:
补充:判断语句里面是整数和负数都代表条件满足,只有0才代表条件不满足。而函数strcmp和strncmp比较两函数,相等时,返回0,带入判断可以用取反运算符。