云计算百科
云计算领域专业知识百科平台

C语言基础知识(一)————各类符号的含义与输入输出库(stdio)

前言

在编写 C 语言程序之前,我们需要先导入程序运行所需的库,这些库也被称为头文件。本篇基础知识将以 C 语言标准输入输出库 stdio.h 为例进行讲解。

一、占位符:

与 Java 不同,在 C 语言中,占位符用于 printf、scanf 这类格式化输入输出函数,用来标记数据的位置与数据类型。在 printf 输出时,占位符所在的位置会被替换为变量的值;在 scanf 输入时,占位符则代表需要从控制台读取对应类型的数据并存入变量。

C++ 中存在两套 IO 体系:如果沿用 C 风格的 printf/scanf,占位符的用法和规则与 C 语言完全一致;如果使用 C++ 原生的 cout 与 cin 流输入输出,则无需占位符,系统会自动识别变量的数据类型。

在 C 语言中,变量必须先声明后使用,声明时需要指定其数据类型。数据类型决定了变量在内存中占用的字节数、取值范围以及可进行的运算。下面列出 C 语言中常见的变量类型:

数据类型关键字占用字节数(32位系统)取值范围(大致)
短整型 short 2 字节 -32768 ~ 32767
整型 int 4 字节 -2147483648 ~ 2147483647
长整型 long 4 字节(32位)/ 8 字节(64位) 取决于系统位数
长长整型 long long 8 字节 -9223372036854775808 ~ 9223372036854775807
无符号整型 unsigned int 4 字节 0 ~ 4294967295
单精度浮点型 float 4 字节 约 3.4e-38 ~ 3.4e38
双精度浮点型 double 8 字节 约 1.7e-308 ~ 1.7e308
字符型 char 1 字节 -128 ~ 127(或 0 ~ 255)
字符串 char[] 取决于长度 由字符数组存储
指针 void* / 类型* 4 字节(32位)/ 8 字节(64位) 内存地址

注意:上表中的字节数基于常见的 32 位系统,实际大小可能因编译器和操作系统而异。可以使用 sizeof(类型) 运算符在程序中获取某个类型实际占用的字节数。

总而言之,在 C 和 C++ 语言中,占位符就是变量位置的替代品。不同变量对应的占位符如下表所示:

数据类型占位符说明
int %d 输出/输入十进制整数
long %ld 输出/输入长整型整数
long long %lld 输出/输入长长整型整数
unsigned int %u 输出/输入无符号十进制整数
float %f 输出/输入单精度浮点数
double %lf 输出/输入双精度浮点数(scanf 中必须用 %lf)
char %c 输出/输入单个字符
char[](字符串) %s 输出/输入字符串
void*(指针) %p 输出指针地址
short %hd 输出/输入短整型整数
unsigned long %lu 输出/输入无符号长整型整数
unsigned long long %llu 输出/输入无符号长长整型整数
double(printf 输出) %e / %E 以科学计数法输出浮点数
double(printf 输出) %g / %G 根据数值大小自动选择 %f 或 %e 输出
int(八进制) %o 以八进制形式输出整数
int(十六进制) %x / %X 以十六进制形式输出整数(小写/大写字母)

二、转义符:

在 C 语言中,转义字符以反斜杠 \\ 开头,其核心作用是改变紧跟在反斜杠后面的字符原本的含义。有些字符无法直接写在字符串中,或者本身在 C 语言中具有特殊语法作用,此时就需要借助转义符来表示。

举个例子:双引号 " 是字符串的边界标记,如果直接写在字符串内部,编译器会误认为字符串提前结束,从而引发编译错误;此时使用 \\",反斜杠会告诉编译器,这个双引号只是普通字符,并非字符串结束符,最终就能正常输出双引号。再比如换行操作,我们无法直接在双引号包裹的字符串中敲回车换行,使用 \\n 就可以实现换行功能。

除了 \\" 和 \\n 之外,还有很多常用转义字符:\\r 代表回车,将光标移到当前行的开头;\\t 是水平制表符,相当于按下 Tab 键,用来做文本对齐;\\\\ 用来输出反斜杠本身;\\0 是空字符,作为 C 语言字符串的结束标记,是字符串必不可少的终止符号。

简单来说,转义字符解决了两类问题:一是表示无法直接输入、不可见的控制字符(如换行、制表、字符串结束符等);二是转义 C 语言中自带特殊含义的符号(如双引号、反斜杠等),让它们不再承担语法功能,而是单纯作为普通字符输出。

