首页 > 其他分享 >深入学习scanf()的使用方法

深入学习scanf()的使用方法

时间:2024-11-23 14:36:02浏览次数:2  
标签:int scanf printf 学习 num 深入 output input

众所周知,C语言的scanf()位于<stdio.h>,用于输入数据,但一直以来我都对它的使用方式似懂非懂,今天我们来详细聊聊它。
scanf意为“scan format”, 即格式化输入,原型如下:

int scanf(const char *format, ...);

一、基础使用方式

#include <stdio.h>
int main() {
  int num = 0;
  scanf("%d", &num); // 一定注意要使用&传递指针,以在scanf()中修改num的值,这是特别易错点
  printf("%d\n", num); // 注意printf() 与 scanf()的调用差异,也很容易错
  return 0;
}

二、scanf()的返回值

成功时,scanf()会返回成功匹配与赋值的个数; 如果遇到EOF,会返回EOF,

/***
  * brief : check the return-val of scanf();
  * input-1 : 0 1 2
  * output-1: 3
  * conclusion: On success, scanf() will return the number of input items successfully matched and assigned.
  * input-2 : <EOF>
  * output-2: -1
  */
void return_val() {
    int num = 0;
    int ret = 0;
    ret = scanf("%d%d%d", &num, &num, &num); // input-1 : 0 1 2
    printf("%d\n", ret); // output-1: 3
}

关于EOF:

// EOF定义在stdio.h中,如下
/* The value returned by fgetc and similar functions to indicate the
   end of the file.  */
#define EOF (-1)

三、scanf()的工作方式

阅读man scanf,我们可以完全了解scanf()的工作方式,但是它很难读,而这就是我写博客的意义。
stdio.h中定义了输入与输出的缓冲区(可以阅读源码),我们输入的字符就会先进入这个缓冲区。
scanf()类似于一个字符串最长优先匹配函数,会尽可能去获取最长的、符合当前需要的数据;
而且它会跳过前导空格。

#include <stdio.h>

/**
 * brief : 显示scanf()如何工作
 * input : 10.3        5 6
 * output:
 *   i = 10
 *   j = 0.300000
 *   k = 5
 * explaination:
 * scanf()首先尝试匹配一个整数,它依次看到字符'1', '0', '.',然后由于字符'.'是不应该出现在整数中的,因此它返回10
 * 然后它尝试匹配一个float,它依次看到字符'.','3',' ', 由于空格字符不会出现在小数中, 因此它返回0.3
 * 最后它尝试匹配一个整数,它会跳过前导空格,看到字符'5',' ',由于整数没有空格,因此它返回5
 * 输入缓冲区中还有字符'6', 这将是下一次scanf()开始的字符
 */

int main() {
    int i, k; float j;
    scanf("%d%f%d", &i, &j, &k); // 10.3        5 6
    printf("i = %d\nj = %f\nk = %d\n", i, j, k);
    return 0;
}

再来一个例子:

int a = 0, b = 0;
scanf("%d/%d", &a, &b); // input: 3/5
printf("%d, %d", a, b); // output: 3, 5

那么它期望的输入中,必须包含字符'/', 否则scanf()会匹配失败。

四、scanf()使用注意事项

int scanf(const char *format, ...);
  1. format字符串中转换说明的数量 必须 与后续输入变量的数量相等,否则可能导致未定义行为(undefined behaviour)。
  2. 每个<转换说明, 输入变量> 对 必须是对应的,不应该为short型使用%d(64位平台),而应该使用%hd(专用于short)。编译器可能会提示你,也有可能程序会在运行过程中崩溃 来告诉你“哪里出了问题”。
  3. scanf() 需要传递变量地址,这很容易忽略(这不是你的问题,别太担心,因为这很容易与printf混淆)

五、奇怪的、不常用的、但很有意思的scanf()可选"修饰"符

  1. 最大字段宽度(the maximum field width):限制了输入字符的数量。如果达到这个最大值,那么scanf()将返回。前导空格不计。
 /*
   * brief : test %width and sscanf()
   * input : NULL(don't need input)
   * output: 5 14 893 0 0
   * conclusion: the "width" limit the "upper" of input, and when no input, it will assign 0
   */
