【Jason's_Knowledge】算法竞赛中的字符与字符串

来源:互联网 发布:易语言软件版本 编辑:程序博客网 时间:2024/06/07 01:58

算法竞赛中的字符与字符串

鄙人才疏学浅,还望各位前辈批评指正,万分感谢。

为了不至于混淆,我们将C语言中的字符与字符串和C++语言中的字符与字符串分开来讨论。在算法竞赛中,为了保证程序执行的时间效率,通常我们使用C语言的字符与字符串,以下我们先着重讲解C语言中的字符与字符串。

 

一、C语言中的字符与字符串

1.字符

字符数据是使用单引号括起来的一个字符。例如:’A’ , ’a’ , ’=’ , ’1’均为合法的字符型数据。

转义字符是一种特殊的字符型数据,转义字符以反斜线’\’开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。例如:’\n’即为一个转义字符,它的意义是“回车换行”。

字符仅占一个字节的内存空间。

 

2.字符串

字符串数据是使用双引号括起来的一个字符序列。例如:”Doris” , ”Jason” , ”#007”均为合法的字符串数据。

字符串占用的内存空间字节数为:字符串所含字符数量加1(亦即字符串的长度)

字符串结束标志为’\0’(ASCII码为0)

    

从上面我们清楚,’a’与”a”意义是不同的,一个为字符,一个为字符串。他们在内存中的存储情况如下:

’a’在内存中占一个字节,可表示为:


”a”在内存中占两个字节,可表示为:

 

 

3.字符变量与字符串变量的定义以及初始化

(1) 字符变量的定义以及初始化形式如下

 

char 变量名;    例如:

char a;

char 变量名=’字符’;    例如:

char a=’x’;

 

(2) 字符串变量的定义以及初始化形式如下

C语言中没有相应的字符串变量,也就是说不存在这样的关键字,将一个变量声明为字符串。

但是通常可以用一个字符数组来存放一个字符串。

 

char 变量名[字符串长度];    例如:

char a[100];

『在更进一步的讨论字符串变量的初始化之前,我们先来回顾一下一维数组与二维数组初始化的内容。』

为了方便理解,我们一下均举例讨论,不再有任何形式化的描述。

1.一维数组的初始化

如: 

int a[10]={1,2,3,4,5,6,7,8,9,10};

若给全部元素赋值,则在数组说明中,可以不给出数组元素的个数。

如: 

int a[]={1,2,3,4,5,6,7,8,9,10};

2.二维数组的初始化

如: 

int a[2][3]={{1,2,3},{4,5,6}};

也可以: 

int a[2][3]={1,2,3,4,5,6};

若给全部元素赋初值,则在数组说明中,可以不给出第一维的长度。

如: 

int a[][3]={{1,2,3},{4,5,6}};

也可以: 

int a[][3]={1,2,3,4,5,6};

    

注意:数组类型指的是数组所包含的元素的类型,而不是数组名的类型,数组名永远是一 个指针,指向第一个元素的地址,即数组首地址。

所以,可以说字符数组同普通数组几乎一样。

 

我们先来讨论字符数组的初始化。

明确了上面的概念后,我们很容易的就能得出字符数组的初始化方式。

如: 

char c[8]={’a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’};

也可以:

char c[]={’a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’};

其中:

c[0]=’a’; c[1]=’b’;  c[2]=’c’;  c[3]=’d’;  c[4]=’e’  c[5]=’f’;  c[6]=’g’;  c[7]=’h’;

 

现在我们来讨论字符串的初始化。

字符数组与普通数组的不同在于,由于规定字符数组可以存放一个字符串,那么我 们可以这样初始化一个字符串:

如: 

char c[]={”Jason”};

也可以: 

char c[]=”Jason”;

亦可使用字符数组的复制方式: 

char c[]={’J’,’a’,’s’,’o’,’n’};

但这里要着重注意的是:在这里,我们想为c[]赋值的数据是字符串而非字符数组,虽然说这在物理形式上是没有任何区别的,但是从逻辑的角度上来看,我们定义字符数组

char c[]={’J’,’a’,’s’,’o’,’n’};

与定义字符串

char c[]={’J’,’a’,’s’,’o’,’n’};

的区别在于,字符数组是

char c[5]={’J’,’a’,’s’,’o’,’n’};

而字符串是

char c[6]={’J’,’a’,’s’,’o’,’n’,’\0’};/*即*/ char c[6]={”Jason”};/*亦即*/ char c[6]=”Jason”;

可见,系统编译时会在字符串初始化时自动为之添加字符串结束符’\0’。所以用字符串方式赋值比用字符逐个赋值要多占一个字节, 多占的这一字节用于存放字符串结束标志'\0'

 

为了不过分的纠结于初始化字符串的长度问题,我们通常使用如下的定义方式:

char c[]=”Jason”;

另外,我们讨论一种特殊的字符串的定义与初始化方式(为方便理解,同字符数组对比理解):

使用字符数组的情况如下:

char c[]=”Jason”;

使用字符指针的情况如下:

char* c=”Jason”;

也可以:

char* c;c=”Jason”;

但在cc++混用的算法竞赛中这是很不安全的,所以我们通常会看见这样的形式:

