C 语言中的字符串

在程序设计中,不止会用到数值和字符,也要用到字符串。甚至还可以说,字符串在程序设计中还有着比较重要的作用。

字符串常量

C 语言中提供了字符串,但是并没有提供字符串类型。但这并不意味着不能够使用字符串。

字符串表示

通常会用 “” 来表示这是一个字符串,实际上用 “” 括起来的部分可以认为是字符串常量。

字符串长度

通常情况下,字符串长度要比 “” 中间的字符数目多一个,多出来的那个字符是 “\0”。这个字符被称为字符串结束字符,是系统对 “” 表示的字符串自动加设的。可以看下边的程序:

#include <stdio.h>

int main()
{
    printf("The string is %s\n","Hello world");
    printf("The length of tht string is %d\n",sizeof("Hello world"));

    for (int i = 0; i < sizeof("Hello world"); i++)
        printf("The ASCII is %d,the letter is %c\n",*("Hello world" + i),*("Hello world" + i));

    return 0;
}

结果为:

The string is Hello world
The length of tht string is 12
The ASCII is 72,the letter is H
The ASCII is 101,the letter is e
The ASCII is 108,the letter is l
The ASCII is 108,the letter is l
The ASCII is 111,the letter is o
The ASCII is 32,the letter is
The ASCII is 119,the letter is w
The ASCII is 111,the letter is o
The ASCII is 114,the letter is r
The ASCII is 108,the letter is l
The ASCII is 100,the letter is d
The ASCII is 0,the letter is

从上边的结果可以看出:

  • 实际上 “Hello world” 是该字符串的首地址,因此可以用 *("Hello world" + i) 来访问单个字符,又因为 a[i] = *(a + i),所以利用 “Hello world”[i] 的形式也是可以的
  • 可以利用 %s 输出字符串,后边对应的可以是字符串的地址,字符串变量或者是 char * 指针
  • 字符串的长度比实际看到的字符数目多 1
  • 字符串最后一个字符为控制字符 \0

字符串存储

对于字符串常量的存储,C 语言不像其它普通类型常量将之存储在代码段,而是将字符串常量保存在了数据段中的只读数据段。也就是通常所说的常量区。

字符串常量与指针的关系

之前我们说到,利用 printf 函数进行输出时,“Hello world” 实际上相当于一个指针,该指针指向该字符串的首地址。也就是说,C 语言内部将字符串常量处理为一个指向该字符串常量首字节地址的指针。因此我们可以将该字符串常量赋值给一个 char * 的指针。

#include <stdio.h>

int main()
{
    char *pa = "Hello world";

    printf("pa = %p\t\"Hello world\" = %p\n",pa,"Hello world");
    printf("The string is %s\n",pa);

    //pa[0] = 'h';

    return 0;
}

结果为:

pa = 00404064   "Hello world" = 00404064
The string is Hello world

从结果可以看出:

  • 字符串常量确实是个地址
  • 利用 char * 指针可以指向字符串常量
  • 两次的 “Hello world” 所指向的地址相同,这意味着相同的字符串常量对应的地址也是一样的
  • 程序中注释掉的语句说明,字符串常量不能够重新赋值,因为存储在只读数据段

字符数组

字符数组就是数组中存储的是字符值。之前我们说字符串常量的值不能更改,但是字符数组是能够改变值的。

之前提到过,字符串比实际看到的字符数目还要多 1。也就是说如果字符数组在保存字符串中的显式字符之外再保存一个 “\0”,就变成了字符串变量。看下边的程序:

#include <stdio.h>

int main()
{
    char a[20] = "hello world";
    char b[12] = "hello world";
    char c[11] = "hello world";
    char d[] = "hello world";

    printf("The address is %p,the string is %s\n",a,a);
    printf("The address is %p,the string is %s\n",b,b);
    printf("The address is %p,the string is %s\n",c,c);
    printf("The address is %p,the string is %s\n",d,d);

    a[0] = 'H';

    printf("The address is %p,the string is %s\n",a,a);

    return 0;
}

结果为:

The address is 0060FE9C,the string is hello world
The address is 0060FE90,the string is hello world
The address is 0060FE85,the string is hello worldhello world
The address is 0060FE79,the string is hello world
The address is 0060FE9C,the string is Hello world

从上边的结果可以看出:

  • 我们并没有在字符数组的最后手动加 “\0”,但却能够在 printf 函数中按字符串输出,这说明 “\0” 是自动添加的
  • 当字符数组的长度大于字符的数目时,printf 能够正常输出,因为最后有控制字符 “\0”
  • 当字符数组的长度不大于字符的数目时,按 %s 就不知道会输出什么内容,没有不知道下一个控制字符 " \0" 在哪里
  • 字符数组能够改变保存的字符串值,同时地址不发生改变
  • 习惯上,使用带有初始化的字符数组时,一般不限定字符数组的长度,写成 char a[]

字符串的输入和输出

输出

printf

可以利用 %s 来输出字符串,但是只有在遇到控制字符 “\0” 才会停止输出。

puts

函数头为:

int __cdecl puts(const char *_Str);

先不用去管 __cdec1,该函数能够向屏幕打印 _Str 对应的内容,成功返回 >0,失败返回 -1,并会自动换行。

输入

scanf

  • scanf 遇到空格就会截止输入
  • 输入的字符长度小于字符数组的长度时,会自动在字符串后加 “\0”
  • 输入的字符长度最后不好超过字符数组的长度

gets

  • gets 遇到回车才会截止输入
  • 输入的字符长度小于字符数组的长度时,会自动在字符串后加 “\0”
  • 输入的字符长度最后不好超过字符数组的长度

可以利用下边的程序自行测试:

#include <stdio.h>

int main()
{
    char a[10];

    printf("Please input a string:");
    scanf("%s",a);
    //gets(a);
    printf("The string is %s",a);
    return 0;
}

字符串操作函数

可以看这篇文章

指针数组

数组中的各个元素都是字符指针,就称该数组为字符指针数组,或者是指针数组。看下边的程序:

#include <stdio.h>

int main()
{
    char a[][10] = {"book","desk","light"};
    char *b[] = {"book","desk","light"};

    for (int i = 0; i < 3; i++)
        printf("%s\n",a[i]);

    for (int i = 0; i < 3; i++)
        printf("%s\n",b[i]);

    return 0;
}

结果为:

book
desk
light
book
desk
light

从上边的结果可以看出:

  • char a[][n],char *a[] 两种形式都能够表示指针数组
  • 可以认为指针数组就是二维数组和字符数组的结合
发布了77 篇原创文章 · 获赞 5 · 访问量 4867

猜你喜欢

转载自blog.csdn.net/SAKURASANN/article/details/104524309