OverIQ 中文系列教程(二)

原文:OverIQ Tutorials

协议:CC BY-NC-SA 4.0

C 语言中的递增和递减运算符

原文:https://overiq.com/c-programming-101/increment-and-decrement-operators-in-c/

最后更新于 2020 年 7 月 27 日


c 有两个特殊的一元运算符,分别叫做增量(++)和减量(--)运算符。这些运算符通过1增加和减少变量值。

++xx = x + 1x += 1
--xx = x - 1x -= 1

递增和递减运算符只能用于变量。它们不能与常量或表达式一起使用。

int x = 1, y = 1;

++x;     // valid

++5;      // invalid - increment operator operating on a constant value

++(x+y);  // invalid - increment operating on an expression

递增/递减运算符有两种类型:

  1. 前缀递增/递减运算符。
  2. 后缀递增/递减运算符。

让我们从第一个开始。

前缀递增/递减运算符

前缀递增/递减运算符会立即增加或减少变量的当前值。然后在表达式中使用该值。让我们举个例子:

y = ++x;

这里首先x的当前值增加1x的新值被分配给y。同样,在声明中:

y = --x;

x的当前值递减1x的新值被分配给y

以下程序演示了前缀递增/递减运算符的作用:

#include<stdio.h>

int main()
{
    
    
    int x = 12, y = 1;

    printf("Initial value of x = %d\n", x); // print the initial value of x
    printf("Initial value of y = %d\n\n", y); // print the initial value of y

    y = ++x; // increment the value of x by 1 then assign this new value to y

    printf("After incrementing by 1: x = %d\n", x);
    printf("y = %d\n\n", y);

    y = --x; // decrement the value of x by 1 then assign this new value to y

    printf("After decrementing by 1: x = %d\n", x);
    printf("y = %d\n\n", y);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Initial value of x = 12
Initial value of y = 1

After incrementing by 1: x = 13
y = 13

After decrementing by 1: x = 12
y = 12

后缀递增/递减运算符

后缀递增/递减运算符使变量的当前值在表达式中使用,然后该值递增或递减。例如:

y = x++;

这里首先将x的当前值赋给y,然后x递增。

同样,在声明中:

y = x--;

x的当前值分配给y,然后x递减。

以下程序演示了后缀递增/递减运算符的作用:

#include<stdio.h>

int main()
{
    
    
    int x = 12, y = 1;

    printf("Initial value of x = %d\n", x); // print the initial value of x
    printf("Initial value of y = %d\n\n", y); // print the initial value of y

    y = x++; // use the current value of x then increment it by 1

    printf("After incrementing by 1: x = %d\n", x);
    printf("y = %d\n\n", y);

    y = x--; // use the current value of x then decrement it by 1

    printf("After decrementing by 1: x = %d\n", x);
    printf("y = %d\n\n", y);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Initial value of x = 12
Initial value of y = 1

After incrementing by 1: x = 13
y = 12

After decrementing by 1: x = 12
y = 13

优先

递增和递减运算符的优先级高于我们到目前为止讨论过的运算符(唯一的例外是括号)。此外,后缀递增/递减运算符的优先级高于前缀递增/递减运算符。

下表列出了我们到目前为止讨论过的运算符的优先级和关联性:

经营者 描述 结合性
() 圆括号 从左到右
++-- 后缀递增运算符、后缀递减运算符 从左到右
++--+- 前缀递增运算符、前缀递减运算符、一元加号、一元减号 从右向左
*/% 乘法、除法和模数 从左到右
+- 加法和减法 从左到右
=+=-=*=/=%= 赋值运算符和复合赋值运算符 从右向左

我们取一些表达式,在运算符优先的基础上求解。

例 1 :

int x, y, z;
x = 5;
y = 8;
z = ++x + y++;

解决方案:

第一步:评估y++。由于++是后缀,y的当前值将用于表达式中,然后递增。

z = ++x + 8;

第二步:评估++x。由于++是前缀,x的值将立即递增。

z = 6 + 8;

第三步:评估6 + 8

z = 14;

例 2 :

int a, b, c;
a = 10;
b = 20;
c = 1;
c += a++ * 5 - --b;

解决方案:

第一步:评估a++。由于++是后缀,a的当前值将用于表达式中,然后递增。表达式现在变成:

c += 10 * 5 - --b;

第二步:评估--b。由于--是前缀,b的值将立即递减。表达式现在变成:

c += 10 * 5 - 19;

第三步:评估10 * 5

c += 50 - 19;

第四步:评估50 - 19

c += 31;

第五步:评估+=

c = 32;



C 语言中的关系运算符

原文:https://overiq.com/c-programming-101/relational-operators-in-c/

最后更新于 2020 年 7 月 27 日


关系运算符用于比较两个表达式的值。关系运算符是二进制运算符,因为它们需要两个操作数来操作。包含关系运算符的表达式称为关系表达式。如果关系为真,则关系表达式的结果为1,如果关系为假,则关系表达式的结果为0

下表列出了关系运算符以及一些示例:

操作员 描述 例子 结果
> 大于 1 > 2 0
>= 大于或等于 3 >= 2 1
< 小于 10 < 5 0
<= 小于或等于 6 <= 7 1
== 等于 98==98 1
!= 不等于 10 != 9 1

在 C 中,所有非零值被认为是真,而0被认为是假。以下程序演示了关系运算符的作用:

#include<stdio.h>

int main()
{
    
    
    int x = 12, y = 13;

    printf("x = %d\n", x);
    printf("y = %d\n\n", y);

    // Is x is greater than y?
    printf("x > y : %d\n", x > y);

    // Is x is greater than or equal to y?
    printf("x >= y : %d\n", x >= y);

    // Is x is smaller than y?
    printf("x < y : %d\n", x < y);

    // Is x is smaller than or equal to y?
    printf("x <= y : %d\n", x <= y);

    // Is x is equal to y?
    printf("x == y : %d\n", x == y);

    // Is x is not equal to y?
    printf("x != y : %d\n", x != y);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

x = 12
y = 13

x > y : 0
x >= y : 0
x < y : 1
x <= y : 1
x == y : 0
x != y : 1

优先

<<=>>=操作符的优先级相同,从左到右关联。然而,==!=的优先级比其他关系运算符低,它们从左到右关联。关系运算符的优先级低于算术运算符。

为了清楚起见,让我们评估一些涉及关系运算符的表达式:

例 1 :

4 + 2 * 3 > 12 - 2

第一步:评估2 * 3

4 + 6 > 12 - 2

第二步:评估4 + 6,然后是12 - 2

10 > 10

第三步:10不大于10,所以上面的表达式计算为假(0)。因此整个表达式的结果是0

结果:

4 + 2 * 3 > 12 - 2 => 0

例 2 :

(4 % 2 == 0) <= (8 * 2)

步骤 1:括号操作符具有最高的优先级,它从左向右关联。所以表达式(4 % 2 == 0)将首先被求值。%运算符的优先级高于等于==运算符。因此,首先应用%运算符,然后应用==运算符。表达式现在变成:

(4 % 2 == 0) <= (8 * 2)
=> (0 == 0) <= (8 * 2)
=> 1 <= (8 * 2)

第二步:评估(8 * 2)

1 <= (8 * 2)
=> 1 <= 16

第三步:1小于16。所以上面的表达式评估为真(1)。因此整个表达式的结果是真的。

结果:

(4 % 2 == 0) <= (8 * 2) => 0

不要将赋值运算符(=)与等于运算符(==)混淆。第一个用于给变量赋值,第二个用于测试两个值是否相等。

要充分利用关系运算符,您必须学习如何使用 if-else 语句。if-else 语句在 If… else 语句 C 章节中详细讨论。



C 语言中的逻辑运算符

原文:https://overiq.com/c-programming-101/logical-operators-in-c/

最后更新于 2020 年 7 月 27 日


逻辑运算符用于计算两个或多个条件。一般来说,逻辑运算符用于组合关系表达式,但它们不仅限于关系表达式,您可以使用任何类型的表达式,甚至常量。如果逻辑运算符的结果为真,则返回1,否则返回0

逻辑运算符有三种类型:

操作员 意义
&& 逻辑积算符
&#124;&#124; 或运算符
! “非”算符

AND ( &&)和 OR ( ||)是二元运算符,而 NOT ( !)是一元运算符。

在我们开始解释&&运算符之前,请记住-在 C 中,所有非零值都被认为是真(1),而0被认为是假。

AND (&&)运算符

如果两个操作数都为真,该运算符给出真(即1)的净结果,否则为假(即0)。

操作数 1 操作数 2 结果
真实的 真实的 真实的
真实的 错误的 错误的
错误的 真实的 错误的
错误的 错误的 错误的

让我们举个例子:

int a = 12, b = 3;

假设我们有以下逻辑表达式:

(a==12) && (b<5)

在上面的表达式中,条件a == 12b < 5都为真,因此整个表达式为真。因此,整个逻辑表达式的价值是1

为了可读性,上面的表达式添加了括号。它不会以任何方式改变操作顺序。所以这个表达:

(a<12) && (b<5)

相当于:

a < 12 && b < 5

当然,前者比后者可读性更强。

再考虑一些例子:

表示 中间表达 结果
(a==4) && (b==2) false && false = > false 0
(a>100) && (b<10) false && true = > false 0
a && b true && true = > true 1
a && 0 true && false = > false 0

特别注意最后两个例子,如上所述,逻辑表达式中的操作数可以是任何表达式、变量或常量。

这是&&符最重要的一点。

&&(与)运算符中,如果第一个操作数的计算结果为假,则第二个操作数根本不会计算。

考虑以下示例:

int a = 12;
(a==11) && (a++);

上式中a==11为假,所以右操作数a++根本不求值。以下程序演示了这一概念:

#include<stdio.h>

int main()
{
    
    
    int a = 12, result;

    printf("Initial value of a = %d\n", a);

    // result of the logical expression is stored in result
    result = (a==11) && (a++); 

    printf("Final value of a = %d\n", a);
    printf("Result of logical expression = %d\n", result);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Initial value of a = 12
Final value of a = 12
Result of logical expression = 0

如果条件a==11为真,那么a的值就会增加1

或(||)运算符

如果至少有一个操作数为真,该运算符给出真(即1)的最终结果,否则为假。

操作数 1 操作数 2 结果
真实的 真实的 真实的
真实的 错误的 真实的
错误的 真实的 真实的
错误的 错误的 错误的

让我们举个例子:

int a = 10, b = 9;

假设我们有以下逻辑表达式:

(a<12) || (b<5)

上式中a < 12为真,b < 5为假。因此整个表达式评估为真,逻辑表达式的值为1

再考虑一些例子:

表示 中间表达 结果
(a==4) &#124;&#124; (b==2) false &#124;&#124; false = >假 0
(a>10) &#124;&#124; (b<10) false &#124;&#124; true = >真 1
a &#124;&#124; b true &#124;&#124; true = >真 1
a &#124;&#124; 12.12 true &#124;&#124; true = >真 1

请注意,上面两个表达式中使用了括号来提高可读性,当然表达式(a==4) && (b==2)a==4 && b==2更易读。

请注意,在最后一条语句中,第二个操作数的类型是 double,这是完全可以接受的。

OR( ||)运算符最重要的一点是,如果第一个操作数的计算结果为真,那么第二个操作数就不会被计算。考虑以下示例:

int a = 10;
(a==10) || (a--);

上式中a==10为真,故表达式a--不求值,整体表达式的结果为1。以下程序演示了这一概念:

#include<stdio.h>

int main()
{
    
    
    int a = 10, result;

    printf("Initial value of a = %d\n", a);

    // result of the logical expression is stored in result
    result = (a==10) || (a--); 

    printf("Final value of a = %d\n", a);
    printf("Result of logical expression = %d\n", result);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Initial value of a = 10
Final value of a = 10
Result of logical expression = 1

如果条件a==10为假,则 a 的值将减少1

!(非)操作员

!(非)运算符否定条件的值。如果条件是假的,那么它就变成真的,如果它是真的,那么它就变成假的。与&&(与)和||(或)运算符不同,!(非)运算符是一元运算符。

操作数 结果
真实的 错误的
错误的 真实的

让我们举个例子:

int a = 10, b = 9;

假设我们有以下逻辑表达式。

!(a > 5)

我们可以看到,条件a > 5是真的。而! (NOT)运算符否定条件的值,所以整体表达式的结果为假,即0

以下是更多的例子:

表示 中间表达 结果
!(a==4) !false = > true 1
!(a &#124;&#124; b) !true = > false 0
!(a && b) !true = > false 0
!(a > b) !true = > false 0

**注意:**要充分发挥关系和逻辑的潜力,必须首先掌握 if-else 语句和循环。如果-否则语句和循环分别在章节中详细讨论。

以下程序演示了非(!)运算符的作用:

#include<stdio.h>

int main()
{
    
    
    int a = 100, result;
    printf("Initial value of a = %d\n", a);

    // result of the logical expression is stored in result
    result = (a>10); 

    printf("Is a > 10 : %d\n", result);
    printf("After applying not operator\n");
    printf("Is a > 10 : %d\n", !result);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Initial value of a = 100
Is a > 10 : 1
After applying not operator
Is a > 10 : 0

优先

在逻辑运算符中,NOT ( !)运算符的优先级最高,它从右向左关联。“与”(&&)运算符的优先级高于“或”(||)运算符,它们都从左向右关联(参见完整的优先级表)。

现在让我们解决一些涉及逻辑运算符的表达式。例 1 :

int age = 10, height = 45;
(age < 12 && height < 48) || (age > 65 && height > 72);

解决方案:这种情况下,运算符的求值顺序为圆括号(())、关系运算符(<>)、AND ( &&)运算符、OR ( ||)运算符。

(age < 12 && height < 48) || (age > 65 && height > 72)
=> (10 < 12 && 45 < 48) || (10 > 65 && 45 > 72)
=> (1 && 1) || (10 > 65 && 45 > 72)
=> 1 || (10 > 65 && 45 > 72)
=> 1 || (0 && 0)
=> 1 || 0 
=> 1

例 2 :

int year = 2000;
(year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0);

解决方案:在这种情况下,运算符的求值顺序将是圆括号(())、模除法(%)、关系运算符(==!=)和(&&)运算符,或者(||)运算符。

(year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0)
=> (2000 % 4 == 0 && 2000 % 100 != 0 ) || (2000 % 400 == 0)
=> (0 == 0 && 2000 % 100 != 0 ) || (2000 % 400 == 0)
=> (0 == 0 && 0 != 0 ) || (2000 % 400 == 0)
=> (1 && 0 != 0 ) || (2000 % 400 == 0)
=> (1 && 0 ) || (2000 % 400 == 0)
=> 0 || (2000 % 400 == 0)
=> 0 || (0 == 0)
=> 0 || 1
=> 1



C 语言中的条件运算符、逗号运算符和sizeof()运算符

原文:https://overiq.com/c-programming-101/conditional-operator-comma-operator-and-sizeof-operator-in-c/

最后更新于 2020 年 7 月 27 日


条件运算符

条件运算符(?:)是一种特殊的运算符,需要三个操作数。它的语法如下:

语法: expression1 ? expression2 : expression3

下面是条件运算符的工作原理。

第一个expression1被求值,如果它是真的,那么expression2的值成为整个表达式的结果。另一方面,如果expression1为假,那么expression3的值就成为整体表达式的结果。

让我们举个例子:

int a = 5, b = 3;
a > b ? a : b

在上式中,a>b为真,因此变量a的值成为整体条件表达式的结果。

由于a > b ? a : b是一个表达式,我们可以将其值赋给一个变量。

max = a > b ? a : b

条件运算符有时也称为三元运算符。

下面的程序演示了如何使用条件运算符找到两个数字中最大的一个

#include<stdio.h>

int main()
{
    
    
    int a, b, max;

    printf("Enter a and b: ");
    scanf("%d%d", &a, &b);

    max = a > b ? a : b;

    printf("Largest of the two numbers = %d\n", max);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Enter a and b: 1993 1534
Largest of the two numbers = 1993

条件运算符的优先级远远低于算术、逻辑和关系运算符。但它比赋值和复合赋值运算符更高。条件运算符的结合性是从右向左的(参见 C 中的运算符优先级)。

考虑以下条件表达式:

x ? y : a ? b : c

在这种情况下,expression3本身就是一个条件表达式。此外,由于条件运算符从右向左关联,因此上述表达式相当于:

x ? y : (a ? b : c)

如果x的值为真(即非零),则整个表达式的值为y。否则,整个表达式的值将是(a ? b : c)

逗点算符

逗号运算符允许我们在 C 语法只允许一个表达式的地方放置一个或多个表达式。每个表达式必须用逗号(,)隔开,并从左到右计算。最右边表达式的值成为整个表达式的值。举个例子就能说明一切。

a=2, a++, a+10

这里我们结合了三个表达式,让我们看看它是如何工作的。首先2被分配给变量a,然后a的值增加1。最后对a+10进行了评价。所以整体表达的价值是13

我们再举一个例子。

sum = (a=3, b=4, c=5, a+b+c);

这里首先将3赋给变量a,然后将4赋给变量b5赋给变量c。最后a+b+c被求值,并且整个表达式的结果(即最右边的表达式)被分配给sum

逗号运算符(,)的优先级最低,从左向右关联(参见中的运算符优先级和关联性)。因此,上面表达式中的括号是必要的,否则,变量sum将被赋予一个值3

逗号运算符(,)帮助我们使代码更加简洁。如果不使用逗号运算符,上述任务至少需要 2 条语句。

a=3, b=4, c=5;
sum = a+b+c;

以下程序演示了逗号运算符(,)的作用:

#include<stdio.h>

int main()
{
    
    
    int a, b, c, sum;
    sum = (a=3, b=4, c=5, a+b+c);
    printf("Sum = %d\n", sum);
    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Sum = 12

操作符的大小

sizeof是一元运算符,用于确定其操作数的大小。sizeof运算符的一般形式是:

sizeof(object)

其中对象可以是数据类型关键字,如intfloatdouble或表达式或变量。

例如,sizeof(int)给出了一个int数据类型所占的大小。sizeof运算符以字节为单位返回大小。

下面的程序演示了如何使用sizeof()操作符检查系统中基本类型的大小。

#include<stdio.h>

int main()
{
    
    
    printf("Size of short = %lu\n", sizeof(short));
    printf("Size of int = %lu\n", sizeof(int));
    printf("Size of unsigned int = %lu\n", sizeof(unsigned int));
    printf("Size of char = %lu\n", sizeof(char));
    printf("Size of float = %lu\n", sizeof(float));
    printf("Size of double = %lu\n", sizeof(double));
    printf("Size of long double = %lu\n", sizeof(long double));

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Size of short = 2
Size of int = 4
Size of unsigned int = 4
Size of char = 1
Size of float = 4
Size of double = 8
Size of long double = 16

因为 C 在存储需求方面相当灵活。上述程序的输出可能因您的机器而异。

sizeof运算符的优先级与前缀递增/递减运算符相同,从右向左关联(参见中的运算符优先级和关联性)。



C 语言中的隐式类型转换

原文:https://overiq.com/c-programming-101/implicit-type-conversion-in-c/

最后更新于 2020 年 7 月 27 日


c 允许我们在表达式中混合基本类型。在 C 的算术运算符一章中讨论混合模式算术时,我们已经看到了这种行为的一瞥。在这样的表达式中,一种类型的操作数被转换成另一种类型。这个过程称为类型转换。

有两种类型的类型转换:

  1. 隐式类型转换。
  2. 显式类型转换

在本章中,我们将讨论隐式类型转换。

隐式类型转换

这种类型的转换由编译器根据以下规则完成:

  1. 如果一个操作数是类型long double,那么另一个操作数将被转换为long double,然后运算的结果将是一个long double
  2. 否则,如果一个操作数的类型为double,那么另一个操作数将被转换为double,运算结果将是double
  3. 否则,如果一个操作数的类型为float,那么另一个操作数将被转换为float,运算结果将是float
  4. 否则,如果一个操作数的类型为unsigned long int,那么另一个操作数将被转换为unsigned long int,运算结果将是unsigned long int
  5. 否则,如果一个操作数的类型为long int,另一个操作数的类型为unsigned int,则有两种可能:
    1. 如果long int可以表示一个unsigned int的所有值,那么类型unsigned int的操作数将被转换为long int,结果将是一个long int
    2. 否则,如果long int不能代表一个unsigned int的所有值,则两个操作数的操作数都转换为unsigned long int,结果为unsigned long int
  6. 否则,如果一个操作数的类型为long int,那么另一个操作数将被转换为long int,运算结果将是long int
  7. 否则,如果一个操作数的类型为unsigned int,那么另一个操作数将被转换为unsigned int,运算结果将是unsigned int
  8. 否则,如果一个操作数的类型为int,那么另一个操作数将被转换为int,运算结果将是int

我们举几个例子把事情说清楚。

例 1:

int a = 100;
double b = 12.5;

a + b;

这里一个操作数是类型int,另一个是类型double。因此根据规则 3,变量a将被转换为double,整体运算的结果将是一个double,即112.500000

例 2:

char ch = 'a';
int a = 10;

a + c;

根据规则 8,在任何操作之前,char将被转换为int,并且整体操作的结果将是int。因为ch的整数值是97(即字符'a'的 ASCII 值)。因此,97 + 10 = 107

例 3:

char ch = 'A';
unsigned int a = 10;

a * b;

这里根据规则 7,类型为char的变量ch将首先转换为unsigned int,即65 (ASCII 值为'A',然后进行加法运算,整体运算结果为unsigned int。因此,65 + 10 = 75

下面是更多的例子:

char ch;
short int si;
int i;
unsigned int ui;
float f;
long double ld;

i = ch + si;  // both ch and si will be converted to int before addition - rule 8
i = si + i;   // si will be converted to int before addition - rule 8
ui = i + ui;  // i will be converted to unsigned int before addition - rule 7
f = ui + f;   // ui will be converted to float before addition - rule 3
ld = f + ld;  // f will be converted to long double before addition - rule 1

通过给每种类型分配一个等级,可以简化上述所有规则。以下是它的工作原理。

每当表达式中涉及两个不同数据类型的操作数时,较低等级的操作数将被转换为较高等级的数据类型。这个过程叫做型的提升。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

:为简单起见,图中省略了规则 5。

分配中的类型转换

如果赋值表达式中的操作数类型不同,那么右边的操作数将根据以下规则转换为左边的操作数类型。

  1. 如果右侧操作数的等级较低,则它将被提升到左侧操作数的等级。这里有一个例子:

    int i = 'z';
    
    

    这里右操作数'z'是类型char,右操作数是类型int。根据规则——较低等级的操作数(在本例中为char)将被提升到较高等级(在本例中为int)。所以赋值前'z'122 (ASCII 值)会提升到int再赋值到i

  2. 否则,如果右侧操作数的等级较高,则它将被降级为左侧操作数的等级。例如:

    float a = 120.33;
    
    

    回想一下,默认情况下浮点常量的类型是double。在这种情况下,右侧操作数即120.33double类型,左侧操作数为float类型。因此在赋值操作之前120.33将被降级为float类型,然后赋值将会发生。

赋值中类型转换的一些结果是:

  1. long int转换为intint转换为short intint转换为char时,高阶位可能会丢失。让我们举个例子来清楚地理解这一点。假设我们有以下陈述:

    unsigned char ch = 257;
    
    

    这里我们试图将257 ( int类型)分配给一个char变量。根据类型转换规则 2:如果右手操作数的等级较高,那么它将被降级为左手操作数的等级。但是有一个问题,回想一下unsigned char型只能取0255的数值。Cleary,257超出变量ch的范围。在这种情况下,从范围的另一侧拾取适当的值并存储在ch中。所以最终存储在ch变量中的是一个带有 ASCII 值2的笑脸字符。

  2. 从浮点类型(如doublefloat)转换为int类型时,小数部分将被截断。

  3. double类型转换为float类型时,数字四舍五入。

  4. int转换为floatfloat转换为double时,精度没有增加。

  5. signed类型变为unsigned类型时,标志可能会掉落。

下面的示例演示了如何进行类型转换。

#include<stdio.h>

int main()
{
    
    
    float f_val1 = 97.12, f_val2;
    int i_val1, i_val2;
    char ch_val1, ch_val2;

    // float is demoted to int, only 97 is assigned to i_val1
    i_val1 = f_val1;

    // int is demoted to char,
    ch_val1 = i_val1;

    // float is demoted to int, only 12 is assigned to i_val2
    i_val2 = 12.45f;

    // char is promoted to int, now
    // i_val1 contains ASCII value of character 'e' i.e 101
    i_val2 = 'e';

    /*
        double is demoted to float, since by
        default floating point constants
        are of type double
    */

    f_val2 = 12.34;

    // Print the value of i
    printf("Value of i_val1 = %d\n", i_val1);

    // Print the character corresponding to ASCII value 97
    printf("Value of ch_val1 = %c\n", ch_val1);

    // Print the ASCII value of character 'e'
    printf("Value of i_val2 = %d\n", i_val2);

    // Print f_val2 with 2 digits of precision
    printf("Value of f_val2 = %.2f\n", f_val2);

    // Signal to operating system everything works fine
    return 0;
}

预期输出:

Value of i_val1 = 97
Value of ch_val1 = a
Value of i_val2 = 101
Value of f_val2 = 12.34



C 语言中的显式类型转换

原文:https://overiq.com/c-programming-101/explicit-type-conversion-in-c/

最后更新于 2020 年 7 月 27 日


上一章讨论的隐式类型转换是由编译器自动完成的。在某些情况下,我们可能希望对转换如何发生有更多的控制。举个例子吧。

float f;
int a = 20, b = 3;
f = a/b

f的值将是6.000000而不是6.666666,因为两个整数之间的运算会产生一个整数值。当然解决这个问题的一个方法是使用混合模式算法,并将ab的类型更改为doublefloat。改变变量的类型并不总是可行的,当然也不是一个好的编程。在 c 中输入显式类型转换。

演职人员

强制转换运算符是一元运算符,用于将常量、变量或表达式临时转换为特定类型。强制转换运算符的语法是:

语法: (datatype)expression

其中datatype指您希望表达式转换成的类型。所以如果我们把上面的陈述写成:

f = (float)a/b;

然后我们会得到正确的答案,即6.666666

以下是演职人员的工作方式。

首先,它将类型为int的变量a临时转换为类型为float。我们已经知道floatint操作数之间的运算会产生float结果,这就是为什么答案是6.666666而不是6.000000

请注意,在上面的陈述中,cast 运算符仅适用于变量a,而不适用于ba/b

另一个需要注意的要点是,变量a的数据类型是float,直到语句执行为止。之后,将被视为int

在我们离开这个话题之前,请考虑以下声明:

f = (float)(a/b);

你可能会认为这个说法和上一个(即f = (float)a/b;)是一样的,但其实不是,这里是为什么。

这里首先对表达式a/b进行求值,然后由于类型转换,其结果被转换为float,并最终分配给f

以下程序演示了 cast 运算符的作用:

#include<stdio.h>

int main()
{
    
    
    int a = 25, b = 13;
    float result;

    result = a/b;

    // display only 2 digits after decimal point
    printf("(Without typecasting) 25/13 = %.2f\n", result );  

    result = (float)a/b;

    // display only 2 digits after decimal point
    printf("(With typecasting) 25/13 = %.2f\n", result ); 

    // signal to operating system everything works fine
    return 0;
}

预期输出:

(Without typecasting) 25/13 = 1.00
(With typecasting) 25/13 = 1.92



C 语言中的控制语句

C 语言中的if-else语句

原文:https://overiq.com/c-programming-101/if-else-statements-in-c/

最后更新于 2020 年 7 月 27 日


C 语言中的控制语句

到目前为止,在我们编写的所有程序中,语句按照它们出现的顺序依次执行。但是有时我们希望只有在某些条件为真时才执行语句。例如,如果银行余额超过七位数,购买一辆新车,否则续订公共汽车月票。为了做出这样的决定,C 提供了一种称为控制语句的工具。

控制语句用于改变程序的流程。它们用于指定语句的执行顺序。它们通常用于定义控制如何从程序的一部分转移到另一部分。

C 语言有以下控制语句:

  • 如果…否则
  • 转换
    • 正在…
    • 做…正在…

复合语句

复合语句是使用大括号({})组合在一起的语句块。在复合语句中,所有语句都是按顺序执行的。复合语句也称为块。它采用以下形式:

{
    
    
    statement1;
    statement2;
    statement3;
    ...
    statementn;
}

我们了解到所有语句都以分号(;)结尾,但复合语句是这一规则的例外。另一个需要理解的重要事情是,复合语句在语法上等同于单个语句,这意味着我们可以将复合语句放在允许单个语句的地方。这意味着下面的代码完全有效。

#include<stdio.h>

int main()
{
    
    
    int i = 100;

    printf("A single statement\n");

    {
    
    
        // a compound statement
        printf("A statement inside compound statement\n");
        printf("Another statement inside compound statement\n");
    }

    // signal to operating system everything works fine
    return 0;
}

预期输出:

A single statement
A statement inside compound statement
Another statement inside compound statement

如果语句

If 语句用于测试条件并采取两种可能的操作之一。if 语句的语法是:

语法:

if (condition)
{
    
    
    // if block
    statement1;
    statement2;
}

条件可以是任何常量、变量、表达式、关系表达式、逻辑表达式等等。请记住,在 C 中,任何非零值都被认为是真,而0被认为是假。

工作原理:

if 块内的语句(即statement1statement2)只有在条件为真时才执行。如果为假,则跳过 If 块内部的语句。当条件为真时,当您想要执行多个语句时,大括号({})总是必需的。此外,请注意 if 块中的语句略有缩进。这样做是为了提高可读性,语法上不需要缩进。

如果您想在条件为真时只执行一条语句,那么可以省略大括号({})。通常,即使只有一条语句要执行,也不应该省略大括号。

if (condition)
    statement1;

如果用户输入的数字是偶数,下面的程序将打印一条消息。

#include<stdio.h>

int main()
{
    
    
    int n;

    printf("Enter a number: ");
    scanf("%d", &n);

    if(n % 2 == 0)
    {
    
    
        printf("%d is even", n);
    }

    // signal to operating system everything works fine
    return 0;
}

第一次运行:

运行程序并输入一个偶数,您将获得以下输出:

预期输出:

Enter a number: 46
46 is even

第二次运行:

再次运行程序,但这次输入一个奇数。

预期输出:

Enter a number: 21

这一次,条件(n % 2 == 0)的计算结果为 false,因此 if 块中的语句被跳过。

哪种说法属于 if?

if (condition)
statement1;
statement2;
statement3;

如果条件为假,你能找到哪个语句将被省略吗?

如果 If 语句后面没有大括号({}),那么只有下一个立即语句属于 if 语句。else 和 else-if 子句也是如此(else 和 else-if 子句将在本章后面讨论)。

因此,只有statement1属于 if 语句。因此,如果条件为假,则仅省略statement1。无论条件如何,statement2statement3将始终被执行。以下示例说明了这一事实:

#include<stdio.h>

int main()
{
    
    
    if(0)
    printf("statement 1\n");
    printf("statement 2\n");
    printf("statement 3\n");

    // signal to operating system everything works fine
    return 0;
}

预期输出:

statement 2
statement 3

这里的条件是假的,这就是为什么只执行最后两个语句。这验证了第 6 行中的语句只属于 if 语句的事实。乍看之下,确定哪个语句属于 if 语句有点混乱,这就是为什么建议总是使用大括号({})来包装要用 if 语句执行的语句。

#include<stdio.h>

int main()
{
    
    

    if(0)
    {
    
    
        printf("statement 1\n");
    }
    printf("statement 2\n");
    printf("statement 3\n");

    // signal to operating system prgram ran fine
    return 0;
}

现在您可以清楚地看到,只有第一个语句属于 if 语句。

else 子句

else子句允许我们为if条件添加一个替代路径。只有当if条件为假时,才会执行else块下的语句。

语法:

if (condition)
{
    
    
    // if block
    statement1;
    statement2;
}

else
{
    
    
    // else block
    statement3;
    statement4;
}

通常,如果 else 块中只有一条语句,那么大括号({})可以省略。虽然,不推荐。

if (expression)
    statement1;
else
    statement2;

如前所述,缩进不是必需的,因此上面的代码也可以写成:

if (expression)
statement1;
else
statement2;

但是为什么要抹杀可读性呢?做一个好的程序员,总是缩进我们的代码。

现在,让我们在之前编写的程序中添加一个else子句。

#include<stdio.h>

int main()
{
    
    
    int n;

    printf("Enter a number: ");
    scanf("%d", &n);

    if(n % 2 == 0)
    {
    
    
        printf("%d is even", n);
    }

    else
    {
    
    
        printf("%d is odd", n);
    }

    // signal to operating system everything program ran fine
    return 0;
}

**第一次运行:**运行程序并输入一个偶数。

Enter a number: 44
44 is even

第二次运行:

再次运行程序,但这次输入一个奇数。

Enter a number: 91
91 is odd

再考虑一个例子。以下程序确定两个输入数字中较大的一个:

#include<stdio.h>

int main()
{
    
    
    int a, b;

    printf("Enter two numbers: ");
    scanf("%d %d", &a, &b);

    if(a > b)
    {
    
    
        printf("%d is greater than %d", a, b);
    }

    else
    {
    
    
        printf("%d is greater than %d", b, a);
    }

    // signal to operating system everything works fine
    return 0;
}

预期输出:

第一次运行:

Enter two numbers: 344 200
344 is greater than 200

第二次运行:

Enter two numbers: 99 999
999 is greater than 99

嵌套 if… else

我们可以添加ifelse声明在if街区或else街区内。这叫做【T4 的筑巢】…else语法:

if(condition1)
{
    
    
    if(condition2)
    {
    
    
        statement1;
        statement2;
    }

    else
    {
    
    
        statement3;
        statement4;
    }
}

else
{
    
    
    if(condition3)
    {
    
    
        statement5;
        statement6;
    }

    else
    {
    
    
        statement7;
        statement8;
    }
}

我们可以筑巢ifelse陈述到任何深度。

工作原理:

首先检查condition1,如果为真,则检查condition2,如果为真,则执行if块内的语句(第 4-7 行)。

否则,执行else块(第 10-13 行)中的语句。否则,如果condition1为假,则检查condition3,如果为真,则执行第 19-22 行 if 块下的语句。否则,执行else块(第 25-28 行)中的语句。

以下程序使用两个嵌套的 if-else 语句来确定三个数字中较大的一个:

#include<stdio.h>

int main()
{
    
    
    int a, b, c, larger;

    printf("Enter three numbers: ");
    scanf("%d %d %d", &a, &b, &c);

    if(a > b)
    {
    
    
        if(a > c)
        {
    
    
            larger = a;
        }

        else
        {
    
    
            larger = c;
        }
    }
    else
    {
    
    
        if(b > c)
        {
    
    
            larger = b;
        }

        else
        {
    
    
            larger = c;
        }
    }

    printf("Largest number is %d", larger);

    // signal to operating system everything works fine
    return 0;
}

预期输出:

第一次运行:

Enter three numbers: 12 35 54
Largest number is 54

第二次运行:

Enter three numbers: 77 23 871
Largest number is 871

匹配 if…其他部分

有时将 else 子句与if语句联系起来会变得令人困惑。考虑以下示例:

if(a<10)
    if (a % 2 ==0)
        printf("a is even and less than 10\n");
else
printf("a is greater than 10");

哪个if语句与else块相关联?根据代码缩进的方式,您可能会认为else属于第一个if语句,但事实并非如此。编译器不会根据缩进将ifelse语句关联起来,而是将 else 部分与最接近的不匹配的if部分进行匹配。所以else语句与第二个if语句相关联。

使用牙套({})我们总能避免这样的并发症。

if(a < 10)
{
    
    
    if (a % 2 ==0)
    {
    
    
        printf("a is even and less than 10\n");
    }

    else
    {
    
    
        printf("a is greater than 10");
    }
}

现在一切都清楚了。

else if 子句

if-else是一个双向语句,用于测试一个条件并采取两个可能的动作之一。如果我们要进行一系列测试呢?检查多个条件的一种方法是使用嵌套的if-else语句。我们在本章前面已经看到了这种技术的一个例子。实现这一点的另一种方法是使用 else-if 子句。else-if 子句扩展了基本的 if-else 语句,并允许我们执行一系列测试。if-else 语句的更新语法如下所示:

if(condition1)
{
    
    
    statement1;
}

else if(condition2)
{
    
    
    statement2;
}

else if(condition3)
{
    
    
    statement3;
}

...

else
{
    
    
    statement4;
}

这里,逐一检查每个条件。一旦发现一个条件为真,则执行对应于该块的语句。if-else 语句的其余部分中的条件和语句被跳过,程序控制从if-else语句中出来。如果所有条件都不成立,则执行else块中的语句。

使用else-if子句,我们可以以更紧凑的形式编写嵌套的if-else语句。

让我们重写程序,使用 else-if 子句来确定这两个数字中最大的一个。

#include<stdio.h>

int main()
{
    
    
    int a, b, c, larger;

    printf("Enter three numbers: ");
    scanf("%d %d %d", &a, &b, &c);

    if(a > b && a > c)
    {
    
    
        larger = a;
    }

    else if(b > a && b > c)
    {
    
    
       larger = b;
    }

    else
    {
    
    
        larger = c;
    }

    printf("Largest number is %d", larger);

    // signal to operating system everything works fine
    return 0;
}

这个版本的程序在功能上等同于使用嵌套 if-else 语句的程序。但它避免了深缩进,使代码更易读。



C 语言中的while循环

原文:https://overiq.com/c-programming-101/the-while-loop-in-c/

最后更新于 2020 年 7 月 27 日


循环用于重复执行语句或语句块。例如,假设我们想写一个程序打印"Hello" 5 次。实现这一点的一种方法是将下面的语句写 5 遍。

printf("hello\n");

但是如果我们想打印1001000次呢。当然,把同样的语句写 100 次或 1000 次是疯狂的。使用循环我们可以很容易地解决这类问题。c 提供了三种类型的循环。

  1. while 循环
  2. 边循环边做
  3. for 循环

while 循环

语法:

while(condition)
{
    
    
    // body of while loop
    statement 1;
    statement 2;
}

就像 if-else 语句一样,while 循环以一个条件开始。首先,评估condition,如果为真,则执行 while 主体中的语句。在执行 while 循环的主体后,再次检查条件,如果条件仍然为真,则再次执行 while 主体中的语句。这个过程一直重复,直到condition变为假。因此,你必须始终包含一个改变condition价值的陈述,这样它最终会在某个时候变成假的。循环体的每次执行都被称为迭代。

以下程序使用 while 循环打印1100之间的所有偶数:

例 1:

#include<stdio.h>

int main()
{
    
    
    int i = 1;

    // keep looping while i < 100
    while(i < 100)
    {
    
    
        // if i is even
        if(i % 2 == 0)
        {
    
    
            printf("%d ", i);
        }
        i++; // increment i by 1
    }

    // signal to operating system everything works fine
    return 0;
}

预期输出:

2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50
52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96
98

工作原理:

在第 5 行,我们已经声明了一个变量i,并将其初始化为1。首先,检查条件(i < 100),如果是真的。控制在 while 循环的主体内传递。在循环体内部,如果条件(i % 2 == 0)被检查,如果它为真,那么 if 块内部的语句被执行。然后使用表达式i++增加i的值。由于在 while 循环的主体中没有更多的语句可以执行,因此第一次迭代就完成了。再次检查条件(i < 100),如果它仍然为真,则再次执行循环主体。只要i的值小于100,这个过程就会重复。当i到达100时,循环终止,控制脱离 while 循环。

再考虑一个例子:

例 2:

以下程序计算用户输入的数字的十进制位总和。

#include<stdio.h>

int main()
{
    
    
    int n, num, sum = 0, remainder;

    printf("Enter a number: ");
    scanf("%d", &n);

    num = n;

    // keep looping while n > 0
    while( n > 0 )
    {
    
    
        remainder = n % 10;   // get the last digit of n
        sum += remainder;     // add the remainder to the sum
        n /= 10;              // remove the last digit from n
    }

    printf("Sum of digits of %d is %d", num, sum);

    // signal to operating system everything works fine
    return 0;
}

**预期输出:**第一次运行:

Enter a number: 222
Sum of digits of 222 is 6

第二次运行:

Enter a number: 456
Sum of digits of 456 is 15

工作原理:

假设用户输入了123,那么下面是求位数之和的步骤。

第一次迭代

n = 123

第一步:

通过评估123 % 10取出123的最后一位数字,并将结果存储在变量remainder中。

remainder = n % 10;
remainder = 123 % 10
remainder = 3

第二步:

将最后一步得到的数字加到变量sum中。

sum += remainder
sum = sum + remainder
sum = 3

第三步:

现在不需要123的最后一位数字了,通过评估123 / 10去掉。

n /= 10
n = 123 / 10
n = 12

第二次迭代

n = 12

第一步:
remainder = n % 10;
remainder = 12 % 10
remainder = 2

第二步:
sum += remainder
sum = sum + remainder
sum = 3 + 2
sum = 5

第三步:
n /= 10
n = 12 / 10
n = 1

第三次迭代

n = 1

第一步:
remainder = n % 10;
remainder = 1 % 10
remainder = 1

第二步:
sum += remainder
sum = sum + remainder
sum = 5 + 1
sum = 6

第三步:
n /= 10
n = 1 / 10
n = 0

n到达0时,while 条件变为假,并且控制脱离 while 循环。因此123的十进制位总和为6



C 语言中的do-while循环

原文:https://overiq.com/c-programming-101/the-do-while-loop-in-c/

最后更新于 2020 年 7 月 27 日


做…同时循环

语法:

do{
    
    
   // body of do while loop
   statement 1;
   statement 2;
}while(condition);

在 do while 循环中,首先执行主体中的语句,然后检查条件。如果条件为真,则再次执行正文中的语句。这个过程一直重复,直到条件变为假。通常,如果 do while 循环的主体只包含一个语句,那么可以省略大括号({})。请注意,与 while 循环不同的是,在 do while 中,条件后会放置一个分号(;)。

do while 循环与 while 循环有很大的不同,因为在 do while 循环中,即使条件为假,主体中的语句也至少执行一次。在 while 循环的情况下,首先检查条件,如果条件为真,则只执行循环体中的语句。

以下程序使用 do while 循环打印1100之间的数字,它们是3的倍数:

#include<stdio.h> // include the stdio.h

int main()
{
    
    
    int i = 1; // declare and initialize i to 1

    do
    {
    
    
        // check whether i is multiple of 3 not or not
        if(i % 3 == 0)
        {
    
    
            printf("%d ", i);   // print the value of i
        }
        i++; // increment i by 1
    }while(i < 100);  // stop the loop when i becomes greater than 100

    // signal to operating system everything works fine
    return 0;
}

预期输出:

3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 7
5 78 81 84 87 90 93 96 99

工作原理:

在第 5 行,我们已经声明并初始化了变量i。然后,控件进入 do while 循环的主体。在循环体内部,测试 if 条件(i%3==0),如果为真,则执行 if 块内部的语句。声明i++i的值增加1。最后,检查边做边条件(i<100)。如果为真,则循环体内部的语句将再次执行。只要i的值小于100,这个过程就一直重复。

我应该在哪里使用 do while 循环?

大多数时候你会用 while 循环代替 do while。然而,在一些场景中,while loop 最适合。考虑以下问题。

假设你想创建一个程序来寻找一个数的阶乘。你可能知道阶乘只对0和正数有效。这里有一种方法可以解决这个问题。

假设用户输入了一个负数,与其显示错误消息并退出程序,不如再次要求用户输入一个数字。你要一直问,直到用户输入一个正数或者0。一旦输入正数或0,计算阶乘并显示结果。

让我们看看如何使用 while 和 do while 循环来实现它。

使用 while 循环

#include<stdio.h> // include the stdio.h

int main()
{
    
    
    int num;
    char num_ok = 0;

    // keep asking for numbers until num_ok == 0
    while(num_ok==0)
    {
    
    
        printf("Enter a number: ");
        scanf("%d", &num);

        // if num >= 0 set num_ok = 1 and stop asking for input
        if(num>=0)
        {
    
    
            num_ok = 1;
        }
    }

   // calculate factorial
}

使用 do while 循环

#include<stdio.h> // include the stdio.h

int main()
{
    
    
    int num;

    do
    {
    
    
        printf("Enter a number: ");
        scanf("%d", &num);
    }while(num<0); // keep asking for numbers until num < 0

   // calculate factorial
}

请注意,使用 while 循环的解决方案更加复杂,为了实现同样的目的,我们必须创建一个额外的变量num_ok,以及一个额外的 if 语句。另一方面,do while 循环实现了同样的事情,没有任何欺骗,它更优雅和简洁。

在我们离开 do while 循环之前,让我们再举一个例子。

以下程序计算简单利息:

/******************************************
 Program to calculate the Simple interest 
 *
 * SI = (Principal * Rate * Time) / 100
 *
******************************************/

#include<stdio.h> // include stdio.h

int main()
{
    
    
    float p, r, t;
    char ch = 'y';

    do
    {
    
    
        printf("Enter principal: ");
        scanf("%f", &p);

        printf("Enter rate: ");
        scanf("%f", &r);

        printf("Enter t: ");
        scanf("%f", &t);

        printf("SI = %.2f", (p *r * t)/100 );

        printf("\n\nCalculate SI one more time ? ('y' for Yes, 'n' for no ) : ");
        scanf(" %c", &ch);    // notice the preceding white space before %c 
    }while(ch == 'y');        // keep asking for P, R and T til the input is 'y'

    // signal to operating system everything works fine
    return 0;
}

预期输出:

Enter principal: 15000
Enter rate: 4.5
Enter t: 3
SI = 2025.00

Calculate SI one more time ? ('y' for Yes, 'n' for no ) : y
Enter principal: 20000
Enter rate: 5.4
Enter t: 4
SI = 4320.00

Calculate SI one more time ? ('y' for Yes, 'n' for no ) : n



C 语言中的for循环

原文:https://overiq.com/c-programming-101/the-for-loop-in-c/

最后更新于 2020 年 7 月 27 日


在前两章中,我们已经学习了 whiledo while loop 。在本章中,我们讨论 for 循环:for 循环的语法如下:语法:

for(expression1; expression2; expression3)
{
    
    
    // body of for loop
    statement1;
    statement2;
}

expression1是初始化表达式。
expression2是测试表达式或条件。
这个expression3就是更新表情。

工作原理:

首先执行初始化表达式(即expression1)初始化循环变量。当循环开始时,expression1只执行一次。然后检查条件(即expression2,如果是真的,则执行循环的主体。在执行循环体之后,程序控制被转移到更新表达式(expression3)。expression3修改循环变量。然后再次检查条件(即expression2)。如果条件仍然为真,则再次执行循环体。这个过程一直持续到expression2变为假。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果 for 循环的主体只包含一条语句,那么大括号({})可以省略。

for(expression1; expression2; expression3)
    statement1;

// The above for loop is equivalent to:

for(expression1; expression2; expression3)
{
    
    
    statement1;
}

以下程序计算从1100的数字总和。

#include<stdio.h>

int main()
{
    
      
    int i;   // loop variable
    int sum = 0;    // variable to accumulate sum

    for(i = 1; i <= 100; i++)
    {
    
    
        sum += i;
    }

    printf("Sum = %d", sum);

    // return 0 to operating system
    return 0;
}

预期输出:

Sum = 5050

工作原理:

在第 5 行,我们声明了一个名为i的循环变量。在第 6 行,我们将名为sum的变量声明并初始化为0。然后程序控制进入 for 循环。首先执行初始化语句(i=1)初始化循环变量i。然后检查条件(i<100),如果为真,则执行 for 循环体内部的语句。在执行循环体之后,程序控制转移到更新表达式(i++),并且i的值增加1。然后再次检查条件(i<100),如果仍然为真,则执行循环体。只要变量i小于或等于100,该过程就会继续。当i到达101时,条件(i<100)变为假,控制从 for 循环中出来,执行后面的语句。

while 和 for 循环有什么区别吗?

while 和 for 循环本质上是以不同的方式做同样的事情。事实上,除了在极少数情况下,for 循环总是可以被 while 循环替换,反之亦然。

expression1;
while(expression2)
{
    
    
    expression3;
}

在上面的片段中,expression1可以被视为初始化表达式,因为它在 while 循环的开始只执行一次。expression2是测试表达式,expression3是更新表达式。将这个模式应用到我们前面的 for 循环示例中,让我们使用 while 循环重写它。

#include<stdio.h>

int main()
{
    
    
    int i = 1, sum = 0;

    while(i <= 100)
    {
    
    
        sum += i;
        i++;
    }

    printf("Sum = %d", sum);

    // return 0 to operating system
    return 0;
}

for 循环中的表达式是可选的

for 循环中的所有三个表达式都是可选的,但两个分号必须始终存在。

  • 如果初始化是在 for 循环之外完成的,我们可以省略expression1
  • 如果省略expression2,那么条件总是真的,导致无限循环的产生——一个永不停止执行的循环。为了避免无限循环,您应该在循环体中包含一个中断返回语句。我们将在接下来的章节中详细讨论breakreturn陈述。
  • 如果 for 循环体中存在更新表达式,我们可以省略expression3

以下是基于省略表达式的 for 循环的一些简单变体:

例 1: 省略expression1

/*
     1st variation - expression1 is omitted
*/

#include<stdio.h>

int main()
{
    
    
    int i = 1, sum = 0;

    //expression 1 is omitted

    for( ; i <= 100; i++)
    {
    
    
        sum += i;
    }

    printf("Sum = %d", sum);

    // return 0 to operating system
    return 0;
}

预期输出:

Sum = 5050

在这种情况下,expression1被省略,因为循环变量的初始化是在 for 循环之外执行的(第 9 行)。请注意,虽然省略了expression1,但分号(;)必须存在。

例 2: 省略expression2

/*
  2nd variaton - expression2 is omitted
*/

#include<stdio.h>

int main()
{
    
    
    int i, sum = 0;

   for(i = 1 ; ; i++)  // expression 2 is omitted
   {
    
    
       if(i > 100)
       {
    
    
            /* the break statement causes the loop to terminate.
               We will discuss the break statement in detail
               in later chapters.
             */
            break;
        }
        sum += i;
    }
    printf("Sum = %d", sum);

    // return 0 to operating system
    return 0;
}

预期输出:

Sum = 5050

这里省略了条件。为了补偿这种情况,我们添加了 if 语句。当控制进入 for 循环的主体时,检查条件(i>100),如果为假,则省略 if 块中的语句。当i到达100时,条件(i>100)变为真,执行break语句,导致循环终止,程序执行随循环后的语句恢复。

**注意:**语句导致退出循环。在章节中的中断和continue语句中有详细讨论。

例 3: 省略expression3

/*
 3rd variation - expression3 is omitted
*/

#include<stdio.h>

int main()
{
    
    
    int i, sum = 0;

    // expression3 is omitted

    for(i = 1 ; i <= 100 ; )
    {
    
    
        sum += i;
        i++; // update expression
    }

    printf("Sum = %d", sum);

    // return 0 to operating system
    return 0;
}

预期输出:

Sum = 5050

这里省略了第三个表达式。为了补偿第三个表达式,我们在sum += i;语句后添加了i++;

例 4:

/*
   4th variation - all the expressions are omitted
*/
#include<stdio.h>

int main()
{
    
        
    int i = 0; // initialization expression
    int sum = 0;

    for( ; ; )
    {
    
    
        if(i > 100) // condition
        {
    
    
            break; // break out of the for loop
        }
        sum += i;
        i++; // update expression
    }

    printf("Sum = %d", sum);

    // return 0 to operating system
    return 0;
}

预期输出:

Sum = 5050

循环的嵌套

正如 if-else 语句可以嵌套在另一个 if-else 语句中一样,我们可以将任何类型的循环嵌套在任何其他类型的循环中。例如,一个 For 循环可以嵌套在另一个 for 循环中,或者嵌套在 while 或 do while 循环中。同样,while 和 do while 也可以嵌套。

以下程序使用嵌套 for 循环打印半金字塔图案:

#include<stdio.h>

int main()
{
    
    
    int row = 0, col = 0;

    for(row = 0; row < 10; row++)  // number of lines
    {
    
    
        for(col = 0; col < row; col++)  // num of * in each lines
        {
    
    
            printf(" * ");
        }
        printf("\n");
    }

    // return 0 to operating system
    return 0;
}

预期输出:

*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *

工作原理:

在第 5 行,我们已经声明并初始化了两个整数变量rowcol

在第 7-14 行,我们有一个嵌套的 for 循环。外部 for 循环控制要打印的行数,内部 for 循环控制每行要打印的*数。

当执行外部 for 循环时,row变量的值被初始化为0,然后条件(row<10)被测试,因为它是真的(0<10)控制进入外部 for 循环的主体,这是另一个 for 循环。在内部 for 循环中,变量col被初始化为0,然后检查条件(col<=row),因为它是真的(0<=0)。执行内部循环体内部的语句,即printf(" * ")。然后,使用更新表达式col++col增加1(现在col的值为1)。再次测试条件(col<=row),因为它是假的(1<=0)。控件脱离内部 for 循环。第 13 行的printf()语句打印一个换行符(\n)。由于没有更多的语句可以执行,控制转移到外部 for 循环的更新表达式。row的值增加1(现在row1)。测试条件(row<10),因为它是真的(1<10)。再次执行外部 for 循环的主体。这个过程会一直重复直到row<10。当row到达10时,条件row < 10变为假,控制从外环出来。



猜你喜欢

转载自blog.csdn.net/wizardforcel/article/details/143582710