int main()
{
//1 大{}号法 初始化列表
//数组初始化有2种方法 默认元素个数、指定元素个数
char buf1[] = {'a', 'b', 'c', 'd', 'e'}; //若没有指定长度,默认不分配零
//若指定长度,不够报错;buf长度多于初始化个数,会自动补充零
char buf2[6] = {'a', 'b', 'c', 'd', 'e'};
char buf3[6] = {'a', 'b', 'c', 'd', 'e'};
//char buf4[5] = {'a', 'b', 'c', 'd', 'e'};
printf("buf3:%s", buf3);
system("pause");
}
在C语言中使用字符数组来模拟字符串
C语言中的字符串是以’\0’结束的字符数组
C语言中的字符串可以分配于栈空间,堆空间或者只读存储区
{
//1 用字符串来初始化数组
char buf2[] = {'a', 'b','c','d','\0'};
//2 字符串常量初始化一个字符数组
char buf3[] = {"abcde"}; //结论:会补充零
char buf4[] = "abcde";
char buf5[100] = "abcde";
printf(" strlen(buf5) :%d \n", strlen(buf5));
printf(" sizeof(buf4) :%d \n", sizeof(buf5));
printf(" sizeof(buf4) :%d \n", sizeof(buf4));
}
sizeof与strlen的区别
strlen()求字符串的长度,注意字符串的长度不包含\0
sizeof(类型)字符串类型,的大小,包括\0;
字符数组名,是个指针,是个常量指针;
字符数组名,代表字符数组首元素的地址,不代表整个数组的。
如果代表这个数组,那需要数组数据类型的知识!
//字符串操作方法 数组下标法 指针法
int main()
{
int i = 0;
char buf5[100] = "abcde";
char *p = NULL;
//下标法
for (i=0; i<100; i++)
{
printf("%c", buf5[i]);
}
printf("\n");
//指针法1
for (i=0; i<100; i++)
{
printf("%c", *(buf5+i));
}
//buf5是个指针,是个常量指针
//指针法2
printf("\n");
p = buf5;
for (i=0; i<100; i++)
{
printf("%c", *(p+i));
}
//buf5是个指针,是个常量指针
}
推演过程为:i变0+I, 去[]号加*号
其实本质:指针*p间接寻址,操作内存;
[] 编译器为我们做了*p操作而已
深入理解指针的关键是什么?
一维字符串内存模型:两种
void main()
{
char buf[20]= "aaaa"; //定义并且初始化
char buf2[] = "bbbb";
char *p1 = "111111";
char *p2 = malloc(100);
strcpy(p2, "3333");
system("pause");
return ;
}
指针变量可以指向字符常量,但是它所指向内存空间的值不可以修改
指针变量保存着字符常量所在内存空间的地址,所以指针变量可以修改,但是指针变量所指向的内存空间的值不可修改
//*from是指针变量可以被修改,但是它指向的内存空间的值是字符常量,不能被修改
//*to也是指针变量,要想修改它指向的内存空间的值,必须在定义时分配内存空间,并且不能用字符常量初始化
void copy_str01(char *from, char *to)
{
for (; *from!='\0'; from++, to++)
{
*to = *from;
}
*to = '\0';
}
void copy_str02(char *from, char *to)
{
while(*from!='\0')
{
*to++ = *from++;
}
*to = '\0';
}
void copy_str03(char *from, char *to)
{
while( (*to=*from) !='\0')
{
to++;
from++;
}
}
void copy_str04(char *from, char *to)
{
while( (*to++=*from++) !='\0')
{
;
}
}
int copy_str05_good(const char *from, char *to)
{
if (from==NULL || to==NULL)
{
printf("func copy_str05_good() err. (from==NULL || to==NULL)\n");
return -1;
}
while( (*to++=*from++) !='\0')
{
;
}
return 0;
}
//不要轻易改变形参的值, 要引入一个辅助的指针变量. 把形参给接过来.....
int copy_str26_good(char *from , char *to)
{
char *tmpfrom = from;
char *tmpto = to;
if ( from == NULL || to == NULL)
{
return -1;
}
while ( *tmpto++ = *tmpfrom++ ) ; //空语句
printf("from:%s \n", from);
}
int main()
{
int ret = 0;
char *from = "abcd";
char buf2[100];
copy_str21(from, buf2);
copy_str22(from,buf2);
copy_str23(from, buf2);
copy_str24(from, buf2);
copy_str25(from ,buf2);
//在被调用函数中输出buf2的正确做法
copy_str26_good(from ,buf2);
//这里输出buf2没有任何问题,那么,如何在被调用函数里输出buf2?
printf("buf2:%s \n", buf2);
}
典型错误知多少
char *str_cnct(char *x, char* y) /*简化算法*/
{
char str3[80];
char *z=str3; /*指针z指向数组str3*/
while(*z++=*x++);
z--; /*去掉串尾结束标志*/
while(*z++=*y++);
z=str3; /*将str3地址赋给指针变量z*/
return(z);
}
修改字符常量结果会如何
Char *p = “abcdefg”;
Modify p[1] = ‘1’;
字符串操作易错
//你往哪里输入数据
int main()
{
char buf[2000];
char *p = NULL;//NULL是字符常量
p = buf;
printf("\n请输入一个字符串:");
scanf("%s", p);
printf("%s", p);
getchar();
getchar();
return 0;
}
快速的上手api是一种能力!
int main00()
{
char buf1[100];
char buf2[200];
strcpy(buf1, "111");
printf("%s", strcat(buf1, "222"));
getchar();
return 0;
}
int main01()
{
char *string1 = "1234567890";
char *string2 = "747DC8";
int length;
//在字符str1中查找,与str2中任意字符有公共交集的位置
length = strcspn(string1, string2);
printf("Character where strings intersect is at position %d\n", length);
getchar();
return 0;
}
//strnset函数有错误
//测试程序修改如下
int main02()
{
char string[] = "abcdefghijklmnopqrstuvwxyz";
char letter = 'x';
printf("string before strnset: %s\n", string);
strnset(string, letter, 13);
printf("string after strnset: %s\n", string);
getchar();
return 0;
}
int main03()
{
char *string1 = "abcdefghijklmnopqrstuvwxyz";
char *string2 = "onm";
char *ptr;
ptr = strpbrk(string1, string2);
if (ptr)
printf("strpbrk found first character: %c\n", *ptr);
else
printf("strpbrk didn't find character in set\n");
getchar();
return 0;
}
int main04()
{
char input[16] = "abc,d";
char *p;
/* strtok places a NULL terminator
in front of the token, if found */
p = strtok(input, ",");
if (p) printf("%s\n", p);
/* A second call to strtok using a NULL
as the first parameter returns a pointer
to the character following the token */
p = strtok(NULL, ",");
if (p) printf("%s\n", p);
getchar();
return 0;
}
//典型的状态函数
int main()
{
char str[] = "now # is the time for all # good men to come to the # aid of their country";
//char delims[] = "#";
char *delims = "#";
char *result = NULL;
result = strtok( str, delims );
while( result != NULL ) {
printf( "result is \"%s\"\n", result );
result = strtok( NULL, delims );
}
printf("----------==========----------\n");
printf("%s", str);
getchar();
return 0;
}
//一级指针的典型用法
//数组 int a[10]
//字符串
//1 C语言的字符串 以零结尾的字符串
//2 在C语言中没有字符串类型 通过字符数组 来模拟字符串
//3 字符串的内存分配 堆上 栈上 全局区 (很重要)
//字符数组 初始化
void main00()
{
//1 指定长度
char buf2[100] = {'a', 'b', 'c', 'd'};
//1-1char buf3[2] = {'a', 'b', 'c', 'd'}; //如果初始化的个数大于内存的个数 编译错误
//1-22//后面的buf2[4]-buf2[99] 0
//2 不指定长度 C编译器会自动帮程序员 求元素的个数
char buf1[] = {'a', 'b', 'c', 'd'}; //buf1是一个数组 不是一个以0结尾的字符串
printf("buf2: %s \n", buf2);
printf("buf2[88]:%d \n", buf2[88]);
printf("hello....\n");
system("pause");
return ;
}
//用字符串 来 初始化字符数组
//strlen() 长度 不包括0
//sizeof() 内存块的大小
void main01()
{
int size = 0;
char buf3[] = "abcd"; // buf3 作为字符数组 应该是5个字节 //作为字符串 应该4个字节
int len = strlen(buf3);
printf("buf3字符的长度:%d \n", len); //4
//buf3 作为数组 数组是一种数据类型 本质(固定小大内存块的别名)
size = sizeof(buf3); //
printf("buf3数组所占内存空间大小:%d \n", size); //5
printf("hello....\n");
{
char buf4[128] = "abcd"; // buf
printf("buf4[100]:%d \n", buf4[100]);
}
system("pause");
return ;
}
//通过数组下标 和 指针
void main02()
{
int i = 0;
char *p = NULL;
char buf5[128] = "abcdefg";
//buf5是一个数组可以用下表取值
for (i=0; i buf5[0+i]; ==> *(buf5+i);
{
//buf5 = buf5 + 1;
//buf5 = 0x11;
}
printf("hello....\n");
system("pause");
}
// buf[]的本质 :和*p 是一样 ,只不过是符合程序员的阅读习惯
// buf 是一个指针, 只读的常量 buf5是一个常量指针 析构内存的时候,保证buf所指向的内存空间安全释放
项目开发字符串模型--strstr-whiledowhile模型
//char *p = "abcd111122abcd3333322abcd3333322qqq";
//求字符串p中 abcd出现的次数
//1请自定义函数接口,完成上述需求 50 // i++ ++ ++
//2自定义的业务函数 和 main函数必须分开 50
void main00()
{
//strstr(str, str2)
int ncount = 0;
//初始化 让p指针达到查找的条件
char *p = "11abcd111122abcd3333322abcd3333322qqq";
do
{
p = strstr(p, "abcd");
if (p != NULL)
{
ncount++; //
p = p + strlen("abcd"); //指针达到下次查找的条件
}
else
{
break;
}
} while (*p != '\0');
printf("ncount:%d \n", ncount);
system("pause");
return ;
}
void main01()
{
int ncount = 0;
//初始化 让p指针达到查找的条件
char *p = "2abcd3333322qqqabcd";
while ( p = strstr(p, "abcd"))
{
ncount ++;
p = p + strlen("abcd"); //让p指针达到查找的条件
if (*p == '\0')
{
break;
}
}
printf("ncount:%d \n", ncount);
printf("hello...\n");
system("pause");
}
//char *p = "abcd111122abcd3333322abcd3333322qqq";
//求字符串p中 abcd出现的次数
//1请自定义函数接口,完成上述需求 50 // i++ ++ ++
//2 自定义的业务函数 和 main函数必须分开 50
int getCount(char *mystr /*in*/, char *sub /*in*/,int *ncount)
{
int ret = 0;
int tmpCount = 0;
//初始化 让p指针达到查找的条件
char *p = mystr; //不要轻易改变形参的值
if (mystr==NULL || sub==NULL ||ncount==NULL)
{
ret = -1;
printf("func getCount() err:%d (mystr==NULL || sub==NULL ||ncount==NULL) \n", ret);
return ret;
}
do
{
p = strstr(p, sub);
if (p != NULL)
{
tmpCount++; //
p = p + strlen(sub); //指针达到下次查找的条件
}
else
{
break;
}
} while (*p != '\0');
*ncount = tmpCount; //间接赋值是指针存在的最大意义
return ret;
}
int main03()
{
int ret = 0;
char *p = "abcd111122abcd3333322abcd3333322qqq";
int count = 0;
char sub[] = "abcd";
ret = getCount(p,sub, &count);
if (ret != 0)
{
printf("func getCount() err:%d \n", ret);
return ret;
}
ret = getCount(p,NULL, &count);
if (ret != 0)
{
printf("func getCount() err:%d \n", ret);
return ret;
}
printf("count:%d \n", count);
system("pause");
}