博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++学习之字符串
阅读量:4617 次
发布时间:2019-06-09

本文共 2959 字,大约阅读时间需要 9 分钟。

本文试着比较c++字符串与C风格字符串,主要讨论的是c++中的字符串的简单操作。

1、C风格字符串的主要操作与缺陷;

主要操作有: strlen (求长度)、strcpy(复制字符串) 、strcmp(比较字符串大小)、strcat(字符串连接)、strstr(寻找子字符串)

C标准库实现:

char str1[20] = "hello"; //必须有足够大的容量。

char str2[6] = "world!";

1)、strcat

str1 = strcat (str1 ,str2);//将str1末尾的 ' \0 ‘用str2 中的 ' w '替换 。并在新的 str1 末尾自动添加 ’ \0 ‘ 。

               //strcat函数返回的是 新的str1 的首地址

2)、strlen //统计字符串中字符的个数 ,而不将 ‘ \0 ’计入

strlen(str2) = 6 ;

sizeof(str2) = 7 ; 

 

C风格字符串缺陷:

1)、结束符 ' \ 0 ';

2)、很多时候需要自行保证安全性,例如下面的代码很容易让程序崩溃

#include
#include
using namespace std ;int main(int argc ,char *argv[]){ char buf[3] ; strcpy(buf ,"hello"); cout << buf << endl ;}

这里错误的原因在于buf 的内存不够 ,产生内存越界,但是 strcpy 不会也无法检测内存是否越界。

C++ 的解决方案是引入了string类型,我们稍后叙述。

 

这里再叙述很多同学在自己实现字符串的一系列函数中出现的错误以及原因,代码如下;

1 #include
2 #include
3 using namespace std ; 4 5 char *strcat(char *s1 ,const char* s2) 6 { 7 s1 = (char*)malloc( strlen(s1) + strlen(s2) ); 8 } 9 10 char* strcppy(char*s1 , const char* s2)11 {12 s1 = (char*)malloc( strlen(s2) );13 }14 15 int main(int argc ,char *argv[])16 {17 char p[128] ;18 19 strcat( p ,"hello");20 21 return 0 ;22 }

上述代码的错误之处:

1)、我们姑且不管malloc分配内存的大小(当然此处分配的大小肯定是不够的)。

首先对 s1进行重新分配内存显然是无效的,当main函数执行到strcat时 ,会调用strcat函数,然而在strcat函数中 s1 的任何改动都与 p 无关 。因为我们知道C语言中的 参数传递 是 值拷贝(以后会详细叙述)。这实际上造成了内存泄露。

2)、就算这里能够改变 p 的指向,这样的做法也是不允许的。因为这会使得其他地方的字符串失效。当然这里不太可能。不做额外讨论。

 

2、C++字符串的实现

 相对于C,C++提供了一种类型 string,可以更加简单更加安全的操作字符串。代码如下:

#include 
#include
#include
using namespace std; int main(int argc ,char*argv[]) { string s1 = "hello "; string s2("test"); //赋值 string s3 ; //空字符串 cout << s1 << endl ; //打印 cout << s1,size() << endl ;//求长度 s3 = s1 ;//字符串的复制 s3 += s2 ;//OK!字符串的拼接strcat s3 = "hello" + "world" + s1 ; // error 右结合性 char*和char* 不可相加 s3 = s1 + "hello " + "world" ; //ok 右结合性 ,先计算s1+“hello”生成新的str cout << s3 << endl ; //比较大小 cout << (s1 > s2) << endl ; cout << (s1 == s3) << endl ; return 0 ;}

string 同样支持下标操作 和 迭代器操作(可以理解成指针 ,以后详细叙述),代码如下:

//下标操作	for(size_t ix = 0 ;ix != s.size() ; ++ ix)	{		cout << s[ix] << " "  ;	}	cout << endl ;

 

//迭代器操作for (string::iterator it = s3.begin() ;//指向容器的第一个位置   it != s3.end(); // 指向容器最后一个元素的下一个位置      it++ ){	cout << *it << " " ;}cout << endl ;

 一下代码实现的是字符串的查找(查找单词的情况与此一样 ,我们就不再赘述):

//查找单个字符int main(int argc ,char *argv[]){	string str ;		getline(cin ,str); // 读入字符串 ,遇见空格或者enter键表示输入结束		char ch ;	while(cin >> ch)	{		string::size_type pos = s.find(ch) ;		if( pos != string::npos )//search success		{			cout << pos << endl ;// 下标		}else 	 // false		{			cout << "find failure!" << endl ;		}	}       return 0 ; }

 最后 ,string 可以转化为C风格字符串:

//转化为C风格字符串string s = "shenzhen" ;cout << s.c_str() << endl ;

 注意:

1)、string 得出的 char* 是const(只读)属性 ,不可对其修改 ;

2)、另外,这个值可能失效,所以,如果需要,最好每次调用 s.c_str() ;

转载于:https://www.cnblogs.com/xfxu/p/3978404.html

你可能感兴趣的文章
学习记事
查看>>
java 子类重写父类的方法应注意的问题
查看>>
[LevelDB] LevelDB理论基础
查看>>
【codecombat】 试玩全攻略 第一关kithguard地牢
查看>>
【DP】 POJ 1191 棋盘分割 记忆化搜索
查看>>
自动化测试 Appium之Python运行环境搭建 Part2
查看>>
说说DBA职责和目标
查看>>
从头认识Spring-2.4 基于java的标准注解装配-@Inject-限定器@Named
查看>>
sql server 实现多表连接查询
查看>>
Python标准库:内置函数getattr(object, name[, default])
查看>>
转:android 自定义RadioButton样式
查看>>
HTTP请求过程
查看>>
织梦多域名解析到同一个空间导致打开链接不一致怎么办?
查看>>
Xcode10 library not found for -lstdc++ 找不到问题
查看>>
Mysql 8.0.13如何重置密码
查看>>
发布功能完成
查看>>
excel 合并单元格
查看>>
iOS设计模式简介
查看>>
c# 扩展方法 奇思妙用 高级篇 九:OrderBy(string propertyName, bool desc)
查看>>
C语言中的地址传递(传指针,传递给形参的指针仍然是实参指针的一份拷贝)
查看>>