问题

C语言里a>b?a<c?a:b:c;这个怎么该判断?

回答
在C语言中, `a > b ? a < c ? a : b : c` 这种写法是利用了三元运算符 (?:) 的嵌套。它是一种简洁的条件表达式,用来根据条件的真假返回不同的值。理解它的关键在于一步步拆解它的逻辑。

咱们就来好好捋一捋这串表达式的判断过程,讲得透彻一些,保证让你明白它到底是怎么回事儿。

首先,我们得知道什么是三元运算符。

三元运算符 `?:` 的基本语法是这样的:

```c
条件表达式 ? 表达式1 : 表达式2
```

它的意思是:

如果 `条件表达式` 的结果是真(非零),那么整个表达式就返回 `表达式1` 的值。
如果 `条件表达式` 的结果是假(零),那么整个表达式就返回 `表达式2` 的值。

它就是一种更短、更精炼的 `ifelse` 语句,可以写在一行里,非常方便。

现在来看你给出的这个嵌套表达式:`a > b ? a < c ? a : b : c`

这个表达式有两层嵌套的三元运算符。我们要从外层开始,一层一层地剥开来看。

第一步:看最外层的三元运算符

最外层的结构是这样的:

```c
(a > b) ? (a < c ? a : b) : c
```

这里的第一个条件是 `a > b`。

情况 1:如果 `a > b` 为真(也就是 `a` 大于 `b`)

那么整个表达式就会返回冒号 `:` 后面的第一个部分,也就是 `a < c ? a : b` 这个子表达式的结果。

情况 2:如果 `a > b` 为假(也就是 `a` 不大于 `b`,即 `a <= b`)

那么整个表达式就会直接返回冒号 `:` 后面的第二个部分,也就是 `c`。

第二步:深入分析当 `a > b` 为真时的子表达式

如果 `a > b` 为真,我们就需要计算 `a < c ? a : b` 这个子表达式。这个子表达式本身也是一个三元运算符。

这里的条件是 `a < c`。

子情况 1.1:如果 `a < c` 为真(也就是 `a` 小于 `c`)

那么 `a < c ? a : b` 这个子表达式就会返回冒号 `:` 后面的第一个部分,也就是 `a`。

子情况 1.2:如果 `a < c` 为假(也就是 `a` 不小于 `c`,即 `a >= c`)

那么 `a < c ? a : b` 这个子表达式就会返回冒号 `:` 后面的第二个部分,也就是 `b`。

总结一下上面两种情况的结果:

如果 `a > b` 为真,并且 `a < c` 也为真: 最终结果是 `a`。
如果 `a > b` 为真,但是 `a < c` 为假(即 `a >= c`): 最终结果是 `b`。

第三步:结合所有情况,给出完整的判断逻辑

现在我们把上面分析的所有情况串联起来,就能得到完整的判断过程:

1. 首先判断 `a > b`。
2. 如果 `a` 不大于 `b` (即 `a <= b`),那么整个表达式的值就是 `c`。
3. 如果 `a` 大于 `b` (即 `a > b`),那么需要继续判断 `a < c`。
如果此时 `a` 也小于 `c` (即 `a > b` 且 `a < c`),那么整个表达式的值就是 `a`。
如果此时 `a` 不小于 `c` (即 `a > b` 且 `a >= c`),那么整个表达式的值就是 `b`。

换句话说,这个表达式的目的是找到三个数 `a`, `b`, `c` 中的“中间值”(或者说在特定条件下返回某个值)。

我们也可以把它改写成更易读的 `ifelse ifelse` 结构来理解:

```c
int result;
if (a > b) { // 外层判断:a是否大于b
if (a < c) { // 内层判断:如果a大于b,再判断a是否小于c
result = a; // 如果a大于b且a小于c,那么结果是a
} else { // 如果a大于b,但a不小于c (即a >= c)
result = b; // 那么结果是b
}
} else { // 如果a不大于b (即a <= b)
result = c; // 那么结果是c
}
```

我们再举个例子来具体演示一下:

假设 `a = 5`, `b = 3`, `c = 7`

1. 先判断 `a > b`: `5 > 3` 是 真。
2. 因为第一步为真,所以看第二部分子表达式 `a < c ? a : b`。
3. 判断 `a < c`: `5 < 7` 是 真。
4. 因为子表达式的条件为真,所以返回子表达式的第一个值,即 `a`。
5. 所以整个表达式 `a > b ? a < c ? a : b : c` 的结果是 `5`。

再换一组数据: `a = 5`, `b = 3`, `c = 2`

