C Primer Plus 第4章——第二篇

你该逆袭了

第4章:重点摘录

  • [五、scanf( )](#五、scanf( ))
    • [1、使用 scanf( )](#1、使用 scanf( ))
      • [(1)转换说明 *](#(1)转换说明 *)
      • [(2)转换说明 数字](#(2)转换说明 数字)
      • [(3)转换说明 hh](#(3)转换说明 hh)
      • [(4)scanf 中其他的转换说明,不作详细解释,用到的时候再去学习即可](#(4)scanf 中其他的转换说明,不作详细解释,用到的时候再去学习即可)
    • [2、从 scanf( ) 角度 看 输入](#2、从 scanf( ) 角度 看 输入)
    • 3、格式字符串中的普通字符
    • 4、scanf()的返回值
  • [六、printf( ) 和 scanf( ) 的 * 修饰符](#六、printf( ) 和 scanf( ) 的 * 修饰符)
    • [1、printf( ) 中 * 的用法](#1、printf( ) 中 * 的用法)
    • [2、scanf( ) 中 * 的用法](#2、scanf( ) 中 * 的用法)
  • 七、本地化设置
  • [八、第四章的 关键概念](#八、第四章的 关键概念)
  • 九、本章小结

五、scanf( )

1、使用 scanf( )

c 复制代码
#include <stdio.h>

int main()
{
    int age = 0;
    float assets = 0;
    char pet[30] = { 0 };

    printf("Enter your age,assets,and favourite pet.\n");
    scanf("%d %f", &age, &assets);
    scanf("%s", pet);
    printf("%d $%.2f %s\n", age, assets, pet);

    return 0;
}
// scanf()函数使用 空白(换行符、制表符、空格)把输入分成多个字段。
// 在 依次把转换说明和字段匹配 时跳过空白。

// 注意:只要在每个输入项之间输入 至少一个 换行符、空格、制表符 即可,可以在一行或多行输入。

// 唯一例外的是 %c 转换说明。
// 根据 %c ,scanf() 会读取每个字符,包括 空白。

// scanf() 函数所用的转换说明与 printf() 函数 几乎相同。
// 主要区别:
// 对于 float类型 和 double类型 ,
// printf() 都使用 %f、%e、%E、%g 和 %G 转换说明。
// 而 scanf() 函数 只把它们用于 float 类型,
// 对于 double 类型 时,要使用 l 修饰符。


scanf()函数使用 空白(换行符、制表符、空格)把输入分成多个字段。

在 依次把转换说明和字段匹配 时跳过空白。

注意:只要在每个输入项之间输入 至少一个 换行符、空格、制表符 即可,可以在一行或多行输入。

唯一例外的是 %c 转换说明。

根据 %c ,scanf() 会读取每个字符,包括 空白。

scanf() 函数所用的转换说明与 printf() 函数 几乎相同。
主要区别:
对于 float类型 和 double类型 ,
printf() 都使用 %f、%e、%E、%g 和 %G 转换说明。
而 scanf() 函数 只把它们用于 float 类型,
对于 double 类型 时,要使用 l 修饰符。



(1)转换说明 *

转化说明 *

含义:抑制赋值

示例:"%*d"

scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n

在程序需要读取文件中特定列的内容时,这项跳过功能很有用。

c 复制代码
 //转化说明 * 
 //含义:抑制赋值   
 //示例:"%*d"    

//P96 程序清单 4.17
//跳过输入中的前两个整数

#include <stdio.h>

int main()
{
    int n;

    printf("Please enter three integers:\n");
    scanf("%*d %*d %d", &n);                   //2014 2014 2015
    printf("The last integer was %d\n", n);    //2015

    return 0;
}
//scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n
//在程序需要读取文件中特定列的内容时,这项跳过功能很有用。

(2)转换说明 数字

转换说明 数字

最大字段宽度。输入达到最大字段宽度处,或第 1 次遇到 空白字符 时停止。

通过尝试:这里的 空白字符 不包括 回车,只包括 空格 和 制表符。

示例:"%10s"

c 复制代码
//转换说明 数字
//最大字段宽度。输入达到最大字段宽度处,或第 1 次遇到 空白字符 时停止。
//通过尝试:这里的 空白字符 不包括 回车,只包括 空格 和 制表符。
//示例:"%10s"

#include <stdio.h>

int main()
{
    char input[30] = { 0 };
    int ch = 0;

    //第一次遇到 空白字符 时停止

    scanf("%s", input);      //11    25
    printf("%s\n", input);   //11

    while ((ch = getchar()) != '\n')  //清空缓存区中的,上一次输入多余的东西
    {
        ;
    }

    //输入达到最大字段宽度处

    scanf("%10s", input);    //1234567890987654321
    printf("%s\n", input);   //1234567890
     
    return 0;
}

(3)转换说明 hh

转换说明 hh

把整数作为 signed char 或 unsigned char 类型读取

示例:"%hhd" "%hhu"

c 复制代码
//转换说明 hh
//把整数作为 signed char 或 unsigned char 类型读取
//示例:"%hhd" "%hhu"

#include <stdio.h>

int main()
{
    //有符号 char 的取值范围:127~-128
    //无符号 char 的取值范围:0~255

    signed char signedCharVar;
    unsigned char unsignedCharVar;

    scanf("%hhd", &signedCharVar);  // 读取一个signed char类型的值
    scanf("%hhu", &unsignedCharVar);  // 读取一个unsigned char类型的值

    //在上述代码中,%hhd 用于读取一个 signed char 类型的值,
    //而 %hhu 用于读取一个 unsigned char 类型的值。
    //这两个转换说明符,确保了即使在较大的环境中,也可以安全地读取一个字节的数据。

    printf("%c\n", signedCharVar);
    printf("%c\n", unsignedCharVar);

    return 0;
}

(4)scanf 中其他的转换说明,不作详细解释,用到的时候再去学习即可

2、从 scanf( ) 角度 看 输入

假设 scanf() 根据一个 %d 转换说明读取一个整数。

scanf() 函数每次读取一个字符,跳过所有的空白字符,直至遇到 第一个非空白字符 才开始读取。

因为要读取整数,所以 scanf() 希望发现 一个数字字符 或者 一个符号(+、-)。

如果找到一个 数字 或 符号,它便保存该字符,并读取下一个字符。

如果下一个字符是数字,它便保存该数字并读取下一个字符。

scanf() 不断地读取和保存字符,直至遇到非数字字符。

如果遇到一个非数字字符,它便认为读到了 整数的末尾。

然后,scanf() 把非数字字符放回输入。

这意味着程序在下一次读取输入时,首先读到的是上一次读取丢弃的非数字字符。 (我的理解就是:输入的数据保存在了 缓冲区 中)

最后,scanf() 计算已读取数字(可能还有符号)相应的数值,并将计算后的值放入指定的变量中。

如果使用字段宽度,scanf() 会在 字段末尾 或者 第一个空白字符处 停止读取(满足两个条件之一便停止)。

如果 第一个非空白字符 是 A 而不是 数字,会发生什么情况呢?

scanf() 将停在那里,并把 A 放回输入中,不会把值赋给变量。

程序在下一次读取输入时,首先读到的字符是 A 。

如果程序只使用 %d 转换说明,scanf() 就一直无法越过 A 读下一个字符。

另外,如果使用带多个转换说明的 scanf() ,C 规定在 第一个出错处停止读取输入。

用其他数值匹配的转换说明读取输入和用 %d 的情况相同。

区别在于 scanf() 会把更多字符识别成数字的一部分。

例如:%X 转换说明要求 scanf() 识别十六进制数 a~f 和 A~F.

浮点转换说明要求scanf() 识别小数点、e 计数法(指数计数法)和新增的 p 计数法(十六进制指数计数法)。

如果使用 %s 转换说明,scanf() 会读取 除空白以外的所有字符。

scanf() 跳过空白开始读取第一个非空白字符,并保存非空白字符直到再次遇到空白。

这意味着 scanf() 根据 %s 转换说明读取下一个单词,即不包含空白字符的字符串。

如果使用字段宽度,scanf()在字段末尾 或者 第一个空白字符 处停止读取。

无法利用字段宽度让只有一个 %s 的scanf() 读取多个单词。
最后要注意一点:
当 scanf() 把字符串放进指定数组中时间,它会在字符序列的末尾加上 '\0' ,让数组中的内容成为一个 C 字符串。

3、格式字符串中的普通字符

c 复制代码
#include <stdio.h>

int main()
{
    int a = 0;
    int b = 0;

    scanf("%d     %d", &a, &b);
    printf("%d %d\n", a, b);

    scanf("%d%d", &a, &b);
    printf("%d %d\n", a, b);

    return 0;
}

4、scanf()的返回值

六、printf( ) 和 scanf( ) 的 * 修饰符

printf ( ) 和 scanf( ) 都可以使用 * 修饰符 来修改转换说明 的含义。

但是,他们的用法不太一样。

1、printf( ) 中 * 的用法

如果你不想预先指定字段宽度,希望通过程序来指定,那么可以用 * 修饰符 代替 字段宽度。

但还是要用一个参数告诉函数,字段宽度应该是多少。

也就是说,如果转换说明是 %d ,那么参数列表中应包含 * 和 d 对应的值。

这个技巧也可以用于浮点值指定精度和字段宽度。

c 复制代码
//P94 程序清单 4.16
//如果你不想预先指定字段宽度,希望通过程序来指定,那么可以用 * 修饰符 代替 字段宽度。
//但还是要用一个参数告诉函数,字段宽度应该是多少。
//也就是说,如果转换说明是 %d ,那么参数列表中应包含 * 和 d 对应的值。
//这个技巧也可以用于浮点值指定精度和字段宽度。

#include <stdio.h>

int main()
{
    unsigned width, precision;
    int number = 256;
    double weight = 242.5;

    printf("Enter a field width:\n");
    scanf("%d", &width);                                    //6
    printf("The number is:##%*d##:\n", width, number);      //:##   256##:
    printf("Now enter a width and a precision:\n");         //8 3
    scanf("%d %d", &width, &precision);
    printf("Weight = ##%*.*f##\n", width, precision, weight);   //## 242.500##
    printf("Done!\n");

    return 0;
}
//变量 width 提供字段宽度,number 是待打印的数字。
//因为转换说明中 * 在 d 的前面,所以在 printf( ) 的参数列表中,width 在 number 的前面。

变量 width 提供字段宽度,number 是待打印的数字。

因为转换说明中 * 在 d 的前面,所以在 printf( ) 的参数列表中,width 在 number 的前面。

2、scanf( ) 中 * 的用法

scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n

在程序需要读取文件中特定列的内容时,这项跳过功能很有用。

c 复制代码
//P96 程序清单 4.17
//跳过输入中的前两个整数

#include <stdio.h>

int main()
{
    int n;

    printf("Please enter three integers:\n");
    scanf("%*d %*d %d", &n);                   //2014 2014 2015
    printf("The last integer was %d\n", n);    //2015

    return 0;
}
//scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n
//在程序需要读取文件中特定列的内容时,这项跳过功能很有用。

七、本地化设置

八、第四章的 关键概念

九、本章小结


微软雅黑字体
黑体
3号字
4号字
红色
绿色
蓝色

相关推荐
咩咩大主教2 小时前
C++基于select和epoll的TCP服务器
linux·服务器·c语言·开发语言·c++·tcp/ip·io多路复用
时光飞逝的日子2 小时前
多重指针变量(n重指针变量)实例分析
c语言·指针·多重指针·双重指针·n重指针·指针变量
Ylucius3 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
.普通人4 小时前
c语言--力扣简单题目(回文链表)讲解
c语言·leetcode·链表
星迹日4 小时前
C语言:联合和枚举
c语言·开发语言·经验分享·笔记
Huazzi.4 小时前
算法题解:斐波那契数列(C语言)
c语言·开发语言·算法
DdddJMs__1354 小时前
C语言 | Leetcode C语言题解之题409题最长回文串
c语言·leetcode·题解
元气代码鼠5 小时前
C语言程序设计(进阶)
c语言·开发语言·算法
做完作业了5 小时前
【C语言】预处理详解
c语言·预处理
aqymnkstkw7 小时前
2024年【电气试验】考试题库及电气试验模拟试题
大数据·c语言·人工智能·嵌入式硬件·安全