前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >[c语言日寄]兼顾简约与逼格的EOF判定法

[c语言日寄]兼顾简约与逼格的EOF判定法

作者头像
siy2333
发布2025-02-05 12:46:29
发布2025-02-05 12:46:29
8700
代码可运行
举报
文章被收录于专栏:来自csdn的博客来自csdn的博客
运行总次数:0
代码可运行

背景介绍

在今天的快乐刷题中,我发现一位大佬的解法非常有意思,让我们先看看题目:

题目

题目
题目

普通思路

显而易见,需要我们使用scanf的返回值来进行循环的控制。点此跳转:关于scanf返回值的前情提要

代码语言:javascript
代码运行次数:0
复制
while (scanf("%d", &t) == 1){}

这个基于这个循环模块,我们可以很轻松的完成题目的要求。

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>

int main() {
    int t;
    while (scanf("%d", &t) == 1) {
        if(t > 0) printf("1\n");
        else if(t < 0)printf("0\n");
        else printf("0.5\n");
    }
    return 0;
}
普通通过
普通通过

大佬思路

秉持着人外有人,天外有天的原则,我点开题解,去寻找更 牛逼 高级 的解法。

榜一大佬的代码是这样的:

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
main()
{
    int t;
    while(~scanf("%d\n",&t))
    {
        if(t>0)
            printf("1\n");
        else if(t==0)
            printf("0.5\n");
        else
            printf("0\n");
    }
}

不难发现,他与我的代码高度相似,除了一个部分:

代码语言:javascript
代码运行次数:0
复制
   while(~scanf("%d\n",&t))

这是啥?刚刚看到的时候我一脸懵逼。

代码解析

我们知道,‘~’在c语言中的作用是按位取反,但while的接受的是布尔值啊?取反不应该使用逻辑取反符号‘!’吗?

不对不对,这里一定另有玄机。

scanf 返回值分析

众所周知:scanf返回值是成功实际接受到的参数数量,此时,我们只用scanf接收了一个参数,那么 scanf的返回值始终 <= 1。

这也就是这个语句的关键!

我们可以列出scanf返回值的所有可能情况: 当scanf正确接收了一个参数,返回1; 当scanf读取错误,返回EOF; 当scanf接收到文件结束符,返回EOF;

没错!scanf只会有两种可能的返回值! EOF的值是什么?在大部分的情况下是-1。

即scanf的返回值是1或者-1。

按位分析

那么,接下来思路就清晰了,观察按位取反符‘~’的作用:

在计算机中,整数通常使用补码(two’s complement)形式来表示负数。对于-1的真值,即其补码表示,如下:

对于一个8位整数(一个字节),-1的补码表示是11111111。

对于一个16位整数,-1的补码表示是1111111111111111。

对于一个32位整数,-1的补码表示是11111111 11111111 11111111 11111111。

对于一个64位整数,-1的补码表示是1111111111111111 1111111111111111 1111111111111111 1111111111111111。

简而言之,-1的真值(补码表示)就是所有位都是1的二进制数。 那么,-1按位取反的结果是什么呢?

没错,就是0。

0就是False,就是假,就是结束循环!

至于1按位取反,得到的是非0值,也就是真!

总结

当返回值只有-1和1时,我们可以采用按位取反符‘~’简化代码,提高逼格。

代码语言:javascript
代码运行次数:0
复制
   while(~scanf("%d\n",&t))

应用场景拓展

这个循环的应用场景通常包括:

  1. 数据输入:在需要连续输入多个整数直到用户决定停止时,可以使用这个循环。例如,在一个简单的数据收集程序中,用户可以不断地输入数字,直到输入一个特定的结束信号(比如非数字字符)。
  2. 测试和调试:在编写程序时,可能需要测试程序对不同输入的处理能力,这个循环可以用来模拟连续的输入测试。

需要注意的是,这个循环在读取失败时会立即结束,因此在使用时应该考虑到错误处理和用户输入验证的问题。此外,scanf 函数在读取失败时不会从输入流中消耗非整数字符,这可能会导致后续的 scanf 调用再次失败,因此在实际应用中可能需要额外的逻辑来处理这种情况。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景介绍
    • 题目
    • 普通思路
    • 大佬思路
  • 代码解析
    • scanf 返回值分析
    • 按位分析
  • 总结
    • 应用场景拓展
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档