【C】虽然以天记数但是实际上不定期更新的第2天:字符串基础 String

字符串基础 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♪(・ω・)ノ

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值