C语言字符串回顾

一、C语言字符串长度(转自http://blog.csdn.net/kstrwind/article/details/8036555

C语言字符串长度的计算是编程时常用到的,也是求职时必考的一项。

C语言本身不限制字符串的长度,因而程序必须扫描完整个字符串后才能确定字符串的长度。

在程序里,一般会用strlen()函数或sizeof来获取一个字符串的长度,但这2种方法获取的字符串的长度其实是不一样,我们用如下函数进行测试:

void test6()  
{  
     char s1[20] = "hello world";  
     char s2[20] = {'h','e','l','l','0',' ','w','o','r','l','d','\0'};  
     char s3[] = "hello\0 world";  
     char s4[] = {'h','e','l','l','0','\0',' ','w','o','r','l','d','\0'};     
  
     printf("%d\t%d\t%d\t%d\n",strlen(s1),strlen(s2),strlen(s3),strlen(s4));
     printf("%d\t%d\t%d\t%d\n",sizeof(s1),sizeof(s2),sizeof(s3),sizeof(s4));
}  
注意,该函数里面定义了4个字符串,基本数据都是“hello world",但需要注意的是,字符串s1和s2给定了字符串数组的大小为20,然后使用2种方式进行赋值;字符串s3和s4是s1和s2对比的字符串,区别就是s3和s4字符串中间插入了一个'\0'。该函数运行的结果如下:


从运行结果可以看出,strlen()函数和sizeof求字符串长度需要注意下面几点:

1. strlen函数求得的字符串长度是从字符串第一个元素到第一个'\0'之间元素的个数(如果字符串中间有'\0',则结果不是整个字符串的长度),同时不包括该'\0'

2. sizeof求得的结果是存储该字符串的变量占用的空间大小,因而一定会包括'\0'.若'\0'后还有空余的空间,也会包含到结果里面

解释(与2种求值方式的实现原理有关):

1. strlen()的一种实现就是遍历字符串,遇到'\0'就终止,因而返回的结果是第一个'\0'前字符元素的个数

2. sizeof 常用来求变量占用内存空间的大小,因而它返回的是存储字符串的变量所占用的内存空间大小,用来求字符串的长度,只在特定情况下可行,即字符数组刚好被一个字符串占满。

二、字符串的输入问题

gets()函数用来从标准输入设备(键盘)读取字符串直到换行符结束,但换行符会被丢弃,然后在末尾添加'\0'字符。
其调用格式为:gets(s); 其中s为字符串变量(字符串数组名或字符串指针)。   
gets(s)函数与scanf函数相似,但不完全相同,使用scanf("%s",&s);函数输入字符串时存在一个问题,就是如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理,但gets()函数将接收输入的整个字符串直到遇到换行为止。

三、C语言字符串处理函数(转自http://blog.csdn.net/ruizeng88/article/details/6677736

1.字符串比较

int strcmp(const char *s1, const char *s2);

比较两个字符串的大小(不忽略大小写),返回值很有学问:如果s1小于s2返回一个小于0的数,如果s1大于s2返回一个大于0的数,如果相等则返回0。返回值是两个字符串中第一个不相等的字符ascii码的差值。实现如下:

int my_strcmp(const char *s1, const char *s2){  
    //important! validate arguments first!  
    assert(NULL !=s1 && NULL != s2);  
    while(*s1 != '\0' && *s2 != '\0' && *s1==*s2){  
        s1++;  
        s2++;  
    }  
    return *s1 - *s2;  
}

注意再函数开始进行参数检查,防止输入参数有NULL时发生运行时错误。

strcmp是最常用的字符串比较函数,一般用法是if(!strcmp(s1, s2)){ ...}。如果不是对整个字符串进行比较而只是比较指定数目的字符串,可以使用函数:

int strncmp(const char *s1, const char *s2, size_t n);

用法和返回值都和strcmp类似,之比较给定字符串的前n个字符,或者到遇到任一字符串结尾。实现如下:

int my_strncmp(const char *s1, const char *s2, size_t n){  
    //important! validate arguments first!  
    assert(NULL!=s1 && NULL!=s2);  
    if(n == 0)  
        return 0;  
    size_t cnt = 1;  
    while(*s1 != '\0' && *s2 != '\0' && *s1==*s2 && cnt < n){  
        s1++;  
        s2++;  
        cnt++;  
    }  
    return *s1 - *s2;  
}
需要注意的除了参数检查外,还要注意n=0的特殊情况,这里我们n=0永远返回0。

还有其他一些带特殊要求字符串比较函数,如:

stricmp,memcmp,memicmp等等,加i表示比较时忽视大小写,带mem的是比较一块内存区间。

2.字符串查找

最简单的是查找字符串查找字符:

char *strchr(const char *s, int c);

至于参数为什么是int,历史遗留问题,这里不多讨论。函数返回在s中找到的第一个c的位置的指针,注意的是,字符串末尾的‘\0’也是可以被查找的。实现如下:

char *my_strchr(const char *s, int n){  
    assert(s != NULL);  
    char c = (char)n;  
    do{  
        if(*s == c)  
            return (char *)s;  
    }while(*s++);  
    return NULL;  
}

还有查找字符串的函数strstr:

char *strstr(const char *s1, const char *s2);

函数返回s2在s1中出现的首字符的位置,实现如下:

char *my_strstr(const char *s1, const char *s2){  
    assert(NULL!=s1 && NULL!=s2);  
    size_t len = strlen(s2);  
    while(*s1){  
        if(!strncmp(s1,s2,len))  
            return (char *)s1;  
        s1++;  
    }  
    return NULL;  
}

c标准库中并没有定义类似strnchr和strnstr的限定查找范围的函数,当然需要的话我们可以自己定义,如:

char *strnstr(const char* s1, const char* s2, size_t n)  
{  
  const char* p;  
  size_t len = strlen(s2);  
  if (len == 0) {  
    return (char *)s1;  
  }  
  for (p = s1; *p && (p + len<= buffer + n); p++) {  
    if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {  
      return (char *)p;  
    }  
  }  
  return NULL;  
}

3.字符串复制

最常见的字符串复制函数是strcpy:

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

把src所指的由NULL结尾的字符串复制到由dst所指的字符串中,src和dst不可以相同(可以由c99的restrict关键字声明),dst必有足够的空间存放复制的字符串。

还有一点要注意的是函数返回值,返回值是指向dst的指针,这样做的目的是方便程序中语句内联,比如strlen(strcpy(s,t))。

函数的实现如下:

char *my_strcpy(char *dst, const char *src){  
    assert(NULL!=dst && NULL!=src);  
    char *p = dst;  
    while((*dst++ = *src++) != '\0');  
    return p;  
}

使用strcpy是危险的,因为函数本身是不检查dst指向的空间是否足够存储需要复制的字符串,导致的一个潜在隐患就是字符串溢出。这也是上个世纪常被黑客利用的一个经典漏洞。所以,在大多数情况下都是用strncpy无疑更加保险:

char *my_strncpy(char *dst, const char *src, size_t n){  
    assert(NULL!=dst && NULL!=src);  
    char *p = dst;  
    while(n){  
        if((*dst++ = *src++) == '\0')  
            break;  
        n--;  
    }  
    return p;  
}

需要注意另外一个函数strdup:

char *strdup(const char *);

该函数和strcpy的不同是,函数会自己申请内存空间存放拷贝的字符串,然后返回指向该字符串的指针。所以在使用strdup函数时需要注意的是,在使用完复制的字符串后使用free函数释放其占用的空间。

另memcpy函数和strncpy类似,只是不会再遇到NULL时终止拷贝,该函数一定会拷贝n个字符。

4.字符串连接

字符串连接是把一个字符串的头连接到另一个字符串的结尾。

char *strcat(char *s1, const char *s2);

函数的实现如下:

char *my_strcat(char *s1, const char *s2){  
    assert(NULL!=s1 && NULL!=s2);  
    char *p =s1;  
    while(*s1)s1++;  
    strcpy(s1,s2);  
    return p;  
}

同样,strcat也是不安全的,因为也对缓冲区足够存放连接的字串进行了假设。所以,多数情况下我们应该使用更安全的:

char *strncat(char *s1, const char *s2, size_t n);

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值