跳转至

字符串(冬二周——冬四周)

1.字符串基本知识

定义1

char s[6]={'H','e','l','l','o','\0'}

'\0'是八进制字符常数,ascII码=0,作为字符串结束标注

定义2

char s[6]="Hello"   //注意必须是双引号,有隐藏'\0',所以s长度为6

'A'与"A"区别

"A"由'A'和'\0'两个元素组成的字符串,而'A'为字符

空串

""称为空串,里面只有一个'\0'

''语法错误

2.字符串输入输出

%s输入输出字符串

char a[100];
scanf("%s",&a[0]);   #该语句与scanf("%s",a)等价a地址与a[0]地址相同
printf("%s",a);      #此处a可以理解为数组a的全体内容直接写printf(a)也可

想要储存一个字符串,必须用一个数组

输入时要给出一个地址,是a[0]的地址,虽然a[0]只能存储一个字符,但scanf在识别到%s时,能后续获得数组后面元素的地址

%s格式会输出'\0'左边的全体元素,但不输出'\0'本身

char a[100]="0123456789ABCDEF";
scanf("%s",&a[0]);
printf(a);

此时输入ABC xyz 123,输出为ABC

这是因为scanf在输入时,以空格为边界输入(将空格理解为分隔符),此时a实际值变为"ABC\0456789ABCDEF\0"

printf输出时,只输出"\0"左边的值,故输出"ABC",实际上字符串还含有其他内容

gets()输入

char a[100];
gets(a);     //不可写成a=gets(),因为a不是变量名,而是&a[0]

gets()以回车作为输入的结束标志,而不是空格

以下内容摘自小白网页问题4

Q:用scanf()的%s格式输入一个字符串跟用gets()输入一个字符串有什么区别?

A:假定已定义数组char a[100],那么scanf("%s", a)与gets(a)有以下区别:

(1) 不输入具体内容直接敲回车时,scanf()会认为此回车是输入项之间的分隔符,故它会过滤掉此回车并继续等待用户输入非空白的内容;而gets(a)则会认为此回车标志着一行内容输入的结束,于是它会执行a[0]='\0';并返回。

(2) 当输入一个含有空格的字符串如ABC xyz 123时,scanf()仅读取"ABC"并保存到a中,其中a[0]='A', a[1]='B', a[2]='C', a[3]='\0',而把" xyz 123"以及回车符(即'\n')留在输入缓冲区中;gets(a)则会把回车前的所有字符全部保存到数组a中,同时丢弃回车符,此时数组a的内容为:a[0]='A', a[1]='B', a[2]='C', a[3]=' ', a[4]='x', a[5]='y', a[6]='z', a[7]=' ', a[8]='1', a[9]='2',a[10]='3', a[11]='\0'。

(3) 当输入一个不含空格的字符串如ABC时,scanf()会读取"ABC"并保存到a中,同时把回车符留在输入缓冲区中;gets(a)也会读取"ABC"并保存到a中,但它会把回车符丢弃,即不会把回车符留在输入缓冲区内。

gets()有返回值,返回字符串第一个字符的地址,输入失败返回NULL

循环遍历输入

char a[100],x;
int i=0;
while ((x=getchar())!='\n')
{
    a[i]=x;
    i++;     //或合成a[i++]=x
}
a[i]='\0';  //只有末尾是'\0'才是字符串
printf(a);

3.字符串函数

头文件

#inlcude  <string.h>

strlen

char a[100];
int n;
scanf("%s",&a[0]);
n=strlen(a);

strlen函数返回'\0'左边的元素个数,也是'\0'元素的索引下标

函数实现:

int my_strlen(char a[])  /*这里a是用一维数组做形参,或写成char a[100]*/
{
    int i=0;
    while (a[i]!='\0')
        i++;
    return i;
}
int n=my_strlen(a);   /*这里的a是用一维数组做实参,只能是a,a[]或a[100]都不行*/

实参和形参可以一样也可以不一样

二维数组形参规则和边定义边赋值的规则相同,行号可空心,列号不可空心,作形参时不管一维数组还是二维数组实际都是指针

strcpy

用于字符串复制

char a[100]="ABC",char b[100];
strcpy(b,a);

上述程序将a[0]到a[3]复制到b[0]和b[3],复制的是'\0'及其左边的元素,这说明假如b[4]之后有其他元素(如b="0123456789"),输出b也只会输出ABC

不允许用加法运算直接拼接

puts

puts(b);

等价于printf("%s\n",b),注意自带回车

有返回值,输出成功返回'\n',输出失败返回EOF

strcat

字符串连接

strcat(b,a);

把a拼接到b后面

strcmp

字符串的比较

int n;
n=strcmp(a,b);

两个字符串元素逐个比较,若a[i]和b[i]不相等,则输出此时a[i]-b[i]的值;若a[i]和b[i]相等,则比较下一个值,直到'\0'或a[i]与b[i]不相等。

n>0,a>b;n=0, a=b;n<0,a<b

在VC和DEVCPP中,strcmp会把大于0的结果转化成1,小于0的结果转换成-1,等于0则返回0

在TC中,strcmp的值是最后那次减法的差

不能用关系运算符比较字符串的大小

4.一些算法

十进制转十六进制数(字符串%s格式输出)

int x=1000;
char a[100];
int i=0;
char t[]="0123456789ABCDEF";
char c;
do                   /*统计位数或分解整数要用do-while,排除x==0的特殊情况*/
{
    d=x%16;
    a[i]=t[d];       /*查表实现添引号*/
    i++;
    x/=16;
}while (x!=0);
a[i]='\0';
n=strlen(a);        /*等价于n=i*/
for (i=0;i<n/2;i++)
{
    c=a[i];
    a[i]=a[n-1-i];
    a[n-1-i]=c;
}
printf(a);          /*字符串可以直接输出*/

统计单词个数(有空格的单词,空格可能不只1个)

char a[100],b=' ',c;    /*b表示before,初始化为空格相当于给字符串最左边加上一个空格*/
int cnt=0,i,n;
gets(a);
n=strlen(a);
for (i=0;i<n;i++)
{
    c=a[i];
    if (c!=' ' && b==' ')
        cnt++;
    b=c;                /*迭代*/
}
printf("%d",cnt);