const char* c=”Jason”;//(它经常出现在对常量字符串的定义中)

或是这样的形式(他定义了一个指向类型为字符串数据的指针的数组):

const char* c[]={”Jason”,”Doris”,”Win”};

4.字符变量与字符串变量的输入输出

(应该注意,以下有关字符变量与字符串变量的输入输出函数均包含在头文件<cstdio>当中。)

(1) 字符变量的输入输出

char ch;

第一种方式:

scanf(”%c”,&ch);printf(”%c”,ch);

第二种方式:

ch=getchar();putchar(ch);

对于输出方式我们没有什么需要注意的,但是对于这两种输入方式我们需要讨论一下他们的区别。

(I) scanf(”%c”,&ch); SpaceEnterTab结束一次输入,但是不会舍弃最后的结束符(这里的结束符号是指SpaceEnterTab)(即回车符会残留在缓冲区中);

(II) ch=getchar(); Enter结束输入,也不会舍弃最后的回车符;

 

举个例子:

#include <cstdio>  using namespace std;int main()  {      char ch1, ch2;      scanf("%c", &ch1);       scanf("%c", &ch2);      printf("%d  %d\n", ch1, ch2);      return 0;  }  

或者是:

#include <cstdio>  using namespace std;int main()  {       char ch1, ch2;       ch1 = getchar();       ch2 = getchar();       printf("%d  %d\n", ch1, ch2);       return 0;  }  

 

    假若输入’a’并敲击回车,则程序直接输出97 10

这是因为scanf()getchar()函数是从输入流缓冲区中读取的,而并非从键盘(也就是终端)缓冲区读取。由于读取是因为遇到回车(’\n’)才结束的,并且这个’\n’会被一起读入输入流缓冲区中,所以第一次接受输入并取走字符之后会留下字符’\n’,这样第二次的读入函数就会直接从缓冲区中把’\n’取走。显然,这样的读取是成功的,它不会再从终端读取!这就是为什么这个程序只执行了一次输入操作(对于计算机来说的话,换行符也是一个输入,只执行一次输入操作仅仅是由于人的惯性思维所造成的)就结束的原因。

所以在使用scanf()getchar()函数输入数据的时候一定要进行特判。

 

(2) 字符串变量的输入输出

char str[100];//或者是char* str;

第一种方式:

scanf(”%s”,str);printf(”%s”,str);

第二种方式:

gets(str);puts(str);

同样,我们仅对于这两种输入方式讨论一下他们的区别。

(I) scanf(”%s”,str); 以SpaceEnterTab结束一次输入,并舍弃最后的结束符(这里的结束符是指SpaceEnterTab)。

(II) gets(str); 以Enter结束输入(空格不结束),接受空格,并舍弃最后的回车符。

注意:在使用scanf(”%s”,str); 或printf(”%s”,str);输入输出字符串时,str前面并没有添加&符号。这是由于 scanf() 和 printf() 函数有一种占位符”%s”可以用作整体的输入输出字符数组,但是并没有一个特定的占位符支持 int 等其他数组整体数组输出。

 

5.字符串变量的重要操作函数

(应该注意,以下有关字符串变量的操作函数均包含在头文件<cstring>当中。)

1.strcmp(str1,str2); 比较str1str2是否相等。

返回值: ==0  相等;

   <0     str1<str2

   >0     str1>str2

 

2.strlen(str); 求字符串str的长度。(不含字符串结束标志’\0’)

返回值: 字符串str的长度。

 

3.strcpy(str1,str2); 清空str1,并将str2赋值到str1中去。相当于赋值操作。

返回值:str1首地址。

 

4.strcat(str1,str2); str2中的字符串连接到str1 中的字符串的后面,并删去str1后的结束标志”\0”。

返回值:str1首地址。


二、C++语言中的字符与字符串

由于C++语言中的字符及字符数组与C语言中的没有任何差别,故我们只讨论C++语言中的字符串,即string类。(所有有关操作均包含在头文件<string>当中)

每一个string并非语言本身所特有,他其实是一个类,每当使用string定义一个字符串变量,就相当于声明了一个string对象。所以,从某种意义上讲,string相对于C语言中的字符串是十分低效的(不针对工程方面的程序设计),所以在算法竞赛中可以适当的使用它并提高代码编写效率,但是请不要滥用。

在此我就虎头蛇尾一下,简短的介绍一下string类的一点常用方法。

1.定义及初始化

string str1;string str2=”Jason”;

2.赋值

str1=”Doris”;str1[2]=’x’;//(注意必须为单引号)

3.输入输出

无法使用头文件<cstdio>中的输入输出函数,仅允许使用<iostream>中的cincout 作,如下。

cin>>str1;cout<<str1;

4.操作

(1)字符串的比较,直接使用比较运算符即可,如:<等,相当于C语言的strcmp函数。

(2)字符串的链接,直接使用str1=str1+str2,相当于C语言的strcat函数。

(3)字符串的拷贝,直接使用str1=str2,相当于C语言的strcpy函数。

(4)字符串的长度,直接使用str1.size()str1.length()(二者完全一样),相当于C 言的strlen函数。

5.注意

string类声明的对象字符串,没有结束标志’\0’。

0 0
原创粉丝点击