求教c++字符串比较结果及分析!

#include <iostream.h>
#include <string.h>
void swap(char p1[],char p2[]);
void main()
{
char s1[10]="while",s2[10]="else",s3[10]="default",s4[10]="zlse";
if(strcmp(s1,s2))
swap(s1,s2);
if(strcmp(s3,s4))
swap(s3,s4);
if(strcmp(s1,s3))
swap(s1,s3);
cout<<s1<<endl;
}
void swap(char p1[],char p2[])
{
char p[10];
strcpy(p,p1);
strcpy(p1,p2);
strcpy(p2,p);
}

字符串是以空字符结尾的字符数组。

char 型字符串

由于char占用一个字节的空间,为了让char能够存储更多的字符,我们用了数组的方式。

如:

char man[4]={'J','A','C','K'};

然而该char行数组man却不是一个字符串,因为它没有字符串的结束表示——"\0"。只有我们为其添加"\0"这个结束标志后,这个char型数组man才能转化为字符串,如:

char man[5]={'J','A','C','K','\0'};

"\0"是一个空字符表示,它的ASCII码为0,C++有好多处理字符串的函数,它们都以"\0"为结束标示,也就是以空字符为结束标志,如cin和cout,它们也是以空字符为结束标志,它们在碰到空字符后将会停止输入或输出,如:
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char man[12];
cin>>man;
cout<<man<<endl;
system("pause");
return 0;
}
复制代码
输出:
hello world
hello

分析:
第3行我们定义了一个存储12个字符的char型数组man,第6行用数组man来保存用户输出,我们输入了10个字符hello world,由于cin遇到空字符就停止输入,而我们在输入world时空了一格,因此我们看到输出的结果只是hello。

可使用cin.get解决这一问题。

程序代码如下:
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char man[12];
cin>>man;
cin.get(man,12);
system("pause");
return 0;
}
复制代码
cin.get的结束标志是"\n",也就是换行,因此语句遇到空格不会结束,而是把空格也看做一个字符,同时在输入结束后,也就是用户输入一个回车后,cin.get自动为当前接受输入的数组添加字符串结束标志"\0",因此它实际保存的有效字符是它的第2个参数减1,在本例中是(12-1)11个字符。

同样,输出也是这样,假如我们在一行字符串的中间放了0,如:
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char man[]={'H','e','l','l','o','0','W','o','r','l','d'};
cout<<man<<endl;
system("pause");
return 0;
}
复制代码
空字符的ASCII码为0,我们在字符型数组中输入了一个不加引号的0,编译器就会根据ASCII码值来寻找字符,ASCII码值为0的字符是NULL字符,也就是空字符,cout遇到空字符就会停止输出,因此0后面的字符没有输出,只输出了Hello。

要解决这个问题,也就是想要存储一个,则必须将空格作为一个字符来录入,如:
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char man[12]={'H','e','l','l','o',' ','W','o','r','l','d'};
cout<<man<<endl;
system("pause");
return 0;
}
复制代码
输出 Hello World

分析:
第5行字符o后面的两个单引号''中间是一个空格,由于用单引号括了起来,因此编译器会把这个空格当做字符串存储在char型数组man中,而不是当做空字符。

虽然像第5行那样逐个字符地录入是可行的,但是写起来太麻烦,而且很容易看错位置,导致输入出错。C++提供了一种简便的方式来替代第5行,如:

char man[12]={"Hello world"};

用双引号包括起来的字符串隐含了字符串结束标志"\0",因此你不用动手去添加它。这样的写法明显要比第5行省事多了。

你也可以省略定义字符串的长度,而把这个任务交给编译器去完成,如:
char man[]={"Hello world"};

编译器会自动根据双引号内字符的个数定义字符串的长度。

假如你不知道具体要存放多少个字符,那么你可以将数组长度定义得大一点,如:
char man[99];

这样,即可以防止在要存储的字符很多时,超出数组末尾写入数据,也就是数组越界。这样做的坏处就是浪费空间,因此处理字符串的函数根据空字符的位置,而不是字符的长度来进行处理,所以你为字符数组man多开辟出来的那些内存空间除了耗费系统内存之外没有什么实际用途。另外,C++不限制字符串的长度,也就是说可以将字符串数组的长度定义为无限大。

