字符串在C中是比较特殊的一类数据类型,学习时候总感觉和其他数据类型有区别。然后最近在看视频和查资料的时候总结一下。
1.字符串定义
之前对字符串初始化都是似懂非懂的,这里做个总结。
1.1字符串初始化
- C中字符串 是以0结尾的字符串
- C中没有字符串类型,可以通过字符数组来模拟字符串。也就是说只有char,没有string。
int main(void)
{
char p1[] = { 'c','u','o' };
char p2[] = { 'w','e','t','\0' };
char p3[] = "hello";
char p = '3';
printf("%c\n", p);
printf("%s\n", p2);
printf("%s\n", p3);
printf("hello\n");
system("pause");
}
上面列出是比较常见的几种声明方式。
- 首先,p1这种方法都编译通过,但是不能打印出来,就算打印了也是不正确的字符。必须后面加个’\0’。
- 最最常见是p3声明方式。
- 还有就是字符串只有一个可见字符时只能单引号,而且输出用%c,而不是%s
1.2字符串和字符数组
char p[] = "hello";
char *p1 = "hello";
这两个都是指向同个字符串。
但是 p是字符数组 --------------p1是指针。
还有一点要注意,p1是常量指针,不能被修改。
也就是说不能执行以下操作:
char p[] = "hello";
p = p + 1;
编译器会报错,因为在释放指针内存时,要保证完整。
发现一篇博客写的很好:字符串
这位大哥总结的很完整。
1.3strlen()和sizeof()
#include "stdio.h"
int main(void)
{
char a[] = "abcd";
printf("%5d", strlen(a));
printf("%5d", sizeof(a));
system("pause");
return 0;
}
这里我们可以看到:
- strlen()长度不包括0
- sizeof()是内存的大小,包括0
2.字符串基本操作
2.1字符串遍历
字符串遍历有三种方式,其本质其实是一样的。
#include "stdio.h"
int main(void)
{
char a[] = "asdsfjklg";
char *p = NULL;
int i = 0;
p = a;
for (i = 0; i < strlen(a);i++)
{
printf("%5c", a[i]);
}
for (i = 0; i < strlen(a); i++)
{
printf("%5c", *(p + i));
}
for (i = 0; i < strlen(a); i++)
{
printf("%5c", *(a + i));
}
printf("\n");
printf("hello\n");
system("pause");
return 0;
}
第一种是我们最常见的遍历,但是第二种才是编译器的理解,所以按照第二种写效率会更高。
从这个例子可以知道其实 *和[]是一样的,只是表现形式不一样。
2.2字符串的拷贝(包括传参)
#include "stdio.h"
int main(void)
{
char a[] = "hsdkjfj";
char b[123];
int i = 0;
for (; *(a + i) != '\0'; i++)
{
*(b + i) = *(a + i);
}
b[i] = '\0';
printf("%s\n", b);
printf("hello\n");
system("pause");
return 0;
}
这是不传参的,要注意for里面的判断条件,当然也可以写a[i] !=’\0’。
还有不要忘了在最后加个\0,不然会出错。
#include "stdio.h"
int StrCopy(char *a, char *b)
{
char *from = NULL;
char *to = NULL;
from = a;
to = b;
if (from == NULL || to == NULL )
{
return;
}
int i = 0;
for (; *(a + i) != '\0';)
{
*(b++) = *(a++);
}
*(b + i) = '\0';
return 0;
}
int StrCopy1(char *a, char *b)
{
char *from = NULL;
char *to = NULL;
from = a;
to = b;
if (from == NULL || to == NULL)
{
return;
}
int i = 0;
while ((*to = *from) != '\0')
{
to++;
from++;
}
return 0;
}
int StrCopy2(char *a, char *b)
{
char *from = NULL;
char *to = NULL;
from = a;
to = b;
if (from == NULL || to == NULL )
{
return;
}
int i = 0;
while((*to ++ = *from++) != '\0')
{
;
}
return 0;
}
int main(void)
{
char *a = "nidwqej";
char b[100];
int ret = 0;
ret = StrCopy2(a, b);
if (ret != 0)
{
printf("ERROR\n");
}
printf("%s\n", b);
printf("hello\n");
system("pause");
return 0;
}
上面有三种不同拷贝方法,都需要学习,对提高代码编写能力有提高。
2.3要注意的问题
刚刚上面代码最好每个形参过来,在每个被调函数里面再申明变量把形参接过来,尽量不要去改变形参的值。
比如:
int StrCopy1(char *a, char *b)
{
int i = 0;
while ((*b= *a) != '\0')
{
b++;
a++;
}
printf("%s",a);
return 0;
}
这样会出问题的,因为a的指向一直在变,到最后是不能得到相应结果的。