Skip to content

字符串与输入输出

C语言中的字符串是一个比较让人头疼的问题。首先,C语言中没有独立的字符串数据类型,所以你需要使用「字符数组」来表示字符串。

这太反人类了!

字符数组

在C语言中,单引号''包裹起来的将被视作字符,双引号""包裹起来的将被视作字符串。

字符串需要存储在字符数组中。字符类型即char,你可以通过如下方式定义单个字符和字符数组:

c
char i1 = 'Q';
char i2 = 'A';
char i3 = 'Q';

char qaq1[4] = {'Q', 'A', 'Q', '\0'};
char qaq2[4] = "QAQ";

字符数组的长度即字符串的长度。但是,C语言要求字符串的末尾(即最后一个有效字符)的后面需要跟一个\0,表示字符串结束。因此我们看起来长度为3的QAQ需要定义在长度为4的字符数组中。

在按照第5行的方式依次给出字符时,需要在最后一位给出\0;按照第6行的方式使用双引号直接给出字符串,则无需手动给出\0。字符数组的长度可以更长,对于QAQ来说,数组的长度只需要大于3即可,是4或是400都是合法的。

一定要有\0吗?

是的,C语言中字符串或字符数组必须要以\0作为结尾。

C语言需要通过\0来判断字符串的结束位置;否则,在程序运行的过程中可能会出现意外错误,并且在不同的环境中可能出现不同的意外错误。

输入输出

输出字符串

标准库函数printf用于在控制台打印字符串。你不能像其他语言的printlog那样随便传各种类型的值,只能传递字符串。

但是你可以通过格式控制符将其他数据(包括其他字符串)嵌入到字符串中:

c
#include <stdio.h>

int main(void){
    int a = 5;
    char string[20] = "Are you OK?";
    char c = 'A';
    double pi = 3.14;
    printf("数字是 %d 字符串是 %s 字符是 %c 圆周率是 %lf\n", a, string, c, pi);
    return 0;
}
bash
数字是 5 字符串是 Are you OK? 字符是 A 圆周率是 3.140000

以下是C语言中支持的格式控制说明符:

  • %d - 有符号十进制整数
  • %u - 无符号十进制整数
  • %s - 字符串
  • %c - 字符
  • %ld - 浮点数(小数形式)
  • %e - 科学计数法(小写e
  • %E - 科学计数法(大写E
  • %p - 指针地址

然后,作为格式控制说明符,你还可以控制打印格式。

对于整数,%5d指定了最小输出宽度,整数在打印时若宽度不够,则会在左边补空格以达到5宽度。如果需要在左边补0而不是空格,则可以使用%05d

对于浮点数,%.2lf指定了保留两位小数,%6.2f指定了宽度为6且保留两位小数。

对于字符串,同样可以使用%10.6s来限制其宽度为10,截断输出前6个字符。

c
#include <stdio.h>

int main(void){
    int a = 5;
    char string[20] = "Are you OK?";
    char c = 'A';
    double pi = 3.14;
    printf("数字是 %d 字符串是 %s 字符是 %c 圆周率是 %lf\n", a, string, c, pi);
    printf("数字不仅是 %5d 还是 %05d\n", a, a);
    printf("圆周率是 %.2lf 还是 %6.2lf\n", pi, pi);
    printf("字符串是 %10.6s 还是 %.2s\n", string, string);
    return 0;
}
bash
数字是 5 字符串是 Are you OK? 字符是 A 圆周率是 3.140000
数字不仅是     5 还是 00005
圆周率是 3.14 还是   3.14
字符串是     Are yo 还是 Ar

另外,你可以使用%-5d来让数字在宽度为5输出时靠左(空格在右)而不是%5d一样靠右(空格在左),对于整形和字符串也是一致。

按照顺序,依次传入每个格式控制符对应的变量,程序在运行时会将变量嵌入字符串中并进行输出。

输入

你可以使用标准库函数scanf从控制台接收用户传入的内容。scanf的使用与printf有一定区别需要注意。

c
#include <stdio.h>

int main(void){
    int a;
    double pi;
    scanf("%d %lf", &a, &pi);
    printf("a = %d, pi = %lf\n", a, pi);
}
bash
6 3.14159
a = 6, pi = 3.141590

scanf的首个参数是字符串,规定了接收控制台传入参数的格式,并且使用格式控制说明符。用户按照格式传入参数之后,scanf从中提取出想要的参数,赋值到scanf的第二个即往后的传入地址中。

scanf接收的第二个即更多参数需要是指针类型,scanf会把用户从控制台传入的变量分别赋值到地址中。

于是我们得到了如下规范:

  • 不可以在scanf的首个字符串参数中填写说明。 因为不像Python中的input可以传入输入说明,C中的scanf的首个字符串参数是不会在控制台中显示,而仅用作传入参数的匹配提取的。
    • 这意味着如果你使用scanf("请输入a的值:%d", &a),则用户需要在控制台完整输入请输入a的值:6,显然程序没有按照期望运行。
  • 必须在scanf中传入待赋值变量的指针。 且,在前一节数组中我们知道,数组会在被作为参数传入函数时退化成其头指针,因此接收字符数组(字符串)时无需特地求其地址。
c
#include <stdio.h>

int main(void){
    int a;
    double pi;
    scanf("请输入两个变量的值:%d %lf", &a, &pi);
    printf("a = %d, pi = %lf\n", a, pi);
}
bash
请输入两个变量的值:6 3.14159
a = 6, pi = 3.141590
bash
6 3.14159
a = 0, pi = 0.000000

从上面可以看出,在匹配提取参数失败时,scanf不会出现错误。

下面是合理的传入字符串参数的实现:

c
#include <stdio.h>

int main(void){
    char str[100];
    printf("请输入一个字符串:");
    scanf("%s", str);
    printf("你输入的字符串是:%s\n", str);
}
bash
mangofanfan@LAPTOP-MREQPRK3:~/CTest$ ./02_io 
请输入一个字符串:你好?
你输入的字符串是:你好?

在上面,我们使用printf提供了需要用户输入字符串时的提示文本。字符串你好?由用户输入,在C语言中,汉字占用的字符长度根据编码决定,例如在目前广为常用的UTF-8编码下一个汉字占用3字符,则你好?至少需要用长度为10的字符数组存储;而稍久远的GBK编码中则占用2字符,则你好?至少需要用长度为7的字符数组存储。

贡献者

页面历史