最好,我们在计算字符串长度时,不要忘记最后的空字符"\0".
计算字符串长度及大小的程序代码如下:
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char man[12]={"Hello world"};
cout<<man<<endl;
cout<<"strlen(man):"<<strlen(man)<<endl;
cout<<"sizeof(man):"<<sizeof(man)<<endl;
man[5]='\0';
cout<<man<<endl;
cout<<"strlen(man):"<<strlen(man)<<endl;
cout<<"sizeof(man):"<<sizeof(man)<<endl;
system("pause");
return 0;
}
复制代码
输出:
Hello world
strlen(man):11
sizeof(man):12
Hello
strlen(man):5
sizeof(man):12

分析:
第5行定义了一个字符串数组man,它保存了包括空格在内的11个字符和一个用来表示字符串结束的"\0".这样一共是12个字符,但是第7行输出strlen函数返回的字符串长度时,我们发现是11,而用sizeof返回的是12,这是为什么呢?

这是因为strlen返回的是字符串结束标志"\0"之前的字符串长度,而不是数组长度,而sizeof返回的是数组的长度,也就是该数组共有多少个元素。

在第9行,我们将数组的第6个元素修改为字符串结束标志"\0",(第1个元素是man[0]),我们看到由cout遇到空字符而结束输出,结果只输出了hello。跟着第11行用strlen获取字符串的长度,为5,是可见字符hello的长度,没有包括结束标志"\0"。而第12行sizeof获取的是数组的长度12.

string型字符串

char型字符串是C语言风格的字符串,它是用数组来保存字符串的,但是到了C++时代,由于诞生了类,出现了一种C++风格的字符串,也就是string型字符串。

这种风格的字符串是用string类来定义字符串的,因此要使用string类,我们必须在程序开头添加头文件string,string类存在于命名空间std中,这样我们就必须使用using std::string指令,或者直接用std::string来访问它。string类在定义时隐藏掉了字符串的数组性质,因此在使用string类定义字符串时不用考虑如何将字符串存放在数组中,string类已经做好了这一步,编程者要做的,就是像定义一个整型变量那样使用它,如:

string str;

这里定义了一个C++风格的字符串str。

C++风格的字符串就是用对象来保存字符串的。下面用实例演示char型字符数组和string型字符串的不同。

字符数组与字符对象不同,两者相比较的程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str="string型字符串";
char ch[]="char型字符串";
cout<<str<<endl;
cout<<ch<<endl;
cout<<"请输入“狗”的英文单词:"<<endl;
cin>>str;
if(str=="dog")
{
cout<<"狗:"<<str<<endl;
cout<<"str"<<"的第1个字符是:"<<str[0]<<endl;
}
else
cout<<"输入错误"<<endl;
cout<<"请输入“猪”的英文单词:"<<endl;
cin>>ch;
if(ch=="pig")
{
cout<<"猪:"<<ch<<endl;
cout<<"ch"<<"的第1个字符是:"<<ch[0]<<endl;
}
else
cout<<"输入错误"<<endl;
system("pause");
return 0;
}
复制代码
输出:
string型字符串
char型字符串
请输入“狗”的英文单词:
dog
狗:dog
str的第1个字符是:d
请输入“猪”的英文单词:
pig
输入错误

分析:
第6行定义并初始化了一个string型字符串str,第7行定义并初始化了一个char型字符数组ch,第8行和第9行分别输出它们的值。可以看到它们的初始化工作和输出结果都是一样的。

区别在第12行和第21行。

第11行用cin接受用户输入的字符串并保存在string型字符串str中,然后第12行对str和双引号内的正确答案进行判断,假如两者相等的话,执行大括号中的语句,输出str的值以及str中的第1个字符。我们看到第24行也可以用个数组的形式访问str对象中的字符。输出的结果也证明第12那种直接用str对象与一串字符进行的判断的方法是可以的。

第20行将用户输入的字符保存在char型字符数组ch中,第21行也用了第12行的方式进行判断,但是我们发现即使输出了正确的单词,系统提示输入错误。这是为什么呢?

这是因为ch是一个数组名,我们知道数组名是该数组第1个元素的内存地址,而用引号括起来的字符串也代表第1个字符的内存地址,这两个内存地址根本不可能相等,因此程序始终执行else分支,提示输入错误。

