字符串
1、字符串就是一个字符数组
2、一般用指针的方式定义字符串
- char *p = “hello world!”;
定义方式:
第一种定义方式
char c = ‘A’;
- 定义单个字符
char str[5] = {‘a’,‘b’,‘c’,‘d’,‘e’};
- 定义字符串
- 类比于整数数组
#include <stdio.h>
int main()
{
int i = 10;
int a[3] = {13,46,78};
char c = 'A';
char str[5] = {'a','b','c','d','e'};//类比于整数数组
for(i=0;i<sizeof(str)/sizeof(str[0]);i++){
printf("%c ",str[i]);
}
system("pause");
return 0;
}
第二种定义方式
char str[5] = “abcde”;
- 定义字符串
#include <stdio.h>
int main()
{
int i;
char str[5] = "abcde";
for(i=0;i<sizeof(str)/sizeof(str[0]);i++){
printf("%c ",str[i]);
}
system("pause");
return 0;
}
第三种定义方式
char str[] = “abcdefghijkrst”;
- 字符数组元素个数不写,会根据真实大小来默认分配
#include <stdio.h>
int main()
{
int i;
char str[] = "abcdefghijkrst";
for(i=0;i<sizeof(str)/sizeof(str[0]);i++){
printf("%c ",str[i]);
}
putchar('\n');
system("pause");
return 0;
}
第四种定义方式,指针
1、数组名就是地址(多数情况下)
2、指针方式,如果操作不对(内存非法),容易造成段错误 sigment error
3、字符串用格式占位符%s表示,不需要 i 的下标历遍
- printf("%s\n",pstr);
#include <stdio.h>
int main()
{
//数组名就是地址(多数情况下)
char *pstr = "hello world!\n this is str"; //指针方式,如果操作不对(内存非法),容易造成段错误 sigment error
printf("%s\n",pstr);//字符串用格式占位符%s表示,不需要i的下标历遍
system("pause");
return 0;
}
字符串的存储方式
整型数组的存储方式
int a[3] = {1,3,5};
int a[] = {1,24,6};
- 连续的空间,整个数组的大小是:数组元素个数乘以元素类型大小
整型数组存储空间计算
#include <stdio.h>
int main()
{
int a[3] = {1,24,6};
printf("a数组的大小是:%d\n",sizeof(a));
printf("数组的元素大小是:%d\n",sizeof(a[0]));
printf("数组的元素大小是:%d\n",sizeof(int));
printf("数组的个数是:%d\n",sizeof(a)/sizeof(a[0]));
system("pause");
return 0;
}
执行结果:
a数组的大小是:12
数组的元素大小是:4
数组的元素大小是:4
数组的个数是:3
字符串存储方式
char b[3] = {‘z’,‘b’,‘a’};
- 连续的空间,整个数组的大小是:数组元素个数乘以元素类型大小
char d[] = “afg”;
- 字符串在内存中,除了有效字符afg以外,还会自动在末尾补一个 ‘\0’ 作为字符串的结束标志
字符串存储空间计算
第一种定义方式
- char b[3] = {‘z’,‘b’,‘a’};
#include <stdio.h>
int main()
{
char b[3] = {'z','b','a'};
printf("b数组的大小是:%d\n",sizeof(b));
printf("数组的元素大小是:%d\n",sizeof(b[0]));
printf("数组的元素大小是:%d\n",sizeof(char));
printf("数组的个数是:%d\n",sizeof(b)/sizeof(b[0]));
system("pause");
return 0;
}
执行结果:
b数组的大小是:3
数组的元素大小是:1
数组的元素大小是:1
数组的个数是:3
第二种种定义方式
- char c[3] = “afg”;
#include <stdio.h>
int main()
{
char c[3] = "afg";
printf("c数组的大小是:%d\n",sizeof(c));
printf("数组的元素大小是:%d\n",sizeof(c[0]));
printf("数组的元素大小是:%d\n",sizeof(char));
printf("数组的个数是:%d\n",sizeof(c)/sizeof(c[0]));
system("pause");
return 0;
}
执行结果:
c数组的大小是:3
数组的元素大小是:1
数组的元素大小是:1
数组的个数是:3
第三种种定义方式
- char c[] = “afg”;
- 不写时,数组的大小会根据初始化的时候,元素的个数来确定
#include <stdio.h>
int main()
{
char d[] = "afg";
//不写时,数组的大小会根据初始化的时候,元素的个数来确定
printf("d数组的大小是:%d\n",sizeof(d));
printf("数组的元素大小是:%d\n",sizeof(d[0]));
printf("数组的元素大小是:%d\n",sizeof(char));
printf("数组的个数是:%d\n",sizeof(d)/sizeof(d[0]));
//结果是4,是因为多了一个字符,'\0' 代表字符串的结束标志
//当printf使用这个字符串时,会去找这个停止符,找到就停止打印,找不到就一直找下一个 '\0'
system("pause");
return 0;
}
执行结果:
d数组的大小是:4
数组的元素大小是:1
数组的元素大小是:1
数组的个数是:4
1、结果是4,是因为多了一个字符,’\0’ 代表字符串的结束标志
2、当printf使用这个字符串时,会去找这个停止符,找到就停止打印,找不到就一直找下一个 ‘\0’
测试停止符
#include <stdio.h>
int main()
{
char a[] = "afg";
int i = 0;
while(a[i] != '\0'){
printf("%c",a[i]);
i++;
}
putchar('\n');
system("pause");
return 0;
}
执行结果:
afg
计算字符串中字符的个数
sizeof函数
strlen函数
它在计算字符串大小时,遇到 ‘\0’ 后,就结束计数了
#include <stdio.h>
int main()
{
int a[] = {1,2,3};
printf("数组a的元素个数是:%d\n",sizeof(a)/sizeof(a[0]));
char b[] = "hello";
printf("数组b的元素个数是:%d\n",sizeof(b)/sizeof(b[0]));
system("pause");
return 0;
}
执行结果:
数组a的元素个数是:3
数组b的元素个数是:6
有填数组大小
#include <stdio.h>
int main()
{
char a[128] = "hello";
printf("数组b的元素个数是:%d\n",sizeof(a)/sizeof(a[0]));
printf("%s\n",a);
system("pause");
return 0;
}
执行结果:
数组a的元素个数是:128
hello
所以不能用sizeof来计算字符串中有效字符的格式,应该用strlen函数
用strlen函数计算字符串大小
#include <stdio.h>
int main()
{
char a[128] = "hello";
printf("数组a的元素个数是:%d\n",sizeof(a)/sizeof(a[0]));
printf("数组a用strlen计算元素个数是:%d\n",strlen(a));
printf("数组a字符串的内容是:%s\n",a);
system("pause");
return 0;
}
执行结果:
数组a的元素个数是:128
数组a用strlen计算元素个数是:5
数组a字符串的内容是:hello
字符串操作常用函数
输出字符串
puts();
- 会在输出字符串末尾自动加一个 ‘\n’
printf("%s",str);
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "hello world!";
puts(str);
printf("%s\n",str);
system("pause");
return 0;
}
执行结果:
hello world!
hello world!
获取字符串
gets();
scanf("%s",str);
通过字符数组开辟空间存储输入字符串:
#include <stdio.h>
#include <string.h>
int main()
{
char pstr[128] = {'\0'};
//开辟了128个字节的内存空间,并初始化给所有开辟的内存空间赋值为 '\0'
printf("请输入字符串:\n");
scanf("%s",pstr);
puts(pstr);
system("pause");
return 0;
}
通过指针开辟空间存储输入字符串:
如果野指针没有开辟内存空间,就去存储输入的字符串,会造成非法内存访问,会出现段错误。CMD窗口闪退
#include <stdio.h>
#include <string.h>
int main()
{
char *pstr = NULL;
pstr = (char *)malloc(128);
printf("请输入字符串:\n");
scanf("%s",pstr);
puts(pstr);
system("pause");
return 0;
}
gets函数使用
从键盘上获取输入的字符串,给到开辟的内存空间
#include <stdio.h>
#include <string.h>
int main()
{
char *pstr = NULL;
pstr = (char *)malloc(128);
printf("请输入字符串:\n");
gets(pstr);
//从键盘上获取输入的字符串,给到开辟的内存空间
puts(pstr);
system("pause");
return 0;
}
计算字符串长度
strlen(str);
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "hello world!";
printf("str字符串长度为:%d\n",strlen(str));
system("pause");
return 0;
}
执行结果:
str字符串长度为:12
初始化开辟的内存空间
void *memset(void *s, int ch, size_t n);
s 为初始化对象
ch 初始化成什么字符
n 初始化多大内存空间
关联函数malloc函数注意:
1、一但用了 malloc 开辟内存空间后,一定要注意内存泄漏的问题
free(void *str);
str = NULL;
2、malloc 可能会开辟失败,要对返回值做判断
memset函数配套应用:
#include <stdio.h>
#include <string.h>
int main()
{
char *pstr = NULL;
pstr = (char *)malloc(128);
//malloc 可能会开辟失败,要对返回值做判断
if(pstr == NULL){
printf("申请内存空间失败!\n");
exit(-1);
}
memset(pstr, '\0', 128);
//把每个元素初始化为 '\0'
printf("请输入字符串:\n");
scanf("%s",pstr);
puts(pstr);
free(pstr);
pstr = NULL;
system("pause");
return 0;
}
字符串拷贝
char *strcpy(char *dest, const char *src);
dest 需要复制到的内存空间
src 需要复制的内容
strcpy拷贝函数应用:
#include <stdio.h>
#include <string.h>
int main()
{
char *strSrc = "hello world!";
char strDest[128] = {'\0'};
strcpy(strDest,strSrc);
printf("复制到Dest的字符串:%s\n",strDest);
memset(strDest, '\0', sizeof(strDest)/sizeof(strDest[0]));
//一般从新复制进去,是没有问题的
//但保险起见,需要对要复制到的空间进行初始化清零
strcpy(strDest,"yangyingchun");
puts(strDest);
system("pause");
return 0;
}
char *strncpy(char *destinin, char *source, int maxlen);
destinin 需要复制到的内存空间
source 需要复制的内容
maxlen 需要复制多少内容
strncpy拷贝函数应用:
#include <stdio.h>
#include <string.h>
int main()
{
//char *strcpy(char *dest, const char *src);
char *strSrc = "hello world!";
char strDest[128] = {'\0'};
strcpy(strDest,strSrc);
printf("复制到Dest的字符串:%s\n",strDest);
memset(strDest, '\0', sizeof(strDest)/sizeof(strDest[0]));
strncpy(strDest,"yangyingchun", 4);
puts(strDest);
system("pause");
return 0;
}
通过指针应用拷贝函数:
#include <stdio.h>
#include <string.h>
int main()
{
char *strSrc = "hello world!";
char *strDest = NULL;
strDest = (char *)malloc(128);
if(strDest == NULL){
printf("申请内存空间失败!\n");
exit(-1);
}
memset(strDest, '\0', 128);
strcpy(strDest,strSrc);
printf("复制到Dest的字符串:%s\n",strDest);
free(strDest);
strDest = NULL;
system("pause");
return 0;
}
字符拼接
strcat(test,src);
- test 需要拼接到的内存空间
- src 需要追加的内容
#include <stdio.h>
#include <string.h>
int main()
{
char *strSrc = "hello world!";
char test[128] = "yangyingchun ";
strcat(test,strSrc);
puts(test);
system("pause");
return 0;
}
字符串的比较
int strncmp(const char *str1, const char *str2)
参数:
- str1-- 要进行比较的第一个字符串。
- str2-- 要进行比较的第二个字符串。
返回值:
- 如果返回值 < 0,则表示 str1 小于 str2。
- 如果返回值 > 0,则表示 str2 小于 str1。
- 如果返回值 = 0,则表示 str1 等于 str2。
案例应用:
#include <stdio.h>
#include <string.h>
int main()
{
char *str1 = "1234";
char *str2 = "1234";
int ret = strcmp(str2,str1);
printf("ret = %d\n",ret);
if(!strcmp(str1,str2)){
printf("两个字符串一样!\n");
}
system("pause");
return 0;
}
字符串的查找
单个字符在字符串中的查找
函数原型:
char *strchr(const char *str, char c);
参数:
str-- 要被检索的 C 字符串。
c-- 在 str 中要搜索的字符。
功能:
在参数str所指向的字符串中搜索第一次出现字符c(一个无符号字符)的位置。
返回值:
返回一个指向该字符串中第一次出现的字符的指针,如果字符串中不包含该字符则返回NULL空指针。
头文件:
#include <string.h>
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "yangyingchun";
char c = 'c';
char *p = NULL;
p = strchr(str,c);
if(p == NULL){
printf("未找到字符%c\n",c);
}else{
printf("找到字符%c:",c);
puts(p);
}
system("pause");
return 0;
}
执行结果:
找到字符c:chun
多个字符(字符串)在字符串中的查找
函数原型:
char *strstr(char *str1, const char *str2);
语法:
char* strstr(str1,str2)
str1: 被查找目标
str2: 要查找对象
**返回值:**若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "yangyingchun";
char *p = NULL;
char *subStr = "ch";
p = strstr(str,subStr);
if(p == NULL){
printf("未找到字符串%s\n",subStr);
}else{
printf("找到字符串%s:",subStr);
puts(p);
}
system("pause");
return 0;
}
执行结果:
找到字符串ch:chun
将字符串中字母转换大小写
将字符串中字母转为小写
函数原型:
char *strlwr(char *s);
头文件:
#include <string.h>
功能:
将字符串s参数转换为小写形式
说明:
只转换s参数中出现的大写字母,不改变其它字符。返回指向s参数的指针。
兼容性说明:
strlwr和strupr不是标准C库函数,只能在VC中使用。linux gcc环境下需要自行定义这个函数。
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "YangYingChun";
//windows环境下,要定义成数组的形态,否则程序会崩溃。linux环境下是可以定义成指针变量的
puts(strlwr(str));
system("pause");
return 0;
}
执行结果:
yangyingchun
将字符串中字母转为大写
函数原型:
char *strupr(char *s);
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "YangYingChun"; //windows环境下,要定义成数组的形态,否则程序会崩溃。linux环境下是可以定义成指针变量的
puts(strlwr(str));
puts(strupr(str));
system("pause");
return 0;
}
执行结果:
yangyingchun
YANGYINGCHUN
字符串的切割
函数原型:
char *strtok(char s[], const char *delim);
s为要分解的字符串
delim为分隔符字符串。(如果传入字符串,则传入的字符串中每个字符均为分割符)。
功能:
分解字符串为一组字符串。
首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。
p = strtok(s,",");
- 第一次调用
p = strtok(NULL,",");
- 第二次调用
返回值:
1、从s开头开始的一个个被分割的串。当s中的字符查找到末尾时,返回NULL。
2、如果查找不到delim中的字符时,返回当前strtok的字符串的指针。
3、所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
例如:
strtok(“abc,def,ghi”,",");
最后可以分割成为
abc
def
ghi
尤其在点分十进制的IP中提取应用较多。
基础案例方法应用:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "Yang Ying Chun";
//windows环境下,要定义成数组的形态,否则程序会崩溃。linux环境下是可以定义成指针变量的
char *p = NULL;
p = strtok(str," ");
if(p != NULL){
printf("获取到的第一个字符串p=%s\n",p);
}
//获取第二个字符串的方式跟第一次不同,需要把目标字符串(str)改成NULL
p = strtok(NULL," ");
printf("获取到的第二个字符串p=%s\n",p);
p = strtok(NULL," ");
printf("获取到的第三个字符串p=%s\n",p);
system("pause");
return 0;
}
执行结果:
获取到的第一个字符串p=Yang
获取到的第二个字符串p=Ying
获取到的第三个字符串p=Chun
优化切割方式:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "Yang Ying Chun hello world!";
char *p = NULL;
int cnt = 1;
p = strtok(str," ");
if(p != NULL){
printf("获取到的第%d个字符串p=%s\n",cnt++,p);
}
while(1){
p = strtok(NULL," ");
if(p != NULL){
printf("获取到的第%d个字符串p=%s\n",cnt++,p);
}else{
printf("没有子串了\n");
break;
}
}
system("pause");
return 0;
}
执行结果:
获取到的第1个字符串p=Yang
获取到的第2个字符串p=Ying
获取到的第3个字符串p=Chun
获取到的第4个字符串p=hello
获取到的第5个字符串p=world!
没有子串了
把切割出的字符串给到指针数组保存
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "Yang Ying Chun hello world!";
char *p = NULL;
int cnt = 0;
char *psubs[10];
p = strtok(str," ");
if(p != NULL){
psubs[cnt] = p;
}
while(1){
cnt++;
p = strtok(NULL," ");
if(p != NULL){
psubs[cnt] = p;
}else{
break;
}
}
int i;
for(i=0;i<cnt;i++){
puts(psubs[i]);
}
system("pause");
return 0;
}
执行结果:
Yang
Ying
Chun
hello
world!
实现API函数操作
puts函数
void myPuts(char *p)//* 字符除了变量声明定义时,都是运算符
{
//字符串明显的特点:结尾有'\0'
while(*p != '\0'){
//putchar(*p++);
printf("%c",*p++);
}
putchar('\n');
}
gets函数
void myGets(char *p)
{
if(p == NULL){
printf("内存非法!");
return;
}
while(*p = getchar()){
if(*p == '\n'){
*p = '\0';
//去掉末尾的回车字符
return;
}else{
p++;
}
}
}
strlen函数
int myStrlen(char *str)
{
int cnt = 0;
while(*str++ != '\0'){
cnt++;
//str++;
}
return cnt;
}
memset函数
#include <stdio.h>
#include <string.h>
int main()
{
char *str = NULL;
str = (char *)malloc(128);
memset(str, 'a', 128);
str[128] = '\0';
puts(str);
system("pause");
return 0;
}
执行结果:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
修改执行函数后:
#include <stdio.h>
#include <string.h>
void myMemset(char *p,char c,int size)
{
while(size){
*p++ = c;
size--;
}
}
int main()
{
char *str2 = NULL;
str2 = (char *)malloc(128);
myMemset(str2, 'v', 128);
str2[128] = '\0';
myPuts(str2);
system("pause");
return 0;
}
执行结果:
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
strcpy,strncpy函数
void myStrcpy(char *dest,char *src)
{
if(dest == NULL || src == NULL){
return NULL;
}
while(*src != '\0'){
*dest++ = *src++;
}
*dest = '\0';
}
void myStrncpy(char *dest,char *src,int n)
{
if(dest == NULL || src == NULL){
return NULL;
}
while(*src != '\0' && 0 < n--){
*dest++ = *src++;
}
*dest = '\0';
}
strcat函数
void myStrcat(char *dest,char *src)
{
if(dest == NULL || src == NULL){
return NULL;
}
while(*dest != '\0'){
dest++;
}
while(*src != '\0'){
*dest++ = *src++;
}
*dest = '\0';
}
strcmp函数
int myStrcmp(char *str1,char *str2)
{
if(str1 == NULL || str2 == NULL){
return NULL;
}
int i;
while(*str1 != '\0'){
if(*str1 == *str2){
i = 0;
}else{
break;
}
str1++;
str2++;
}
if(*str1 != '\0'){
i = 1;
}else if(*str2 != '\0'){
i = -1;
}
return i;
}
实现控制字符串API函数笔记
#include <stdio.h>
#include <string.h>
void myPuts(char *p)//* 字符除了变量声明定义时,都是运算符
{
//字符串明显的特点:结尾有'\0'
while(*p != '\0'){
//putchar(*p++);
printf("%c",*p++);
}
putchar('\n');
}
void myGets(char *p)
{
if(p == NULL){
printf("内存非法!");
return;
}
while(*p = getchar()){
if(*p == '\n'){
*p = '\0';
return;
}else{
p++;
}
}
}
int myStrlen(char *str)
{
int cnt = 0;
while(*str++ != '\0'){
cnt++;
//str++;
}
return cnt;
}
void myMemset(char *p,char s,int size)
{
while(size){
*p++ = s;
size--;
}
}
void myStrcpy(char *dest,char *src)
{
if(dest == NULL || src == NULL){
return NULL;
}
while(*src != '\0'){
*dest++ = *src++;
}
*dest = '\0';
}
void myStrncpy(char *dest,char *src,int n)
{
if(dest == NULL || src == NULL){
return NULL;
}
while(*src != '\0' && 0 < n--){
*dest++ = *src++;
}
*dest = '\0';
}
void myStrcat(char *dest,char *src)
{
if(dest == NULL || src == NULL){
return NULL;
}
while(*dest != '\0'){
dest++;
}
while(*src != '\0'){
*dest++ = *src++;
}
*dest = '\0';
}
int myStrcmp(char *str1,char *str2)
{
if(str1 == NULL || str2 == NULL){
return NULL;
}
int i;
while(*str1 != '\0'){
if(*str1 == *str2){
i = 0;
}else{
break;
}
str1++;
str2++;
}
if(*str1 != '\0'){
i = 1;
}else if(*str2 != '\0'){
i = -1;
}
return i;
}
int main()
{
char *str = "Yang Ying Chun hello world!";
puts(str);
myPuts(str);
char pstr[128] = {'\0'};
myPuts("请输入你的名字:");
myGets(pstr);
myPuts(pstr);
int ret = myStrlen(pstr);
printf("输入的字符串长度为:%d\n",ret);
char *str2 = NULL;
str2 = (char *)malloc(24);
myMemset(str2, 'v', 24);
str2[24] = '\0';
myPuts(str2);
char *src = "yangyingchun hello world!";
char dest[128] = "hello ";
myStrcpy(dest,src);
myPuts(dest);
myStrncpy(dest,src,6);
myPuts(dest);
myStrcat(dest,src);
myPuts(dest);
char *a = "12345";
char *b = "12345";
int ret = myStrcmp(b,a);
printf("ret = %d\n",ret);
system("pause");
return 0;
}