转义符含义说明
\\n 换行 将光标移到下一行开头
\\t 水平制表符 将光标移到下一个制表位(相当于按 Tab 键)
\\\\ 反斜杠 输出一个反斜杠 \\ 本身
\\" 双引号 在字符串中输出双引号 "
\\' 单引号 在字符中输出单引号 '
\\r 回车 将光标移到当前行开头
\\b 退格 将光标向左移动一格
\\f 换页 将光标移到下一页开头(常用于打印机)
\\a 响铃 发出提示音(部分终端有效)
\\v 垂直制表符 将光标移到下一个垂直制表位
\\0 空字符 字符串结束标志(ASCII 码为 0)
\\xhh 十六进制转义 输出 ASCII 码为十六进制 hh 的字符,如 \\x41 输出 A
\\ooo 八进制转义 输出 ASCII 码为八进制 ooo 的字符,如 \\101 输出 A

注意:转义符必须写在双引号或单引号内才会生效。例如 printf("第一行\\n第二行"); 会在输出时换行。

三、头文件:<stdio.h> 标准输入输出库

该库包含的函数有:printf、scanf、fgets、fputs 等。

  • printf
  • printf 是输出打印语句,一般写法为 printf("想输出的内容");。如果涉及到变量,则写为 printf("内容+变量所对应的占位符", 变量);。

    下面给出几个 printf 的代码示例:

    #include <stdio.h>

    int main() {
    int age = 18;
    double score = 92.5;
    char grade = 'A';
    char name[] = "小明";

    // 1. 输出纯文本
    printf("Hello, World!\\n");

    // 2. 输出变量(占位符对应变量)
    printf("年龄:%d\\n", age);

    // 3. 多个占位符,按顺序对应多个变量
    printf("姓名:%s,成绩:%.1f,等级:%c\\n", name, score, grade);

    // 4. 占位符也可以直接放常量或表达式
    printf("两数之和:%d\\n", 10 + 5);

    return 0;
    }

    运行结果:

    Hello, World!
    年龄:18
    姓名:小明,成绩:92.5,等级:A
    两数之和:15

    注意:%.1f 表示保留一位小数;\\n 是换行符。占位符的数量、顺序必须与后面的变量一一对应,否则输出结果会错乱。

  • scanf
  • scanf 用来从键盘读取用户输入的数据并存储在变量中,格式为 scanf("变量对应的占位符", &变量);。

    但是,使用 scanf 存储内容时存在一个问题:如果存储的是字符串,且输入中包含空格,则无法存储空格后面的内容。例如:

    #include <stdio.h>
    int main(){
    char a[10];
    scanf("%s",&a);
    printf("%s",a);
    }

    结果:

    hello world
    hello

    在这里插入图片描述

    这时候,我们就可以使用一个新的函数来解决这个问题。

  • fgets
  • fgets 用来从输入流中读取一行字符串,并存储到指定的字符数组中。与 scanf 不同,fgets 可以读取包含空格的整行内容,因此更适合处理带空格的字符串输入。

    fgets 的格式为 fgets(字符数组, 最大读取字符数, 输入流);。其中,第三个参数 stdin 表示从键盘标准输入读取数据。

    下面给出一个使用 fgets 读取带空格字符串的代码示例:

    #include <stdio.h>

    int main() {
    char name[50];

    printf("请输入姓名(可包含空格):");
    fgets(name, sizeof(name), stdin);

    printf("你输入的姓名是:%s", name);

    return 0;
    }

    运行结果:

    请输入姓名(可包含空格):张三 李四
    你输入的姓名是:张三 李四

    注意:fgets 会把换行符一并读入字符串,因此输出时会在末尾多出一个换行。如果想去掉末尾的换行符,可以手动将其替换为字符串结束符 \\0。此外,fgets 最多读取 最大读取字符数 – 1 个字符,剩余空间会自动补上 \\0,从而避免缓冲区溢出。

  • fputs
  • fputs 用于将字符串写入指定的输出流,其基本格式为 fputs(字符串, 输出流);。其中,第二个参数 stdout 表示输出到屏幕的标准输出。与 printf 不同,fputs 既不会自动添加换行符,也不会解析字符串中的占位符,而是将字符串内容原样输出。因此,fputs 更适合用于输出无需格式化的纯文本。

    具体来说,fputs 的返回值是 int 类型:当写入成功时返回非负值(通常是 0),当发生错误时返回 EOF(即 -1)。这一特性使得 fputs 在需要判断写入是否成功的场景下非常实用,例如在文件写入或网络传输中,可以通过检查返回值来确认数据是否完整送达。

    此外,fputs 的第二个参数不仅可以是 stdout,还可以是文件指针(如 FILE *fp),这意味着它同样适用于向文件写入字符串。与 fprintf 相比,fputs 不会对字符串中的 % 等字符做任何特殊处理,因此当字符串内容本身包含大量 % 符号(如格式化文本、日志模板)时,使用 fputs 可以避免意外的格式解析,保证内容原样输出。

    从底层实现来看,fputs 会逐个字符地将字符串写入输出流,直到遇到字符串结束符 \\0 为止,但并不会把 \\0 本身写入。这意味着它非常适合处理以 \\0 结尾的 C 风格字符串,而不需要额外指定写入长度。相比之下,fwrite 则需要显式指定每次写入的元素大小和数量,使用起来相对繁琐。因此,在需要输出一整行以 \\0 结尾的字符串时,fputs 是更简洁、更直观的选择。
    具体来说,fputs 的返回值是 int 类型:当写入成功时返回非负值(通常是 0),当发生错误时返回 EOF(即 -1)。这一特性使得 fputs 在需要判断写入是否成功的场景下非常实用,例如在文件写入或网络传输中,可以通过检查返回值来确认数据是否完整送达。

    此外,fputs 的第二个参数不仅可以是 stdout,还可以是文件指针(如 FILE *fp),这意味着它同样适用于向文件写入字符串。与 fprintf 相比,fputs 不会对字符串中的 % 等字符做任何特殊处理,因此当字符串内容本身包含大量 % 符号(如格式化文本、日志模板)时,使用 fputs 可以避免意外的格式解析,保证内容原样输出。

    #include <stdio.h>

    int main() {
    char message[] = "Hello, fputs!";

    // 输出到标准输出(屏幕)
    fputs(message, stdout);
    fputs("\\n", stdout); // 手动添加换行

    // 也可以直接输出字符串常量
    fputs("这是第二行内容。\\n", stdout);

    return 0;
    }

    运行结果:

    Hello, fputs!
    这是第二行内容。

    注意:fputs 不会自动换行,需要手动添加 \\n;同时它也不会解析 %d 这类占位符,因此不适合用于输出变量值。若需要格式化输出变量,应改用 printf。此外,fputs 与 fgets 是一对互补函数:fgets 负责从输入流读取数据,fputs 负责向输出流写入数据。

    在实际开发中,fputs 常用于以下场景:一是输出日志信息,因为日志通常不需要格式化,直接原样写入即可;二是向文件追加内容,配合文件指针可以轻松实现;三是与 fgets 配合完成文件的逐行复制。需要注意的是,fputs 写入文件时不会自动添加换行符,因此如果希望每条记录独占一行,需要在字符串末尾手动加上 \\n。

    另外,fputs 与 puts 也有明显区别:puts 只能向标准输出 stdout 写入,并且会在字符串末尾自动追加一个换行符;而 fputs 可以指定任意输出流,且不会自动换行。因此,当需要向文件或其他输出流写入内容、或希望完全控制换行行为时,应优先选择 fputs。

    练习

    1.定义不同类型的变量并输出他们的值和所占字节数
    2.输入圆的半径,计算并输出圆的周长和面积
    3.输入一个三位数,将其百位十位个位分别输出

    1.定义不同类型的变量并输出他们的值和所占字节数

    在 C 语言中,变量必须先声明后使用,声明时需要指定其数据类型。数据类型决定了变量在内存中占用的字节数、取值范围以及可进行的运算。下面列出 C 语言中常见的变量类型:

    数据类型关键字占用字节数(32位系统)取值范围(大致)
    短整型 short 2 字节 -32768 ~ 32767
    整型 int 4 字节 -2147483648 ~ 2147483647
    长整型 long 4 字节(32位)/ 8 字节(64位) 取决于系统位数
    长长整型 long long 8 字节 -9223372036854775808 ~ 9223372036854775807
    无符号整型 unsigned int 4 字节 0 ~ 4294967295
    单精度浮点型 float 4 字节 约 3.4e-38 ~ 3.4e38
    双精度浮点型 double 8 字节 约 1.7e-308 ~ 1.7e308
    字符型 char 1 字节 -128 ~ 127(或 0 ~ 255)
    字符串 char[] 取决于长度 由字符数组存储
    指针 void* / 类型* 4 字节(32位)/ 8 字节(64位) 内存地址

    注意:上表中的字节数基于常见的 32 位系统,实际大小可能因编译器和操作系统而异。可以使用 sizeof(类型) 运算符在程序中获取某个类型实际占用的字节数。

    下面给出一个完整的代码示例,演示如何定义不同类型的变量,并使用 sizeof 运算符输出它们的值和所占字节数:

    #include <stdio.h>

    int main() {
    // 定义不同类型的变量
    short s = 10;
    int i = 100;
    long l = 100000L;
    long long ll = 10000000000LL;
    unsigned int ui = 3000000000U;
    float f = 3.14f;
    double d = 3.14159265358979;
    char c = 'A';
    char str[] = "Hello";
    int *p = &i;

    // 输出变量的值
    printf("short 变量 s 的值:%hd\\n", s);
    printf("int 变量 i 的值:%d\\n", i);
    printf("long 变量 l 的值:%ld\\n", l);
    printf("long long 变量 ll 的值:%lld\\n", ll);
    printf("unsigned int 变量 ui 的值:%u\\n", ui);
    printf("float 变量 f 的值:%f\\n", f);
    printf("double 变量 d 的值:%lf\\n", d);
    printf("char 变量 c 的值:%c\\n", c);
    printf("字符串 str 的值:%s\\n", str);
    printf("指针 p 指向的地址:%p\\n", (void*)p);

    // 输出各变量所占的字节数
    printf("\\n各变量所占字节数:\\n");
    printf("short 占 %zu 字节\\n", sizeof(s));
    printf("int 占 %zu 字节\\n", sizeof(i));
    printf("long 占 %zu 字节\\n", sizeof(l));
    printf("long long 占 %zu 字节\\n", sizeof(ll));
    printf("unsigned int 占 %zu 字节\\n", sizeof(ui));
    printf("float 占 %zu 字节\\n", sizeof(f));
    printf("double 占 %zu 字节\\n", sizeof(d));
    printf("char 占 %zu 字节\\n", sizeof(c));
    printf("字符串 str 占 %zu 字节\\n", sizeof(str));
    printf("指针 p 占 %zu 字节\\n", sizeof(p));

    return 0;
    }

    运行结果(在 64 位系统上):

    short 变量 s 的值:10
    int 变量 i 的值:100
    long 变量 l 的值:100000
    long long 变量 ll 的值:10000000000
    unsigned int 变量 ui 的值:3000000000
    float 变量 f 的值:3.140000
    double 变量 d 的值:3.141593
    char 变量 c 的值:A
    字符串 str 的值:Hello
    指针 p 指向的地址:0x7ffd12345678

    各变量所占字节数:
    short 占 2 字节
    int 占 4 字节
    long 占 8 字节
    long long 占 8 字节
    unsigned int 占 4 字节
    float 占 4 字节
    double 占 8 字节
    char 占 1 字节
    字符串 str 占 6 字节
    指针 p 占 8 字节

    注意:sizeof 返回的是 size_t 类型,因此使用 %zu 作为占位符输出。字符串 str 占 6 字节,是因为它包含 5 个字符加上末尾的字符串结束符 \\0。指针的大小取决于系统位数,在 64 位系统上为 8 字节,在 32 位系统上为 4 字节。

    2.输入圆的半径,计算并输出圆的周长和面积

    输入值并以这个值进行运算,这时候我们需要用到scanf。输出周长和面积则需要我们printf和数学公式
    在这里插入图片描述
    结果为:
    在这里插入图片描述

    3.输入一个三位数,将其百位十位个位分别输出

    这时候我们有两种思路。
    第一种,用数字运算,采用取余整除的方式:
    在这里插入图片描述
    第二种,用数组的方式,我们可以将输入的三位数看作是一个数组,然后读取即可
    在这里插入图片描述
    在这里插入图片描述

    可能有人会问了,我们为什么要减去这个’0’呢?
    我们先记住:‘0’ 是字符0,不是数字0。计算机内存里所有字符存的都是ASCII码。
    字符’0’的ASCII码是 48
    字符’1’的ASCII码是 49
    字符’2’的ASCII码是 50
    ……
    字符’9’的ASCII码是 57

    当我们用%s读取输入123到字符数组里:
    num[0]里面存的并不是整数1,而是字符’1’,它对应的ASCII码是49。
    如果你直接printf(“%d”, num[0]),输出的会是49,而不是我们想要的1。

    ‘1’ – ‘0’ 等价于 49 – 48 = 1
    用字符减去’0’,本质就是用ASCII码相减,把数字字符转换成真正的整型数字。
    下面是不写减去’0’的代码结果:
    在这里插入图片描述

    总结

    这篇文章讲解了 C 语言标准输入输出库 <stdio.h> 的基础知识,核心内容可总结为三部分:

    一、占位符:用于 printf/scanf 等格式化函数,标记数据位置与类型。文中给出了完整对照表,覆盖 int(%d)、long(%ld)、float(%f)、double(%lf)、char(%c)、字符串(%s)、指针(%p)等常用类型,并说明 C++ 沿用 C 风格时规则一致。

    二、转义符:以反斜杠 \\ 开头,用于表示无法直接输入的字符或转义特殊符号。表格列出了 \\n(换行)、\\t(制表符)、\\(反斜杠)、"(双引号)、\\0(字符串结束符)等常用转义符及其含义。

    三、头文件 <stdio.h> 的四个核心函数:
    printf:格式化输出,支持占位符与变量一一对应,附有完整代码示例;
    scanf:从键盘读取输入,但无法读取含空格的字符串;
    fgets:可读取包含空格的整行字符串,更适合处理带空格的输入;
    fputs:向输出流原样写入字符串,不解析占位符、不自动换行,适合输出纯文本或写文件。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » C语言基础知识(一)————各类符号的含义与输入输出库(stdio)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!