以上问题解决的办法是用循环的方式比较数组中的每一个字符。

自定义check比较函数,程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int check(char ch[]);
int _tmain(int argc, _TCHAR* argv[])
{
string str="string型字符串";
char ch[]="char型字符串";
cout<<str<<endl;
cout<<ch<<endl;
cout<<"请输入“狗”的英文单词:"<<endl;
cin>>str;
if(str=="dog")
{
cout<<"狗:"<<str<<endl;
cout<<"str"<<"的第1个字符是:"<<str[0]<<endl;
}
else
cout<<"输入错误"<<endl;
cout<<"请输入“猪”的英文单词:"<<endl;
cin>>ch;
if(check(ch)==1)
{
cout<<"猪:"<<ch<<endl;
cout<<"ch"<<"的第1个字符是:"<<ch[0]<<endl;
}
else
cout<<"输入错误"<<endl;
system("pause");
return 0;
}
int check(char ch[])
{
char ch1[]="pig";
bool quit = false;
for(int i=0;i<strlen(ch1);i++)
{
if(ch[i]!=ch1[i])
{
quit = true;
break;
}
}
if(quit == false)
return 1;
else
return 0;
}
复制代码
分析:
第4行我们定义了一个check函数,它带有一个int型返回值,并且还有一个char型数组作为该函数的接收参数。

第31~47行是该函数的定义部分,在第33行定义了一个char型数组ch1,用来保存正确答案,第34行定义了一个bool型变量quit,并将它的值初始化为false,以后该变量会作为检测的依据,第35行是一个for循环,在这里要注意它的循环次数是保存了正确答案的ch1的字符长度,而不是保存了用户输入的ch。

第37~43行循环对ch1和ch数组中的每个字符进行比较,假如有一个字符不相等的话,立即将quit的值赋为true,然后退出循环,假如所有字符均相等的话,保持不变。

第43~46行在对quit的值进行判断,假如为false,返回1,不相等时,返回0.

第23行调用了这个函数,假如返回值为1,那么执行括号内的语句,否则输出"输入错误".

我们也可以将这个check(char ch[],char ch1[])
这样旧可以去掉第33行对ch1的初始化,而在调用时只要写下。
check(ch,"pig");
这样"pig"会作为一个未命名的字符串数组由check函数的形式参数ch1接受,然后传递到函数中去,这样,ch1在check函数中就成了"pig"的数组名。

对于未命名数组,我们看下面语句就明白了。
cout<<"pig";

该语句中的pig就是作为一个未命名字符串数组保存在栈中,然后通过cout对象加按位左移运算符<<以流的形式将它们输出。

修改后的check函数时的程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int check(char ch[],char ch1[]);
int _tmain(int argc, _TCHAR* argv[])
{
string str="string型字符串";
char ch[]="char型字符串";
cout<<str<<endl;
cout<<ch<<endl;
cout<<"请输入“狗”的英文单词:"<<endl;
cin>>str;
if(str=="dog")
{
cout<<"狗:"<<str<<endl;
cout<<"str"<<"的第1个字符是:"<<str[0]<<endl;
}
else
cout<<"输入错误"<<endl;
cout<<"请输入“猪”的英文单词:"<<endl;
cin>>ch;
if(check(ch,"pig")==1)
{
cout<<"猪:"<<ch<<endl;
cout<<"ch"<<"的第1个字符是:"<<ch[0]<<endl;
}
else
cout<<"输入错误"<<endl;
system("pause");
return 0;
}
int check(char ch[],char ch1[])
{
bool quit = false;
for(int i=0;i<strlen(ch1);i++)
{
if(ch[i]!=ch1[i])
{
quit = true;
break;
}
}
if(quit == false)
return 1;
else
return 0;
}
复制代码
虽然输出结果与修改前的程序相同,但仍很麻烦,假如我们使用strcmp函数的话,那么就可以省略自己定义函数这一步骤。
strcmp函数用来比较两个字符串是否相等,假如str1<str2,返回一个小于0的数字,如-1,假如str1=str2,返回0,假如str1>str2,返回一个大于0的数字,如1.

