详解C与C++中操作字符串方法的不同
来源:互联网 发布:js手写bind实现原理 编辑:程序博客网 时间:2024/06/07 17:56
灵感来源于前些天无意编写的一个小程序,下面是稍微修改过的代码:
#include<stdio.h>int main(){ char *str1="char"; char *str2="char"; if(str1==str2) printf("equal.\n"); else printf("not equal.\n"); return 0;}
这里发生了一个很有趣的现象,我把这段程序分别用VS2013内置的编译器和它的debug版本进行编译运行,出现了两个截然不同的结果:前者显示“equal”,后者显示“not equal”。其中原因我们先按下不表,下文会提到。
这里我们主要关注的是程序的本意应该是比较两个字符串内容是否相等,但是在c语言中像上述程序那样写,却不是比较两个字符串指针指向的具体内容,而是直接对两个字符串指针地址进行比较。因此,在c语言中要比较字符串内容,需要用到<string.h>
头文件中量身打造的字符串函数,在此处应该用到的是strcmp()函数。
#inlcude<stdio.h>#incldue<string.h>int main(){ char *str1="char"; char *str2="char"; if(strcmp(str1,str2)==0) printf("equal.\n"); else printf("not equal.\n"); return 0;}
然而,在c++中,对字符串的比较却不必这么麻烦,c++标准库中定义了一个string类型来处理字符串,因此要实现上述程序的比较功能,只需像下面这样:
#include<iostream>#include<string>using namespace std;int main(){ string str1="char"; string str2="char"; if(str1==str2) cout<<"equal"<<endl; else cout<<"not equal"<<endl; return 0;}
从上述例子可以看出c与c++在操作字符串上的区别,究其原因,是因为字符串在c语言中是以字符形式存入一个数组中,如char[]="hello"
其实是char[]={'h','e','l','l','o','\0'}
,因此直接对字符串比较其实比较的是指针地址;而在c++中,string是一个类型,在STL(c++标准库)中定义了string类型的“==”操作符的重载版本,因此能够直接对两个string型变量进行比较其内容。下面是摘取的string类型中关于“==”的部分源码:
template<class _Elem,class _Traits,class _Alloc> inline bool operator== ( const basic_string<_Elem, _Traits, _Alloc>& _Left, const basic_string<_Elem, _Traits, _Alloc>& _Right) { // test for string equality return (_Left.compare(_Right) == 0); }
int compare(const _Myt& _Right) const _NOEXCEPT { // compare [0, _Mysize) with _Right return (compare(0, this->_Mysize, _Right._Myptr(), _Right.size())); }
const value_type *_Myptr() const { // determine current pointer to buffer for nonmutable string return (this->_BUF_SIZE <= this->_Myres ? _STD addressof(*this->_Bx._Ptr) : this->_Bx._Buf); }
int compare(size_type _Off, size_type _N0, const _Elem *_Ptr, size_type _Count) const { // compare [_Off, _Off + _N0) with [_Ptr, _Ptr + _Count) #if _ITERATOR_DEBUG_LEVEL == 2 if (_Count != 0) _DEBUG_POINTER(_Ptr); #endif /* _ITERATOR_DEBUG_LEVEL == 2 */ if (this->_Mysize < _Off) _Xran(); // _Off off end if (this->_Mysize - _Off < _N0) _N0 = this->_Mysize - _Off; // trim _N0 to size size_type _Ans = _Traits::compare(this->_Myptr() + _Off, _Ptr, _N0 < _Count ? _N0 : _Count); return (_Ans != 0 ? (int)_Ans : _N0 < _Count ? -1 : _N0 == _Count ? 0 : +1); }
好了,文章写到这里,我们再来看一下文章开头提到的“有趣”的现象-为什么不同的编译器编译相同的程序会得到不同的结果呢?
这是因为好的编译器,会把相同的常量字符串仅仅存一份拷贝,各个指针都指向这个拷贝,所以文章开头的程序会出现比较两个指向相同的“char”字符串的指针时打印“equal”的结果。但是有的编译器会存放多份拷贝,也就是说即使编译器检测到两个指针指向的常量字符串相同,编译器仍然会给两个指针分配不同的地址,当然这种编译器不能算是好的编译器,至少在这一点的处理上就可能会大大浪费存储空间。
既然有了上面的基础,那么我们再来看一下下面这个”加强版”的程序:
#include<stdio.h>int main(){ char *str1="char"; char *str2="char"; char str3[]="char"; if(str1==str2) printf("1 equal to 2\n"); if(str1==str3) printf("1 equal to 3\n"); if(str2==str3) printf("2 equal to 3\n"); return 0;}
猜一下程序运行的结果?
哈哈,程序运行的结果是:
1 equal to 2
当然,上面的结果是基于我说的“好”的编译器的基础上的,要不然,可能运行结果就应该是空了。至于为什么同样是C风格的字符串,为什么指针型的比较能相等而数组型的却不可以呢?答案其实很简单。
在定义一个数组时,编译器是在栈里为数组分配了一段内存,返回的是指向数组首元素的指针,如本程序中就应该是指向c的指针;而在定义一个指向常量的指针时,在这里是指向”char”这个字符串常量的内存首地址,所以二者地址一般是不同的,自然比较的结果就不相等了。
- 详解C与C++中操作字符串方法的不同
- c中字符串与c++中字符串的不同
- Object-c 中字符串的各种操作 详解
- 关于Objective-C中常用的操作字符串的方法
- Java:布尔值,字符范围,字符串声明,换行操作,常量定义与c语言的不同
- string 与 c 风格字符串以及字符串常量的不同
- C中字符串操作
- 字符串s中出现的C字符删除的不同实现方法
- 【C语言】 两种不同的方法在一个字符串中找指定的字符
- C与C++中输入字符串的方法
- C中对于字符串的操作总结
- c语言中操作字符串的函数
- c 中字符串 的相关操作
- c语言中字符串操作的函数
- C语言中字符串的操作
- C 语言中操作字符串的函数
- 【c#】c#中 字符串的基本操作
- 标准C中字符串分割的方法
- angular.js学习(2)--filter
- hdu ---2007做题笔记(c++)
- 一步一步DIY jQuery库2-使用es6模块化
- BOM(二)间歇调用和超时调用、BOM其他主要对象
- 95. Unique Binary Search Trees II
- 详解C与C++中操作字符串方法的不同
- 【转】HTML5的 input:file上传类型控制
- codeforces C. DZY Loves Fibonacci Numbers (数论+线段树)
- (笔记)Spring实战_事务管理(1)_理解事务
- 一步一步DIY jQuery库3-引入sizzle引擎
- 组织架构重组创新是企业致胜法宝
- Shell 编程
- 论代码级性能优化变迁之路(一)
- 日常英语 —— 对话、缩略、标语句