字符串基础 String
STR-1 字符串字面量
在C源代码中,以双引号""
括起来的内容是字符串字面量(或称字符串常量)。
编译器读取双引号中的内容,并在结尾处自动添加一个\0
字符,将其一并作为字符串字面量存储在内存中。准确来说,这种存储是字符串字面量的静态static
类型存储,不会受到函数调用、作用域等的影响。
在程序运行时,字符串字面量就已经完成存储,在程序中出现的"string"
实际上被立即看做是一个指向了字符串首字符位置的指针量。因此,可以这样使用字符串字面量:
const char *p = "Hello,world!";
printf("the first char is %c, string is \"%s\", pvalue is %p\n",*p,p,p);
printf("print by string literal:%s","Hello,world!");
在字符串内使用"
时需要加上反斜杠\"
"Hello,world!"
在此处被视作一个指针量,于是我们声明了一个const char *
类型的指针,使其指向首字符'H'
。对p
解引用得到'H'
,,用%s
格式化输出的是整个字符串(在字符串结尾的\0
处结束打印)。此外,我们还可以观察其存储地址。因此,输出是:
the first char is H, string is "Hello,world!", pvalue is 0x1027e3f4c
print by string literal:Hello,world!
注意到此处使用了const char *p = "Hello,world!";
来声明了一个指向常量的指针。这是因为字符串字面量本就是一个const
对象,将指针声明为const char *
以避免尝试修改字符串。如果尝试通过指针来修改字符串字面量,其结果是未定义的。
但是我们可以使用数组来储存字符串,并随心所欲地进行修改。
STR-2 数组中的字符串
用数组同样可以储存一个字符串,优点是,可以按需对其进行修改。
char str_array[20] = "just string";
printf("%s\n",str_array);
str_array[0] = 'J';
printf("%s\n",str_array);
输出:
just string
Just string
按理来说一个数组的初始化应当是char str_array[30] = { }
,但我们也可以直接用字符串字面量的形式进行初始化。这样做的原理实质是:将静态static
存储的字符串内容逐个拷贝到数组str_array
中。因此,现在内存中有了两个副本:一个是只读的字符串字面量,另一个是在一个数组中存储的字符串。字符串字面量的内容依旧是不允许修改的,但是我们可以像一个正常的数组那样去修改数组中的字符串。
那么,这个str_array[20]
中到底有哪些内容?首先字符串字面量"just string”
以及结尾自动添加的'\0'
被复制进字符数组。(因此,在声明字符数组中一定要确保数组能容纳这个\0
!)之后数组里还有空位,为确保安全会将剩余的位置一并初始化为'\0'
。
如果是让编译器自行确定数组长度会方便许多。
char str_array[] = "just string";
STR-3 字符串数组
如果创建一个指针数组来同时访问多个字符串字面量会很方便:
const char *p_array[5] = {"blue","green","white","black","red"};
for(int i=0;i<5;i++)
printf("My favourite color is %s.\n",p_array[i]);
输出如下
My favourite color is blue.
My favourite color is green.
My favourite color is white.
My favourite color is black.
My favourite color is red.
可不可以不使用指针数组,而是用一个二维char
数组来储存所有这些字符串呢?
char matrix [5][10] = {"blue","green","white","black","red"};
for(int i=0;i<5;i++)
printf("My favourite color is %s.\n",matrix[i]);
这样做得到的结果虽然相同,但是使用一个二维数组来存放字符串会额外浪费大量的空间,并且所有字符串的长度都必须小于二维数组的列数。所以,使用指针数组明显是更好的选择。
STR-4 字符串与指针
字符串和指针的结合使用可以带来许多的便利。下面举两个简单的例子:
使用一个指针进行遍历,寻找一个字符串中元音字母(a,e,i,o,u)出现的次数(此处只考虑小写)。
#include <stdio.h>
int count_aeiou(const char *p);
int main(void){
printf("%d",count_aeiou("this function count my aeiou."));
return 0;
}
int count_aeiou(const char *p){
int count = 0;
while(*p != '\n' && *p != '\0'){
if(*p == 'a' ||*p =='e' ||*p == 'i' ||*p == 'o' ||*p == 'u' )
count++;
p++;
}
return count;
}
输出11
。
在一个句子中寻找最长的那个单词:
#include <stdio.h>
const char * findlongword(const char *s);
int main(void){
char array[] = "Life is the art of drawing sufficient conclusions form insufficient premises.";
char * ptr = findlongword(array);
char * s = ptr;
while(*s != ' ' && *s != ',' && *s != '.'&& *s != '\n' && *s != '\0')
s++;
*s = '\0';
printf("longest word in \"Life is the art of drawing sufficient conclusions form insufficient premises.\" is %s.\n",ptr);
return 0;
}
const char * findlongword(const char *s){
const char *p = NULL;
int count=0,max=0;
while(*s != '\n' && *s != '\0'){
while(*s == ' ' || *s == ',' || *s == '.')
s++;
while(*s != ' ' && *s != ',' && *s != '.'&& *s != '\n' && *s != '\0'){
count++;
s++;
}
if(count > max){
max = count;
p = s-count;
}
count = 0;
}
return p;
}
输出为:
longest word in "Life is the art of drawing sufficient conclusions form insufficient premises." is insufficient.
本系列博客为我本人原创的学习笔记,尽量勤更新,如有错误欢迎各位大佬指出,Thanks♪(・ω・)ノ