C语言中的字符串

简介 C风格的字符串其实就是特殊的 char 数组。特殊在于,数组中至少有一个 ‘’ (其ASCII码值为0)空字符元素来作为字符串结束的标志。否则,这个数组只能看做是字符数组,而不能看做是字符串。C处理字符串的标准库string.h,以及其他的字符串处理函数,都建立在这种约定上,所以如果不满足这种约定,则它们不能正确工作。 例如 "C Language"是一个字符串常量,或者叫字符串字面值。它有9个英文字母和1个空格,但它占用11个字节,因为编译器自动在它末尾添加’‘作为字符串结束标志。也就是说不管是程序员,还是编译器,都遵守这样一个规则:C语言字符串以’'结尾。 C L a n g u a g e 


小编分类整理了许多C语言进阶学习材料和BAT面试题,需要资料的请进Q群:731611386免费领取

下面通过例子说明’'对字符串的重要意义以及字符串和字符数组的差别。


空字符串

空字符串的类型是char[1],如

char empty_str1[1] = “”; 类型是:const char[1]

char empty_str2[1] = {’’} 类型是:char[1]

字符串字面值

直接书写的,用双引号表示的就是字符串字面值。形如 “hello” 这样的叫做字符串字面值,或者字符串文字常量。它是字符串,但与普通的数组存储的字符串相比有一些其他的特性。

ANSI C声明:修改一个字符串字面值的后果是未定义的,因此现在的编译器都不允许程序员修改字符串字面值的内容。像下面的代码是不允许的,即便编译通过,也会发生运行时错误。


小编分类整理了许多C语言进阶学习材料和BAT面试题,需要资料的请进Q群:731611386免费领取
ANSI C这样做的一个好处是:程序中使用相同内容的字符串字面值的可能会共享同一个字符串内存数据实体,以避免内存的浪费。

下面两处使用了相同的字符串字面值,好的编译器会仅仅存储一份 "hello"实体在内存中,而指针s 和 msg指向相同的字符串去使用他们。

ANSI C这样做的一个好处是:程序中使用相同内容的字符串字面值的可能会共享同一个字符串内存数据实体,以避免内存的浪费。


小编分类整理了许多C语言进阶学习材料和BAT面试题,需要资料的请进Q群:731611386免费领取

其次,当字符串字面值作为右值使用时,那么表达式的值就是这个字符串字面值存储在内存中的起始地址,即第一个字符在内存中的地址。

char* p = “hello”;

putchar(*p); //打印出:h

再者,字符串字面值是存放在内存的静态存储区的,静态区的数据从程序载入内存运行,到程序结束都一直存在,因此,像下面的代码是合法有效的:即从函数返回一个字符串字面值(实质上是这个字符串在内存中的地址),并不会因为函数执行完而将字符串字面值析构掉。

#include<stdio.h>

char* foo()

{

return “hello world”;

}

int main(int argc, char *argv[])

{

char *msg = foo();

printf(msg);

}

标准库中的字符串函数

以下的字符串函数大多都定义在string.h中。给出的实现源代码从linux2.6内核中提取,仅供参考。

size_t strlen( const char *str );

一种可能的实现方式:

size_t strlen(const char * s)

{

const char *sc;

for (sc = s; *sc != '\0'; ++sc)

    /* nothing */;

return sc - s;

1

2

3

}

返回一个字符串的长度。字符串str必须以’\0’结尾。

char* strcpy( char* dest, const char* src );

一种可能的实现方式:

char * strcpy(char * dest,const char *src)

{

char *tmp = dest;

while ((*dest++ = *src++) != '\0')

    /* nothing */;

return tmp;

1

2

3

}

将src的字符( 包括末尾的\0’)拷贝到des中去。

dest字符串必须保证至少有 strlen(src) +1 的空间。

如果des的容量不足以容纳src的全部字符和末尾的\0,则结果未定义。

如果des 和src内存发生重叠,则结果未定义

char *strncpy( char *dest, const char *src, std::size_t count );

示例:

char * strncpy(char * dest,const char *src,size_t count)

{

char *tmp = dest;

while (count) {

    if ((*tmp = *src) != 0) src++;

    tmp++;

    count--;

}

return dest;

1

2

3

4

5

6

}

将字符串src中最多count个字符拷贝到 dest中。返回字符串dest。

理想的情况是: count==strlen(src) +1

1、如果count 小于 src的长度 +1,则dest将不会以’\0’结尾。

2、如果 count 大于 src 的长度 +1 ,则在完全拷贝src之后,继续在dest后面追加’\0’,直到总共拷贝 count 个 字符到 dest

dest 和 src的内存块不能重叠,否则结果未定义。

int strcmp( const char *lhs, const char *rhs );

示例:

int strcmp(const char * cs,const char * ct)

{

register signed char __res;

while (1) {

    if ((__res = *cs - *ct++) != 0 || !*cs++)

        break;

}

return __res;

1

2

3

4

5

6

}

按照字典顺序(ASCII表)比较2个字符串。总之,如果第一个字符串“大于”第二个字符串,则返回一个正数,如果第一个字符串“小于”第二个字符串,则返回一个负数,如果2个字符串一样,则返回0。

2个字符串必须i是以’\0’结尾的。

如果2个字符串完全相同,则返回0。

如果在循环比较的某个索引位置上,前者lhs的字符“小于”rhs的字符,则返回一个负数。

如果在循环比较的某个索引位置上,前者lhs的字符“大于”rhs的字符,则返回一个正数。

int strncmp( const char *lhs, const char *rhs, size_t count );

和strcmp一样,只不过它最多比较count个连续的字符。

2个字符串必须i是以’\0’结尾的。

count如果过大,使得strncmp在比较过程中访问了超出字符串所在的数组的空间则是未定义的。

char *strcat( char *dest, const char *src );

一种可能的实现方式:

char * strcat(char * dest, const char * src)

{

char *tmp = dest;

while (*dest)

    dest++;      //退出循环后,dest指向目标字符串末尾的'\0'

while ((*dest++ = *src++) != '\0')  //拷贝,直到遇到src中的'\0'

    ;

return tmp;

1

2

3

4

5

6

7

}

将字符串src追加到字符串dest的末尾,返回新的字符串dest的指针 。2个字符串必须i是以’\0’结尾的。

用src[0]替换dest中的原来的用于指示字符串末尾的’\0’,且最终dest依然是以’\0’结尾。

如果dest所在的数组无法容纳原来dest中的字符个数+src的字符个数+1,则结果未定义。

如果dest和是src内存重叠,则结果未定义。

小编分类整理了许多C语言进阶学习材料和BAT面试题,需要资料的请进Q群:731611386免费领取

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容