使用strcmp函数时的程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str="string型字符串";
char ch[]="char型字符串";
cout<<str<<endl;
cout<<ch<<endl;
cout<<"请输入“狗”的英文单词:"<<endl;
cin>>str;
if(str=="dog")
{
cout<<"狗:"<<str<<endl;
cout<<"str"<<"的第1个字符是:"<<str[0]<<endl;
}
else
cout<<"输入错误"<<endl;
cout<<"请输入“猪”的英文单词:"<<endl;
cin>>ch;
if(strcmp(ch,"pig")==0)
{
cout<<"猪:"<<ch<<endl;
cout<<"ch"<<"的第1个字符是:"<<ch[0]<<endl;
}
else
cout<<"输入错误"<<endl;
system("pause");
return 0;
}
复制代码
分析:

使用strcmp函数后,程序代码简化了很多,但是再简化也不如string类的字符串,由于string类中的函数重载了类似比较运算符(==)等关系运算符,因此string类允许使用运算符对它的字符串对象进行比较,这是string型字符串与char型字符数组的第1个区别。

string型字符串的赋值

char型字符串无法直接赋值,如:
char ch1[]="give me";
char ch2[]="a cup";
ch1=ch2;
复制代码
这样是错误的,不能将一个数组名赋给另一个数组名。虽然我们无法直接赋值,但我们可以通过C函数,比如说strcpy拷贝函数来实现赋值的目的。

char型字符的赋值的实现例程代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char ch1[]="what's your name";
char ch2[]="my name is Jack";
strcpy(ch1,ch2);
cout<<ch1<<endl;
cout<<ch2<<endl;
system("pause");
return 0;
}
复制代码
输出:
my name is Jack
my name is Jack

分析:
第7行调用了strcpy函数,它的作用是将ch2中的字符依次复制给ch1.因此必须保证ch1足够大,以便能够容纳ch2的字符串,这里由于在初始化时ch1容纳的字符比ch2多,因此我们没有改动。ch2可以是字符数组名,也可以是一个字符串常量,如:

strcpy(ch1,"my name is Jack");
它与strcpy(ch1,ch2)相同

注意:
(1)strcpy会将ch2中的所有字符,包括结束标志"\0"一起复制到ch1中去。
(2)不可以直接对char型字符串数组进行赋值操作,如:
char a[9],b[9];
a=b;

只能用strcpy函数对数组元素逐个的赋值,如:
a[0]=b[0];
a[1]=b[1];
................
a[8]=b[8];

很明显,这样要麻烦多了,我们来看一下string字符串对象的赋值。
string型字符串对象的赋值实例的程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str1="what's your name";
string str2="my name is Jack";
str1=str2;
cout<<str1<<endl;
cout<<str2<<endl;
system("pause");
return 0;
}
复制代码
分析:
由于在string类中使用operator函数重载了运算符,因此对象之间可以赋值,可以看到第8行直接将str2字符串对象赋给str1,第9行和第10行输出结果,很明显使用string比char要简便多了。

另外,我们也可以调用string类的赋值函数assign,该函数可以取第2个字符串的任意字符赋给第1个字符串,如:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str1="gh";
string str2="abcdef";
str1.assign(str2,3,1);
cout<<str1<<endl;
system("pause");
return 0;
}
复制代码
输出:
d

分析:
第8行调用了assign赋值函数str1.assign(str2,3,1);。
该语句中的3表示从str2中的第3个元素开始,也就是从str2[2]开始,1表示取1个字符,这样,该行语句的意义就是使用对象str1调用string类的成员函数assign将str2中的第3个元素,也就是str2[2]赋给str1,由于是赋值,并且string类具有自动调节字符串大小的功能,因此str1的多余字符被删除,只保存str2[2]赋给它的d。

string型字符串的赋值

char型字符串无法直接赋值,如:
char ch1[]="give me";
char ch2[]="a cup";
ch1=ch2;
复制代码
这样是错误的,不能将一个数组名赋给另一个数组名。虽然我们无法直接赋值,但我们可以通过C函数,比如说strcpy拷贝函数来实现赋值的目的。

char型字符的赋值的实现例程代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char ch1[]="what's your name";
char ch2[]="my name is Jack";
strcpy(ch1,ch2);
cout<<ch1<<endl;
cout<<ch2<<endl;
system("pause");
return 0;
}
复制代码
输出:
my name is Jack
my name is Jack

