当前位置: 首页 > article >正文

go语言中的Scan()和Scanln()输入函数

Scan()输入函数

package main

import "fmt"

func main() {
    var a int
    var b string
    for {
       fmt.Println("请输入一个整数和一个字符串(用空格分隔):")
       fmt.Scan(&a, &b) // 直接读取输入到变量中
       fmt.Println("整数:", a)
       fmt.Println("字符串:", b)
    }
}

正确的运行结果:

在这里插入图片描述

有问题的运行结果(第一种情况):

在这里插入图片描述

为什么当我第一次输入123然后点击Enter键,再输入456然后点击Enter键,控制台正确打印出了结果,但是当我第二次输入qwe然后点击Enter键后,直接在控制台输出了上一次的结果,并且是连续输出多个?

出现这种现象的原因是 fmt.Scan 函数在读取输入时发生了错误,并且没有处理错误的情况。当输入数据格式不符合预期时,例如输入 “qwe” 而不是一个整数和一个字符串,fmt.Scan 会返回一个错误,导致读取失败。由于错误没有被处理,程序会继续循环,并且变量 a 和 b 保留了上一次的值,从而导致上一次的结果被重复输出。

具体原因分析

1.第一次输入正确

  • 你输入了 “123”,按下 Enter 键,然后再输入 “456”,按下 Enter。fmt.Scan 成功读取到整数 123 和字符串 “456”,并赋值给变量 a 和 b。
  • 程序输出:
整数: 123
字符串: 456

2.第二次输入不符合预期

  • 你输入了 “qwe” 并按下 Enter。此时,fmt.Scan 尝试读取一个整数和一个字符串,但输入的 “qwe” 无法解析为整数,因此 fmt.Scan 返回一个错误,并且 a 和 b 保留了之前的值 123 和 “456”。
  • 因为程序没有检查并处理读取失败的情况,导致循环继续进行,重复输出上一次的结果。

3.连续输出

  • 当 fmt.Scan 读取失败时,它不会从输入缓冲区中移除错误的输入(如 “qwe”),因此在下一次循环中再次读取时,仍然读取到 “qwe”,导致重复发生错误,输出同样的内容。

解决方法

需要在读取输入失败时进行错误处理,并清除输入缓冲区中的错误数据。可以使用 bufio.NewReader 来清空缓冲区,以确保下次读取时不会受之前错误输入的影响。
下面是修改后的代码示例:

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    var a int
    var b string
    reader := bufio.NewReader(os.Stdin) // 创建一个 bufio.Reader 来清除缓冲区

    for {
        fmt.Println("请输入一个整数和一个字符串(用空格分隔):")
        _, err := fmt.Scan(&a, &b)
        if err != nil {
            fmt.Println("输入格式不正确,请重新输入")
            // 清除缓冲区中的剩余内容
            reader.ReadString('\n')
            continue
        }
        fmt.Println("整数:", a)
        fmt.Println("字符串:", b)
    }
}

修改说明

1.当输入格式不正确时,程序会提示 “输入格式不正确,请重新输入”,并使用 reader.ReadString(‘\n’) 来清除输入缓冲区中剩余的内容。
2.如果读取成功,则会输出当前的 a 和 b。

总结

出现连续输出的问题是因为 fmt.Scan 在输入格式错误时,未能正确处理错误并清除输入缓冲区。通过添加错误处理和清除输入缓冲区的操作,可以避免这种情况的发生。

当 fmt.Scan 读取失败时,既然它不会从输入缓冲区中移除错误的输入(如 “qwe”),因此在下一次循环中再次读取时,仍然读取到 “qwe”,导致重复发生错误,输出同样的内容。那为什么只是重复输出了3次,而不是一直重复输出下去呢?

出现这种现象的原因在于输入缓冲区的行为和 fmt.Scan 的工作原理。每次调用 fmt.Scan,它都会尝试读取输入缓冲区中的数据并解析为指定的格式(例如整数和字符串)。当输入格式不符合要求时,fmt.Scan 会返回一个错误,并且不会从缓冲区中移除无法解析的内容,因此导致错误的输入被多次重复读取。

但是,为什么这种重复只发生了3次而不是无限次呢?这可能是因为终端的输入缓冲区管理的行为和系统处理输入的方式。以下是可能的解释:
1.输入缓冲区的限制

  • 操作系统或终端在处理输入缓冲区时,可能会对输入尝试的次数做出限制。如果连续多次读取失败,它可能会触发某种输入错误处理机制,导致程序的行为变化。

2.标准输入的阻塞行为

  • 当使用 fmt.Scan 时,它会阻塞等待用户输入。虽然输入流中有残留数据(例如 “qwe”),但经过一定次数的错误读取后,可能输入流被清理,或者终端要求重新输入。因此,程序会暂停,等待用户输入新的数据。

3.自动错误处理机制

  • 某些终端会自动进行错误数据的处理,或者根据缓冲区中的内容进行自动清空。当检测到多次重复输入失败时,可能会重置缓冲区的状态。
    因此,尽管在程序逻辑上看起来应该无限循环,但因为终端或缓冲区管理的机制,导致这种重复输出的次数有限。

有问题的运行结果(第二种情况):
在这里插入图片描述
在这里插入图片描述

Scanln()输入函数

package main

import "fmt"

func main() {
    var a int
    var b string
    for {
       fmt.Println("请输入一个整数和一个字符串(用空格分隔,并按回车结束):")
       fmt.Scanln(&a, &b) // 直接读取输入到变量中
       fmt.Println("整数:", a)
       fmt.Println("字符串:", b)
    }
}

正确的结果:

在这里插入图片描述

错误的结果:

在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/370760.html

相关文章:

  • 微服务中引入消息队列的利弊
  • 虚拟拨号技术(GOIP|VOIP)【基于IP的语音传输转换给不法分子的境外来电披上一层外衣】: Voice over Internet Protocol
  • nginx 的基础语法学习,零基础学习
  • 增广卡尔曼滤波AKF的要点分析
  • springMVC实现文件上传
  • 2.slf4j入口
  • NLTK无法下载?
  • 超好玩又简单-猜数字游戏(有手就行)
  • 关于sse、websocket与流式渲染
  • Spring SPI、Solon SPI 有点儿像(Maven 与 Gradle)
  • zookeeper全系列学习之分布式锁实现
  • Java 实现协同过滤算法推荐算法
  • 【Linux】基础IO-下
  • STM32-Cube定时器TIM
  • 前端性能优化——加载性能优化
  • 代码学习:如何阅读开源代码
  • 行为设计模式 -命令模式- JAVA
  • 青少年编程与数学 02-002 Sql Server 数据库应用 17课题、事务处理
  • go语言多态性(接口interface)的使用
  • 雷池社区版compose配置文件解析-mgt
  • Spring Boot技术栈在论坛网站开发中的应用
  • WPF样式
  • dependencyManagement保持maven的多模块依赖版本一致
  • 【PnP】详细公式推导,使用DLT直接线性变换法求解相机外参
  • SpringBoot高级-底层原理
  • 详解Linux集群技术