void test_2() {
    char str[10] = "514893";
    int arr[5] = {0};
    sscanf(str, "%1d%2d%3d%1d%1d", &arr[0], &arr[1], &arr[2],
            &arr[3], &arr[4]); // input from the string "514893"
    for (int i = 0; i < 5; i++) {
        printf("%d\n", arr[i]); // output: 5 14 893 0 0
    }
}
  1. %[ , 这是转换说明符(Conversion Specification)之一,地位等同于%d, %f, %s这种,但我之前没用过
/*
   * brief : test %[
   * input : Ai51c6
   * output: Ai
   * conclusion: it only accept alpha character, and return when meet others
   */
void test_3() {
    char str[10] = {0};
    scanf("%[a-zA-Z]", str); // input : Ai51c6
    printf("%s\n", str); // output: Ai // 这是因为碰到字符'5',它不属于a-z或A-Z区间,因此返回.
}

3.'*'可以忽略赋值(Assignment-Suppression), 即scanf()会去读取,但不会将它存储在变量中

/*
   * brief : check the Assignment-Suppression *
   * input : 1 2
   * output: 2
   * conclusion: the * tells scanf() to read the input but not store it in a variable
   */
void test_6() {
    int num = 0;
    scanf("%*d %d", &num); // input : 1 2
    printf("%d\n", num); // output: 2
}

over~

标签:int,scanf,printf,学习,num,深入,output,input
From: https://www.cnblogs.com/hk416hasu/p/18564339

相关文章

  • 2024网络安全学习路线 非常详细 推荐学习
    关键词:网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线首先咱们聊聊,学习网络安全方向通常会有哪些问题1、打基础时间太长学基础花费很长时间,光语言都有几门,有些人会倒在学习linux系统及命令的路上,更多的人会倒在学习语言上;2、知识点掌握程度不清楚对于网......
  • 代码随想录刷题学习日记
    仅为个人记录复盘学习历程,解题思路来自代码随想录代码随想录刷题笔记总结网址:代码随想录376.摆动序列如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。给定一个整数序列,......
  • 2024年最强网络安全学习路线,详细到直接上清华的教材!
     关键词:网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线首先咱们聊聊,学习网络安全方向通常会有哪些问题→CSDN官方认证Python入门资料包←点击即可获取!1、打基础时间太长学基础花费很长时间,光语言都有几门,有些人会倒在学习linux系统及命令的路上,更多的人......
  • 大学最后一年的学习规划与思考
    前三学年我的大学前三年其实是充满迷茫和犹豫的。虽然是计算机科班,但看着周围同学刷绩点的刷绩点,实习的实习,考研的考研,而我尚且不知道方向,说实话不焦虑是不可能的。我有读研深造的想法,但是大学前两年实在内耗,被知乎上的主流观点“国内教材大多是shit,要学习国外优秀课程与教材......
  • 网络安全(骇客)—技术学习
    **读者福利|***......
  • 2024-2025-1 20241318《计算机基础与程序设计》第九周学习总结
    这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP(这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK09这个作业的目标<操作系统责任内存与进程管理分时系统CPU调度文件、文件系统文件保护......
  • 人形机器人-强化学习算法-PPO算法的实现细节是否会对算法性能有大的影响.
    PPO算法是强化学习算法中目前应用最广的算法,虽然这个算法是2017年发表的,但是至今在整个AI领域下的agent子领域中这个算法都是最主要的强化学习算法(至少目前还没有之一),这个算法尤其在ChatGPT和人形机器人中起到了关键性的作用,可以说PPO算法是当前AI领域最为重要的算法之一(这个可以......
  • dotnet学习笔记-专题06-过滤器和中间件-01
    1.基本概念在ASP.NETCore中,中间件和过滤器都是处理HTTP请求的重要组件,但它们在应用中的位置、作用范围以及使用方式有所不同。1.1中间件和过滤器的区别1.1.1中间件位置与作用范围:中间件位于ASP.NETCore应用程序请求处理管道的核心位置,它可以处理进入应用程序的每一个HT......
  • C++学习笔记-Cherno C++系列
    21-23.【ChernoC++】C++中的静态(static)static变量只在编译单元内部链接静态变量的作用域只在单个文件内建议:在非特殊情况下,永远使用static定义全局变量以限制作用域全局变量重复定义/*a.cpp*/intg_Variable=5;/*main.cpp*/#include<iostream>intg_V......
  • 【电力系统短期负荷预测】基于ELM、白鲸算法优化ELM、鹭鹰算法优化ELM极限学习机的电
           ......