1. 先判断 `a > b`: `5 > 3` 是 真。
2. 因为第一步为真,所以看第二部分子表达式 `a < c ? a : b`。
3. 判断 `a < c`: `5 < 2` 是 假。
4. 因为子表达式的条件为假,所以返回子表达式的第二个值,即 `b`。
5. 所以整个表达式 `a > b ? a < c ? a : b : c` 的结果是 `3`。

再换一组数据: `a = 3`, `b = 5`, `c = 7`

1. 先判断 `a > b`: `3 > 5` 是 假。
2. 因为第一步为假,所以直接返回冒号 `:` 后面的第二个值,即 `c`。
3. 所以整个表达式 `a > b ? a < c ? a : b : c` 的结果是 `7`。

需要注意的点:

可读性问题: 尽管三元运算符很简洁,但嵌套过多会让代码难以阅读和理解,尤其对于初学者。在实际开发中,如果逻辑比较复杂,还是建议使用 `ifelse` 结构,以提高代码的可维护性。
优先级: 在这个表达式中,三元运算符的优先级并不需要我们特别去关心,因为括号明确了先后的判断顺序。但要知道,在没有括号的情况下,表达式的解析顺序是从左到右。

总而言之,`a > b ? a < c ? a : b : c` 这个表达式的核心就是根据 `a > b` 这个最外层条件来决定是继续评估内层还是直接返回 `c`,而内层评估 `a < c` 的结果又决定了最终返回 `a` 还是 `b`。希望这样的解释够详细,能让你彻底搞懂它!

网友意见

user avatar

恕我直言,从业十年读过的代码也不少,没见过谁这样写。把一个三元操作符构成的表达式作为另一个三元操作符的子表达式,竟然还不用小括号分开,如果谁在项目里这样写,估计会遭千夫指。

代码的可读性怎么强调都不为过。例如:

Programs must be written for people to read, and only incidentally for machines to execute - «Structure and Interpretation of Computer Programs»

“程序是写给人看的,只是顺便用于机器执行”。


这种题目,简直迂腐。就像孔乙己的茴香豆。明白意思就行了,千万别照着做。读书学习尽量选经典教科书(的译本)。


比如一个表达式:

       a + b * c - d / 2 * 5     

乘法和加法的优先级哪个高,相信再初级的程序员也了如指掌;但并不妨碍我们把它写得更加清晰可读:

       a + (b * c) - (d / 2 * 5)     

两种写法别人都能读懂;但显然下面的写法,大脑处理时间更短。当项目规模越来越大时,一行代码节省一秒,整体上就能让大家早点下班享受人生。所以我们要鼓励养成一个好的习惯。


有些教材里还有一种题目,更是误人子弟,类似:

       int a = 5; int b = ++a + a++;     

看起来很高端,但其实这根本是 undefined behavior:在同一个语句里面,包含对同一个变量的多次读、写操作。

如果你的课本里有这种题目,赶快撕掉,不要遗祸人间。


注:本回答用一种夸张的语气来强调代码的可读性,纯属个人观点,请根据个人口味适量添加;真正的答案请参考其它回答。

user avatar

这个,其实是比较正常的嵌套判断写法,只有实际应用中会有人写的。算法竞赛中很可能会有人这么写。不过在试题跟考试中应该很少出现,除非写这个试题的人恰好是算法竞赛出身。

简单说就相当于: if (a>b) { if (a<c) a else b } else c

也就说这是两层 if 嵌套,不是 else if

当然,类似的写法可以拓展成 三层四层甚至更多层,如果特定的算法需要这么写的话。

三元操作符的低优先级是明确定义的,所以并不需要额外的括号,抱怨这个括号问题的人,恐怕就连三元操作符也不希望你使用。

这种用法一般只会用来写特定的算法,算是攻坚项目,普通的工程项目中很难会用到。写专用算法的人也不会是普通码农,所以不必介意他人的嘲讽。


说到这里,对于运算符问题,我个人的建议是:运算符的前两个类别跟最后两个类别建议记忆,中间的十个类别可以不必记忆。

也就是说,作为一个程序员,你必须知道什么运算符是优先级最高的几类,什么运算符是优先级最低的几类。其它的中间类别不需要记忆。

如果有的程序员教你「所有运算符优先级都不需要记忆」,我建议你转身就走,无视他们,因为如果你真的这么做,是根本写不出正常的代码的。

那么优先级最高的运算符类别是什么呢?

  • 括号与下标。例如 [] () . ->
  • 单目操作符,例如单目负号,单目感叹号,单目++,sizeof操作符等

那么优先级最低的运算法类别分别是什么呢?

  • 三元操作符,例如 ? :
  • 赋值操作符,例如 =, +=, -= 等等

当然,还有一些论外操作符,比如逗号,分号之类的,我们通常默认在考虑运算符优先级的时候是不会考虑逗号跟分号的。