分析:
第7行调用了strcpy函数,它的作用是将ch2中的字符依次复制给ch1.因此必须保证ch1足够大,以便能够容纳ch2的字符串,这里由于在初始化时ch1容纳的字符比ch2多,因此我们没有改动。ch2可以是字符数组名,也可以是一个字符串常量,如:

strcpy(ch1,"my name is Jack");
它与strcpy(ch1,ch2)相同

注意:
(1)strcpy会将ch2中的所有字符,包括结束标志"\0"一起复制到ch1中去。
(2)不可以直接对char型字符串数组进行赋值操作,如:
char a[9],b[9];
a=b;

只能用strcpy函数对数组元素逐个的赋值,如:
a[0]=b[0];
a[1]=b[1];
................
a[8]=b[8];

很明显,这样要麻烦多了,我们来看一下string字符串对象的赋值。
string型字符串对象的赋值实例的程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str1="what's your name";
string str2="my name is Jack";
str1=str2;
cout<<str1<<endl;
cout<<str2<<endl;
system("pause");
return 0;
}
复制代码
分析:
由于在string类中使用operator函数重载了运算符,因此对象之间可以赋值,可以看到第8行直接将str2字符串对象赋给str1,第9行和第10行输出结果,很明显使用string比char要简便多了。

另外,我们也可以调用string类的赋值函数assign,该函数可以取第2个字符串的任意字符赋给第1个字符串,如:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str1="gh";
string str2="abcdef";
str1.assign(str2,3,1);
cout<<str1<<endl;
system("pause");
return 0;
}
复制代码
输出:
d

分析:
第8行调用了assign赋值函数str1.assign(str2,3,1);。
该语句中的3表示从str2中的第3个元素开始,也就是从str2[2]开始,1表示取1个字符,这样,该行语句的意义就是使用对象str1调用string类的成员函数assign将str2中的第3个元素,也就是str2[2]赋给str1,由于是赋值,并且string类具有自动调节字符串大小的功能,因此str1的多余字符被删除,只保存str2[2]赋给它的d。
判断string型字符串是否为空

判断string型字符串是否为空

string类的成员函数empty可以判断string型字符串是否为空。
string类的成员函数empty。程序代码如下:
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str="";
if(str.empty())
cout<<"字符串为空!"<<endl;
else
cout<<str<<endl;
system("pause");
return 0;
}
复制代码
输出:
字符串为空!

分析:
第7行用str对象调用该对象的成员函数empty(),如果字符串为空则empty返回真(true),否则返回假(false)。由于返回了假,所以执行第8行,输出“字符串为空”.
温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-11-29
你的程序目的并不明确,既不是求最大值,也不是求最小值,更不是排序问题,
char s1[10]="while",s2[10]="else",s3[10]="default",s4[10]="zlse";
if(strcmp(s1,s2))
swap(s1,s2);-------s1=else,s2=while
if(strcmp(s3,s4))
swap(s3,s4);-------s3=zlse,s4=default
if(strcmp(s1,s3))
swap(s1,s3);-------s1=zlse.s3=else
s1=zlse,s2=while,s3=else,s4=default
虽然结果是从大到小排序,但这算法并不通用,万一字符串的值变了,你的程序就不行了。
例如 char s2[10]="while",s3[10]="else",s4[10]="default",s1[10]="zlse";
说白了,你这算发十分揪心。本回答被提问者采纳
第2个回答  2011-11-29
就是4个字符串找最大的。
s1和s2比较,找出大的那个,放在s1
s3和s4比较,找出大的那个,放在s3
s1和s3比较,找出大的那个,放在s1
所以最后s1里面就是最大的那个
第3个回答  2011-11-29
if(strcmp(s1,s2))//!=0
swap(s1,s2);//s1和s2换
if(strcmp(s3,s4))//!=0
swap(s3,s4);//s3和s4换
if(strcmp(s1,s3))//!=0
swap(s1,s3);//s1和s3换
cout<<s1<<endl;
第一次换的时候s1=else
第二次换的时候s3=zlse
第三次换的时候s1=zlse
第4个回答  2011-11-29
....
相似回答