快速入门
什么是C语言?
C是一种编程语言,1972年由Dennis Ritchie在美国AT & T的贝尔实验室开发。C语言变得很流行,因为它很简单,很容易使用。今天经常听到的一个观点是--"C语言已经被C++、Python和Java等语言所取代,所以今天何必再去学习C语言"。我很不赞同这种观点。这有几个原因。这些原因如下:
(a) C++、Python和Java等语言所取代或Java利用一种叫做面向对象编程(OOP)的原则来组织程序,这有很多好处。在使用这种组织原则时,你需要基本的编程技能。因此,首先学习C语言,然后迁移到C++、C#或Java更有意义。虽然这种两步走的学习过程可能需要更多的时间,但在结束时,你一定会发现它值得一试。
(b) 流行的操作系统,如Windows、UNIX、Linux和Android的主要部分都是用C语言编写的。此外,如果要扩展操作系统以与新设备一起工作,就需要编写设备驱动程序。这些程序完全是用C语言编写的。
(c) 像微波炉、洗衣机和数码相机这样的普通消费设备正变得越来越智能。这种智能来自于这些设备中嵌入的微处理器、操作系统和程序。这些程序必须快速运行并在有限的内存中工作。C语言是建立这种操作系统和程序时的首选语言。
(d) 你一定见过一些专业的3D电脑游戏,用户在游戏中浏览一些物体,比如说一艘宇宙飞船,向入侵者发射子弹。所有这类游戏的本质是速度。为了满足这种对速度的期望,游戏必须对用户的输入做出快速反应。用于创建此类游戏的流行游戏框架(如DirectX)是用C语言编写的。
学习C语言的步骤
学习英语和学习C语言之间存在着密切的相似性。
常量、变量和关键词
当字母、数字和特殊符号恰当地结合在一起时,就形成了常数、变量和关键词。常量是不改变的实体,而变量是可能改变的实体。关键字是具有特殊含义的词。在编程语言中,常量通常被称为字面量,而变量则被称为标识符。现在让我们看看C语言中存在哪些不同类型的常量和变量。
C语言常量的类型
C语言中的常量可分为两大类:
(a) 主要常量
(b) 次要常量
这些常量可进一步分类。
在这个阶段,我们将只讨论初级常量,即整数、实数和字符常量。以下是构建这些不同类型常量的规则:
- 构造整数常数的规则
(a) 整数常数必须至少有一个数字。
(b) 它不能有小数点。
(c) 它可以是零、正或负的任何一种。如果一个整数常数前面没有符号,则假定它是正数。
(d) 整数常数内不允许有逗号或空号。
(e) 整数常数的允许范围是-2147483648到+2147483647。
例如:+325.34 426.0 -32.76 -48.5792
实际上,整数常数的范围取决于编译器。对于像Visual Studio, GCC这样的编译器,范围是-2147483648到+2147483647,而对于像Turbo C或Turbo C++这样的编译器,范围是-32768到+32767。
- 构建实数常量的规则
实数常数通常被称为浮点常数。实数常量可以写成两种形式--小数形式和指数形式。在构建小数形式的实数常数时必须遵守以下规则:
(a) 实数常数必须至少有一个数字。
(b) 它必须有一个小数点。
(c) 它可以是正数或负数。默认符号为正。
(d) 实数常数内不允许有逗号或空白。
例如:+325.34 426.0 -32.76 -48.5792
如果常数的值过小或过大,通常会使用指数形式。然而,它并不限制我们对其他实数常数使用指数形式。
在指数形式中,实数常数由两部分组成。出现在'e'之前的部分被称为尾数,而'e'之后的部分被称为指数。因此,0.000342可以用指数形式写成3.42e-4(在普通算术中意味着3.42 x 10-4)。
在构建以指数形式表示的实数常数时必须遵守以下规则:
(a) 尾数部分和指数部分应以字母e或E分开。
(b) 尾数部分可以有正号或负号。默认符号为正。
(c) 指数必须至少有一个数字,可以是正数或负数的整数。默认符号为正。
(d) 用指数形式表示的实数常数的范围是-3.4e38到3.4e38。
例:+3.2e-5 4.1e8 -0.2E+3 -3.2e-5
- 构建字符常量的规则
(a) 字符常量是字母、数字或特殊符号,包含在单引号内。
例如:'A' 'I' '5' '='
参考资料
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- 本书英文原版: Let Us C Authentic Guide to C Programming Language (17th Edition) -2020 A4.5-804 p485.epub
https://url97.ctfile.com/f/18113597-853620132-541682 下载密码 订阅号pythontesting 发送 密码 。
C语言变量的类型
一个特定类型的变量只能容纳同一类型的常数。例如,一个整数变量只能容纳一个整数常数,一个实数变量只能容纳一个实数常数,一个字符变量只能容纳一个字符常数。因此,C语言中变量的类型和常量的类型一样多。
在任何C语言程序中,都要进行许多计算。这些计算的结果被储存在计算机内存的一些单元(位置)中。为了便于检索和使用这些数值,内存单元被赋予了名称。由于存储在每个位置的值可能会发生变化,所以给这些位置的名称被称为变量名称。
构建不同类型常量的规则是不同的。然而,对于构建所有类型的变量名,同样的规则适用。
- 构建变量名称的规则
(a) 变量名称是1到31个字母、数字或下划线的任何组合。有些编译器允许变量名的长度可以达到247个字符。不要创建不必要的长的变量名,因为它增加了你的打字工作量。
(b) 变量名的第一个字符必须是字母或下划线(_)。
例如:si_int pop_e_89 avg basic_salary
我们应该始终创建有意义的变量名称。例如,在计算单利的时候,我们应该建立像prin, roi, noy这样的变量名来表示原则、利率和年数,而不是像a, b, c这样的任意变量。
创建变量名称的规则对于所有类型的主要变量和次要变量都是一样的。因此,为了帮助区分变量,必须声明我们希望在程序中使用的任何变量的类型。这种类型的声明是如下所示。
例如
int si, m_hra;
float bassal;
char code;
C语言的关键字
关键字是指那些已经向C语言编译器(或广义上的计算机)解释过含义的词。C语言中只有32个关键词。
这些关键字不应作为变量名使用。然而,一些 C 编译器允许你构建与这些关键字完全相似的变量名。
编译器供应商还提供了更多的关键字。尽管ANSI委员会建议这样的编译器特定的关键字都应该在前面加上两个下划线(如___asm),但并不是每个厂商都遵守这个规则。
第一个C语言程序
一旦掌握了变量、常量和关键字的知识,下一个合乎逻辑的步骤就是将它们组合成指令。然而,我们现在要做的不是这样,而是编写我们的第一个C语言程序。一旦我们完成了这一工作,我们将详细了解它所使用的指令。
第一个程序非常简单。它为一组代表本金、年数和利率的数值计算单利。
void main()
{
int p, n ;
float r, si ;
p = 1000 ;
n = 3 ;
r = 8.5 ;
/* formula for simple interest */
si = p * n * r / 100 ;
printf ( "%f" , si ) ;
}
- C语言程序的形式
(a) C语言程序中的每条指令都被写成一个单独的语句。
(b) 程序中的语句必须按照我们希望它们被执行顺序出现。
(c) 两个字之间可以插入空白,以提高语句的可读性。
(d) 所有语句都应使用小写字母。
(e) 每个C语句必须以分号(;)结束。因此,;作为语句的结束符。
(f) C语句可以写在指定行的任何地方。这就是为什么它经常被称为自由形式的语言。
(g) 通常每一行包含一条语句。然而,你可以在一行中写多个语句,只要每个语句以;结束。
- C语言程序中的注释
C语言程序中的注释是用来澄清程序的目的或程序中某些语句的目的。一个好的做法是,在程序开始时用注释说明程序的目的、作者和程序的编写日期。
下面是在C语言程序中写注释的一些提示:
(a) 注释可以是小写的,也可以是大写的,也可以是混合的。它们应该被括在/* */内。因此,我们程序中的前两条语句就是注释。
(b) 有时,程序中某一特定语句的作用并不十分明显。在这种情况下,可以用注释来提及该语句的目的。
(c) 任何数量的注释都可以写在程序的任何地方。因此,注释可以写在语句之前、语句之后或语句之内。
(d) 注释不能被嵌套。这意味着一个注释不能写在另一个注释里面。所以下面的注释是无效的。
(e) 注释可以分割成多行。
(f) ANSI C允许用另一种方式来写注释,如下:
// Calculation of simple interest
// Formula
- 什么是main()?
(a) main()是一个函数。它是一组语句的容器。一个C语言程序可以有多个函数。如果它只包含一个函数,其名称必须是main()。所有属于main()的语句都包含在一对大括号{}中。
(b) 像计算器中的函数一样,C语言中的函数也会返回一个值。 main()函数总是返回一个整数值,因此在main()前面有一个int。这被称为该函数的返回类型。我们要返回的整数值是0,0表示成功。如果main()中的语句未能完成其预期的工作,我们可以从main()中返回一个非零的数字。这将表示失败。
(c) 观察main()返回值的方式在不同的编译器中有所不同,如下所示。
Turbo C, Turbo C++ - Alt C | 信息
Visual Studio - 调试器观察窗口中的$ReturnValue
Linux - 在程序执行后的命令提示符中回显$?
(d) 有些编译器如Turbo C/C++甚至允许我们从main()中不返回任何东西。在这种情况下,我们应该在它前面加上关键字void。但这是写main()函数的非标准方式。
- 变量和它们的用法
(a) 程序中使用的任何变量必须在使用前声明。例如、
(b) C语言中可用的算术运算符是+、-、*和/。
- printf()和它的用途
C语言不包含任何在屏幕上显示输出的关键字。所有对屏幕的输出都是通过库函数如printf()实现的。
(a) 一旦si的值被计算出来,它就需要显示在屏幕上。我们使用了printf()来实现这一目的。
(b) 为了能够使用printf()函数,有必要在程序的开头使用#include <stdio.h>。#include是一个预处理器指令
(c) printf()函数的一般形式是
printf (“<format string>”, <list of variables>);
format string可以包含:
%f用于打印实数值
%d用于打印整数值
%c用于打印字符值
除了像%f、%d和%c这样的格式指定符外,格式字符串还可以包含任何其他字符。这些字符在执行printf()时被打印出来。
(d) 下面是一些使用printf()函数的例子:
printf (“%f”, si);
printf (“%d %d %f %f”, p, n, r, si);
printf (“Simple interest = Rs. %f”, si);
printf (“Principal = %dnRate = %f”, p, r);
最后一条语句的输出会是这样的...
Principal = 1000
Rate = 8.500000
由于换行符'n'的存在,输出被分成了两行。它把光标送到了下一行。它是C语言中可用的几个转义序列之一。
(e) printf()可以打印变量的值以及表达式的结果,如3、3+2、c和a+b*c-d,如下所示。
printf (“%d %d %d %d”, 3, 3 + 2, c, a + b * c - d);
请注意,3和c也代表有效的表达式。
- 编译和执行
一旦你写好了程序,你需要输入它并指示机器执行它。要做到这一点,还需要两个程序--编辑器和编译器。编辑器让我们输入程序,而编译器将我们的程序转换为机器语言程序。这种转换是必要的,因为机器只能理解机器语言。
除了这两个程序外,还有其他程序,你可能需要它们来提高你的编程效率--预处理器、链接器和调试器。单独使用它们中的每一个都是一项乏味的工作。因此,通常所有这些程序都被捆绑在一起,在它们上面有一层图形用户界面。GUI使你更容易使用这些程序。这种捆绑通常被称为集成开发环境(IDE)。
有许多IDE可用。每个都是针对不同的操作系统和微处理器的。
[Running] cd "/home/andrew/code/SourceCode/Source Code/Chap01/" && gcc doc1.c -o doc1 && "/home/andrew/code/SourceCode/Source Code/Chap01/"doc1
255.000000
[Done] exited with code=10 in 0.044 seconds
接收输入
#include <stdio.h>
int main( )
{
int p, n ;
float r, si ;
printf ( "Enter values of p, n, rn" ) ;
scanf ( "%d %d %f", &p, &n, &r ) ;
si = p * n * r / 100 ;
printf ( "%f" , si ) ;
}
执行
$ ./doc2
Enter values of p, n, r
1000 5 3.5
第一个printf()在屏幕上输出 "输入p、n、r的值 "的信息。这里我们没有在printf()中使用任何表达式,这意味着在printf()中使用表达式是可选的。
注意在scanf()函数中的变量前使用&是必要的,&是 "地址 "运算符。它给出变量在内存中使用的位置号(地址)。当我们说&a时,我们在告诉scanf()应该在哪个内存位置存储用户从键盘提供的值。
请注意,在提供给scanf()的数值之间必须有一个空白、一个制表符或一个新行。空白用空格键创建,制表符用Tab键,换行用Enter键。
指令
指令的类型
在C语言中,有三种类型的指令:
(a) 类型声明指令 - 该指令用于声明C语言程序中使用的变量的类型。
(b) 算术指令 - 该指令用于对常数和变量进行算术运算。
(c) 控制指令 - 该指令用于控制C语言程序中各种语句的执行顺序。
类型声明指令
这条指令用于声明程序中使用的变量的类型。类型声明语句写在main()函数的开头。下面是几个例子。
int bas;
float rs, grosssal;
char name, code;
下面是类型声明指令的一些微妙变化......
(a) 在声明变量类型的同时,我们也可以对其进行初始化,如下所示。
int bas;
float rs, grosssal;
char name, code;
(b) 在使用一量之前必须先定义它。下面的语句是非法的,因为我们在定义变量a之前就使用了它。
int i = 10, j = 25;
float a = 1.5, b = 1.99 + 2.4 * 1.44;
(c) 下面的语句可以工作
int a, b, c, d;
a = b = c = 10;
然而,下面的语句将不工作
int a = b = c = d = 10;
算术指令
C语言中的算术指令由=左边的变量名和=右边使用运算符连接的变量名和常数组成。
int ad;
float kot, deta, alpha, beta, gamma;
ad = 3200;
kot = 0.0056;
deta = alpha * beta / gamma + 3.2 * 2 / 5;
*, /, -, +是算术运算符。
= 是赋值运算符。
2、5和3200是整数常数。
3.2和0.0056是实数常数。
ad是一个整数变量。
kot, deta, alpha, beta, gamma是实数变量。
变量和常数一起被称为 "操作数"。在执行算术语句时,右手边的操作数由 "算术运算符 "操作,结果用赋值运算符分配给左手边的变量。
C语言中的算术语句可以有三种类型。这些类型如下:
(a) 整数模式算术语句--在这个语句中,所有操作数都是整数变量或整数常数。
int i, king, issac, noteit;
i = i + 1;
king = issac * 234 + noteit - 7689;
(b) 实模式算术语句--在该语句中,所有操作数都是实数常数或实数变量。
float qbee, antink, si, prin, anoy, roi;
qbee = antink + 23.123 / 4.5 * 0.3442;
si = prin * anoy * roi / 100.0;
(c) 混合模式算术语句 - 在这个语句中,一些操作数是整数,一些操作数是实数。
float si, prin, anoy, roi, avg;
int a, b, c, num;
si = prin * anoy * roi / 100.0;
avg = (a + b + c + num) / 4;
请仔细注意关于算术指令的以下几点:
(a) C语言只允许在=的左边有一个变量,也就是说,z = k * l是合法的,而k * l = z是非法的。
(b) 除了除法运算符之外,C语言还提供了去模运算符。这个运算符返回一个整数除以另一个整数的余数。因此,表达式10 / 2产生5,而10 % 2则产生0。
请注意,模数运算符(%)不能应用于浮点数。还要注意,在使用%时,余数的符号总是与分子的符号相同。因此,-5 % 2的结果是-1,而5 % -2的结果是1。
(c) 算术运算可以在整数、浮点数和字符上进行。因此,下面的语句是有效的。
char x = ’a’, y = ’b’;
int z = x + y;
ASCII代码用于表示内存中的任何字符。a "和 "b "的ASCII代码是01100001和01100010。它们的十进制等价物是97和98。加法是在这些十进制值上进行的,而不是在字符本身上。
(d) 没有假定存在运算符。它必须明确地写出来。在下面的例子中,b后面的乘法运算符必须明确地写出来。
a = c.d.b(xy) usual arithmetic statement
a = c * d * b * (x * y) C statement
(e) C语言中没有运算符来进行指数化操作。指数运算必须按以下方式进行:
#include <stdio.h>
#include <math.h>
void main()
{
float a;
a = pow(3.0, 2.0);
printf("%f", a);
}
执行结果
9.000000
这里pow()函数是一个标准库函数。它被用来将3.0的2.0的幂。pow()函数只对实数工作,因此我们使用了3.0和2.0。
请注意,为了使pow()函数工作,有必要#include <math.h>。
你可以自己探索其他数学函数,如abs()、sqrt()、sin()、cos()、tan()等,这些函数在math.h中声明。
整数和浮点数的转换
(a) 整数和整数之间的算术运算总是产生整数的结果。
(b) 实数和实数之间的运算总是产生实数结果。
(c) 整数和实数之间的运算总是产生实数结果。在这个操作中,整数首先被提升为实数,然后再进行操作。因此,其结果是实数。
赋值中的类型转换
如果两边表达式的类型不一样,那么右边上的表达式的值就会被提升或降低,这取决于=左边的变量的类型。 例如,考虑以下赋值语句:
int i;
float b;
i = 3.5;
b = 30;
在第一条赋值语句中,虽然3.5是一个浮点数,但由于它是一个int,所以不能被存储在i中。因此,3.5(浮点数)被降级为3(int),然后存储在i中。在这里,30被提升为30.0,然后存储在b中。
如果出现复杂的表达式,仍然适用同样的规则。例如,考虑下面的程序片段。
操作符优先级
如果有一组以上的括号,最里面的括号内的操作将首先被执行,然后是最里面的第二组括号内的操作,以此类推。
一些代数表达式及其等价的C语言表达式的例子见图
运算符的相关性
当一个表达式包含两个优先级相同的运算符时,它们之间的平局将通过运算符的相关性来解决。C语言中的所有运算符都有从左到右的相关性或从右到左的相关性。让我们借助几个例子来理解这一点。
考虑一下这个表达式:a = 3 / 2 * 5;
这里有一个相同优先级的运算符之间的平局,即在/和之间。这个平局是利用/和的关联性来解决的。两者都享有从左到右的关联性。因此,首先进行的是/操作,然后是*。
再考虑一个表达式:a = b = 3;
这里,两个赋值运算符都有相同的优先级。所以操作的顺序是由=运算符的关联性决定的。因此,第二个=比第一个=早执行。
再考虑另一个表达式:z = a * b + c / d;
这里和/享有相同的优先级和相同的关联性(从左到右)。编译器可以根据自己的需要自由地执行或/操作,因为无论哪个操作在前面执行,结果都是一样的。
控制指令
控制指令控制程序中指令的执行顺序。换句话说,控制指令决定了程序中的 "控制流"。在C语言中,有四种类型的控制指令,它们是
(a) 顺序控制指令
(b) 选择或决定控制指令
(c) 重复或循环控制指令
(d) case控制指令
顺序控制指令确保指令按照它们在程序中出现的相同顺序执行。决定和case控制指令允许计算机决定下一步执行哪个指令。循环控制指令有助于重复执行一组语句。
条件控制
if - else语句
C语言使用关键字if和else来实现决策控制指令。这个语句的一般形式是这样的:
if (this condition is true)
statement1;
else
statement2;
关键字if后面的条件总是包含在一对小括号内。如果该条件为真,则执行语句1。如果条件不为真,则执行语句2。条件是用C语言中的 "关系 "运算符表示的,这些运算符允许我们比较两个值。图3.1显示了它们在C语言中的外观和评估方式。
这里是等于运算符,!=是不等运算符。请注意,=用于赋值,而则用于两个量的比较。
例3.1: 在购买某些物品时,如果购买的数量超过1000件,可以享受10%的折扣。如果通过键盘输入每件物品的数量和价格,写一个程序来计算总的费用。
#include <stdio.h>
int main()
{
int qty, dis;
float rate, tot;
printf ("Enter quantity and rate:");
scanf ("%d %f", &qty, &rate);
if (qty > 1000)
dis = 10;
else
dis = 0;
tot = (qty * rate) - (qty * rate * dis / 100);
printf ("Total expenses = Rs. %fn", tot);
return 0;
}
下面是一些与程序互动的例子。
Enter quantity and rate 1200 15.50
Total expenses = Rs. 16740.000000
Enter quantity and rate 200 15.50
Total expenses = Rs. 3100.000000
在if-else中的多条语句
在一个程序中,当if后面的表达式得到满足时,我们可能要执行一个以上的语句。如果要执行这样的多条语句,就必须把它们放在一对大括号内,如下面的例子所示:
例3.2:在一家公司里,一个雇员的工资如下:
如果他的基本工资低于1500卢比,那么HRA=基本工资的10%,DA=基本工资的90%。如果他的工资等于或高于1500卢比,那么HRA=500卢比,DA=基本工资的98%。如果员工的工资是通过键盘输入的,那么写一个程序来找出他的工资总额。
实现这一逻辑的程序如下。
/* Calculation of gross salary */
# include <stdio.h>
int main()
{
float bs, gs, da, hra;
printf ("Enter basic salary");
scanf ("%f", &bs);
if (bs < 1500)
{
hra = bs * 10 / 100;
da = bs * 90 / 100;
}
else
{
hra = 500;
da = bs * 98 / 100;
}
gs = bs + hra + da;
printf ("gross salary = Rs. %fn", gs);
return 0;
}
关于这个程序,有几点值得注意...
(a) if之后到else为止的一组语句被称为 "if块"。同样,else之后的语句构成 "else块"。
(b) 注意,else正好写在if的下面。if块中的语句和else块中的语句都是向右缩进的。
(c) 如果在if块中只执行一条语句,在else块中只执行一条语句,我们可以放弃这对大括号。
(d) if和else的默认范围是紧随其后的语句。要覆盖这个默认范围,必须使用一对大括号。
嵌套的if-elses
如果我们在if块或else块中再写一个if-else结构,这是完全可以的。这被称为 "嵌套",在下面的代码片段中显示:
if (i == 1)
printf (“You would go to heaven !n”);
else
{
if (i == 2)
printf (“Hell was created with you in mindn”);
else
printf (“How about mother earth !n”);
}
注意第二个if-else结构是嵌套在第一个else块中的。如果第一个if中的条件是假的,那么第二个if中的条件将被检查。如果它也是假的,那么第二个else将被执行。
你可以观察到,每次if-else结构嵌套在另一个if-else结构中时,它也会缩进,以增加程序的清晰度。培养这种缩进的习惯;否则,你最终写出的程序将没有人(包括你)能够在以后的日子里轻松理解。请注意,无论我们缩进还是不缩进程序,都不会改变程序中指令的执行流程。
在上面的程序中,if-else发生在第一个if语句的 "else块 "中。同样,在其他一些程序中,if-else也可能出现在 "if块 "中。对于if和else的嵌套深度没有限制。
注意事项
尽管通常在if语句中使用一个条件,但任何有效的表达式也可以。因此,以下所有的if语句都是有效的。
if (3 + 2 % 5)
printf (“This works”);
if (a = 10)
printf (“Even this works”);
if (-5)
printf (“Surprisingly even this works”);
请注意,在C语言中,非零值被认为是真,而0被认为是假。在第一个if中,表达式评估为5,由于5是非零值,所以它被认为是真的。因此printf()被执行。
在第二个if中,10被分配给a,所以现在的if被简化为if(a)或if(10)。由于10是非零,它是真的,因此printf()又开始工作了。
在第三个if中,-5是一个非零数,因此是真的。所以printf()又开始工作了。即使使用3.14这样的浮点数来代替-5,也会被认为是真的。所以问题不在于这个数字是整数还是浮点数,也不在于它是正数还是负数。问题是它是零还是非零。
在使用if语句时,另一个常见的错误是在条件后面写一个分号(;),如下所示。
if (i == 1)
scanf (“%d”, &i);
if (i == 5);
printf (“You entered 5n”);
这使编译器将该语句解释为你是以如下方式写的:
if (i == 5)
;
printf (“You entered 5n”);
在这里,如果条件评估为真,就会执行;(空语句,执行时不做任何事情),接着执行printf()。如果条件失败,则直接执行printf()。因此,无论条件的评估结果是真还是假,printf()都会被执行。记住,编译器不会指出这是一个错误,因为就语法而言,没有出错,但逻辑肯定出错了。
文章来源: 博客园
- 还没有人评论,欢迎说说您的想法!