为什么我会强调,对程序员来说,一部分运算符的优先级必须记忆?

对于 [] . -> 这些符号,如果你不知道它跟括号()运算符同级,你要么写出有歧义的代码要么搞错了优先级而不自知。

对于一些单目操作符,显而易见的具备高优先级,额外加括号不但不能提升代码可读性,反而降低了。

而对于赋值语句,如果你连「赋值语句运算符优先级很低」这个事实都不记忆,难道打算每次赋值都打括号?我没有见过如此深井病的程序员。可见很多程序员嘴上说不要,实际上还是会记得「赋值负号具有低优先级」这个客观事实。

而三元操作符,它就是贴近赋值语句的低优先级操作符,除了赋值语句,就是它最低。三元操作符的正常使用就不应当加括号,因为三元操作符把优先级设计得那么低就是为了让你不加括号的。


重申一下我的观点:不同语言运算符的类别可能有10到20种。虽然大多数运算符的优先级不需要专门记忆,但最高的几个级别以及最低的几个级别运算符,建议记忆,一般而言上三下三,或者上二下二就够了。

类似的话题

  • 回答
    在C语言中, `a > b ? a < c ? a : b : c` 这种写法是利用了三元运算符 (?:) 的嵌套。它是一种简洁的条件表达式,用来根据条件的真假返回不同的值。理解它的关键在于一步步拆解它的逻辑。咱们就来好好捋一捋这串表达式的判断过程,讲得透彻一些,保证让你明白它到底是怎么回事儿。首先.............
  • 回答
    C 语言的设计理念是简洁、高效、接近硬件,而其对数组的设计也遵循了这一理念。从现代编程语言的角度来看,C 语言的数组确实存在一些“不改进”的地方,但这些“不改进”很大程度上是为了保持其核心特性的兼容性和效率。下面我将详细阐述 C 语言为何不“改进”数组,以及这种设计背后的权衡和原因:1. 数组在 C.............
  • 回答
    C 语言王者归来,原因何在?C 语言,这个在编程界已经沉浮数十载的老将,似乎并没有随着时间的推移而消逝,反而以一种“王者归来”的姿态,在许多领域焕发新生。它的生命力如此顽强,甚至在 Python、Java、Go 等语言层出不穷的今天,依然占据着不可动摇的地位。那么,C 语言究竟为何能实现“王者归来”.............
  • 回答
    C语言指针是否难,以及数学大V认为指针比范畴论还难的说法,是一个非常有趣且值得深入探讨的话题。下面我将尽量详细地阐述我的看法。 C语言指针:理解的“门槛”与“终点”首先,我们需要明确“难”的定义。在编程领域,“难”通常指的是: 学习曲线陡峭: 需要花费大量时间和精力去理解和掌握。 容易出错:.............
  • 回答
    C 语言中的 `void main()` 并非是语言标准规定的写法,它的出现和流传,更像是一个历史遗留问题、编译器兼容性以及开发者习惯共同作用的结果。要详细讲解,我们需要从 C 语言的诞生和演变说起。1. C 语言的起源和早期标准 (K&R C) C 语言的诞生: C 语言最初是由 Dennis.............
  • 回答
    C语言自学能到什么高度?详细解析C语言,作为一门强大且经典的编程语言,其学习曲线相对陡峭,但一旦掌握,其应用范围之广,性能之优越,是许多其他语言难以比拟的。 仅凭自学,C语言可以让你达到一个非常高的技术高度,足以让你在许多领域成为一名优秀的开发者甚至专家。以下将从多个维度详细阐述C语言自学所能达到的.............
  • 回答
    在 C 语言中判断一个数列是否为等差数列,核心思想是验证数列中任意相邻两项的差值是否恒定不变。下面我将从概念、算法实现、注意事项以及代码示例等方面进行详细讲解。 一、什么是等差数列?在数学中,等差数列(Arithmetic Progression 或 Arithmetic Sequence)是指一个.............
  • 回答
    在 C 语言中,不用 `goto` 和多处 `return` 进行错误处理,通常依靠以下几种模式和技术。这些方法旨在提高代码的可读性、可维护性,并遵循更结构化的编程原则。核心思想: 将错误处理的逻辑集中到函数退出前的某个点,或者通过特定的返回值来指示错误。 1. 集中错误处理(Single Exit.............
  • 回答
    这个问题很有意思,也触及到了C语言作为一种基础性语言的根本。很多人听到“C语言本身是用什么写的”时,会先想到“用更高级的语言写的”,比如Python或者Java。但事实并非如此,或者说,这个答案需要更深入的理解。首先,我们需要明确一点:C语言最初的实现,也就是早期的C编译器,并不是用C语言本身写的。.............
  • 回答
    C 语言中,一些自带函数返回的是指向数组的指针,而你无需手动释放这些内存。这背后涉及到 C 语言的内存管理机制以及函数设计哲学。要弄清楚这个问题,我们需要从几个关键点入手: 1. 返回指针的函数,内存的归属至关重要首先,理解函数返回指针时,内存的“所有权”是谁的,是解决这个疑问的核心。当一个函数返回.............
  • 回答
    在 C 语言中,枚举(`enum`)是一种用户定义的数据类型,它允许你为一组整数常量命名。这使得代码更具可读性和可维护性。而枚举中的 `end` 关键字,严格来说,它本身并不是 C 语言标准枚举定义的一部分,而是一种常见的编程约定或模式,用于标记枚举序列的结束。让我来详细解释一下,并尽可能剥离 AI.............
  • 回答
    在C语言中,严格来说,不能直接“判断”一个变量的类型是否是`int`或`float`。C语言是一种静态类型语言,变量的类型在编译时就已经确定,并且不能在运行时随意更改或检查。当你声明一个变量时,你就已经告诉了编译器它的类型。不过,如果你想表达的是“根据当前存储的值,推断出这个变量应该被视为整数还是浮.............
  • 回答
    在 C 语言中,让不同线程之间能够交流信息、协同工作,这本身就是多线程编程中最核心也是最需要仔细处理的部分。别把它想得太玄乎,无非就是大家共享一块内存,然后约定好怎么读写这块内存罢了。只不过,这“约定”怎么立得住,不让大家互相捣乱,才是关键。咱们把线程通信这事儿,拆解成几个层面来说。 1. 共享内存.............
  • 回答
    C 语言里,一旦你用了 ` ` 来进行换行,确实就“回不去了”——至少在标准的输出流中是这样。这背后的原理,要从计算机如何处理文本输出和终端(或者说显示器)的工作方式说起。核心点:文本流与终端的坐标系统想象一下你的程序输出的文本,就像一条源源不断地向前流动的河流。` `(换行符)就是这条河流中的一个.............
  • 回答
    在C语言中,关于“乘以0.01”和“除以100”哪个更快速,这是一个非常值得探讨的话题,尤其是在追求极致性能的底层开发或者对浮点运算效率敏感的场景下。要回答这个问题,我们需要深入理解计算机如何处理这两种操作,以及它们在硬件层面的具体实现。理解基础:乘法和除法在计算机中的运算首先,我们得明白计算机进行.............
  • 回答
    朋友,咱们这话题聊得挺实在的。C语言现在还有没有“必要”学,未来还有没有“用”,这绝对是个值得深入掰扯掰扯的问题。别听那些虚头巴脑的,咱就从实际出发,好好说说。C语言现在还有没有“必要”学?我想说,如果你想在计算机底层或者和效率打交道,那 C 语言的“必要性”依然挺强的,甚至可以说是基石性的。你得明.............
  • 回答
    在 C 语言编程的世界里,选择一个趁手的编辑器就像是给了你一对飞翔的翅膀。这不仅关乎效率,更影响着你的开发体验和创造力。市面上的编辑器琳琅满目,各有千秋,要说哪个“最好用”,这其实是个非常主观的问题,取决于你的个人习惯、项目需求以及你追求的侧重点。不过,如果你想在众多选择中找到最适合你的那位,不妨先.............
  • 回答
    嘿,哥们,聊到 C 语言的“奇技淫巧”,这可就有意思了。这东西,说白了就是利用 C 语言一些不太直观,但又特别巧妙的特性,来达成一些别人想不到或者达不到的效果。很多时候,这些技巧能让你写出更精炼、更高效的代码,当然了,用不好也容易把自己绕进去。我这里给你掰扯几个比较典型的,保证不像是那种写流水账的A.............
  • 回答
    这个问题在 C 语言中,关于表达式 `a = a++;` 的结果,是初学者乃至一些有经验的程序员都可能感到困惑的地方。它的行为并非我们直观想象的那么简单,并且会涉及到 C 语言中一个非常重要的概念:未定义行为(Undefined Behavior)。首先,让我们尝试理解一下 C 语言是如何处理这个表.............
  • 回答
    在 C 语言的世界里,指针是必不可少的工具,它们就像是内存地址的“指示牌”,让我们能够更灵活地操作数据。而当我们将指针与数组、函数结合起来时,就诞生了一系列强大而又容易让人困惑的概念:指针数组、数组指针、函数指针,以及指向函数的指针。别担心,今天我们就来把它们掰开了揉碎了,让你彻底搞懂它们到底是怎么.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有