从零开始学C语言
@阆苑祁寒
更新时间:2019-09-13
写在前面:本文从一个初学者的角度,给出了对C语言的简单理解。如有谬误,敬请指出!
Week1——基本语法
1 #include 2 int main(void) 3 { 4printf("Hello, world! /n"); 5return 0; 6 }
基本语法解释:
- stdio 系统文件库,除stdio有诸多类型的库函数,stdio中最常用的是printf()函数。
- .h头文件
- #include 预处理器导入头文件,可python的inform和latex的\usepackage是一个道理.
- <> C标准库,写成""表示自定义的库,常见的有标准数据传输库和数学库
,具体参考相关附录. - int 返回一个整数,表示整型数据结构,还有其他种类的数据结构,对应到二进制,拥有巧妙的运算规则.有以下几种类型:字符型(char)→整型(int: short/long/long long; signed/unsigned)→浮点型(float,double,long double),需要特别注意常量的类型和数值溢出(精度)这两个问题.
- main 所有C文件有且只有一个主函数(入口函数),在C++中main()表示不需要参数,在C中main(void)表示不需要参数(当然前一种情况也可以运行),注意没有void main这种说法,int main(int argc, char *argv[])表示需要参数,argc为给程序的参数的个数,argv中保存的是给函数的参数,都是字符串。
- printf()输出到屏幕,必须调用头文件,是标准数据传输库下两个最重要的函数(另外一个是scanf,格式与printf类似,只是参量表前需要加地址符&),其调用格式是 printf("<格式化字符串>", <参量表>); ,库函数的声明是 int printf(const char *format, ...) ,其中字符串format包含了要被写入到标准输出 stdout 的文本,可以包含嵌入的 format 标签,其标签属性是 %[name][flags][width][.precision][length]specifier ,可被随后的附加参数中指定的值替换,并按需求进行格式化。注意每一个printf()可以有多个format标签,写成 %[name]%[name] 格式,中间无需逗号。(注:scanf函数可以识别的数据类型是 [number] [number] (空格输入)和 [number]\n[number] (换行输入),特别,中间如果是逗号则不能识别。)更多内容参考下表(摘自附录):
name | 意义 |
---|---|
d | 以十进制形式输出带符号整数(正数不输出符号) |
o | 以八进制形式输出无符号整数(不输出前缀0) |
x,X | 以十六进制形式输出无符号整数(不输出前缀Ox) |
u | 以十进制形式输出无符号整数 |
f | 以小数形式输出单、双精度实数 |
e,E | 以指数形式输出单、双精度实数 |
g,G | 以%f或%e中较短的输出宽度输出单、双精度实数 |
c | 输出单个字符 |
s | 输出字符串 |
p | 输出指针地址 |
lu | 32位无符号整数 |
llu | 64位无符号整数 |
flags | 意义 |
---|---|
- | 在给定的字段宽度内左对齐,默认是右对齐(参见 width 子说明符)。 |
+ | 强制在结果之前显示加号或减号(+ 或 -),即正数前面会显示 + 号。默认情况下,只有负数前面会显示一个 - 号。 |
空格 | 如果没有写入任何符号,则在该值前面插入一个空格。 |
# | 与 o、x 或 X 说明符一起使用时,非零值前面会分别显示 0、0x 或 0X。 与 e、E 和 f 一起使用时,会强制输出包含一个小数点,即使后边没有数字时也会显示小数点。默认情况下,如果后边没有数字时候,不会显示显示小数点。 与 g 或 G 一起使用时,结果与使用 e 或 E 时相同,但是尾部的零不会被移除。 |
0 | 在指定填充 padding 的数字左边放置零(0),而不是空格(参见 width 子说明符)。 |
width | 意义 |
---|---|
(number) | 要输出的字符的最小数目。如果输出的值短于该数,结果会用空格填充。如果输出的值长于该数,结果不会被截断。 |
* | 宽度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。 |
.precision | 意义 |
---|---|
.number | 对于整数说明符(d、i、o、u、x、X):precision 指定了要写入的数字的最小位数。如果写入的值短于该数,结果会用前导零来填充。如果写入的值长于该数,结果不会被截断。精度为 0 意味着不写入任何字符。 对于 e、E 和 f 说明符:要在小数点后输出的小数位数。 对于 g 和 G 说明符:要输出的最大有效位数。 对于 s: 要输出的最大字符数。默认情况下,所有字符都会被输出,直到遇到末尾的空字符。 对于 c 类型:没有任何影响。 当未指定任何精度时,默认为 1。如果指定时不带有一个显式值,则假定为 0。 |
.* | 精度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。 |
length | 意义 |
---|---|
h | 参数被解释为短整型或无符号短整型(仅适用于整数说明符:i、d、o、u、x 和 X)。 |
l | 参数被解释为长整型或无符号长整型,适用于整数说明符(i、d、o、u、x 和 X)及说明符 c(表示一个宽字符)和 s(表示宽字符字符串)。 |
L | 参数被解释为长双精度型(仅适用于浮点数说明符:e、E、f、g 和 G)。 |
- return 0 参量为空时结束循环(为了使代码严谨,必须要加)。return表示返回一个函数的值,在C中没有真假值一说,与python不同,即没有return false和return ture,返回函数return参见后续内容。
- /n 是C语言中的转义字符,借助/以示与字符(参见ASCII表)的区别。更多内容参考下表(摘自附录):
文章图片
- C标识符 区分大小写,不允许出现除"_"之外的特殊字符(参见ASCII表),为避免与常量的区别,禁止用数字开头,通常由写为"(字母)_(数字)"的形式,且字母要求具有一些明确的含义,不可选用关键字。原则上,可以选用一些库函数中的函数名,但是没有必要,徒增混乱!
- C注释 单行可以用\\注释,多行可以用\*和*\注释,后者更为规范,其本质是预编译时以一个空格代之(搜索\*和*\,也是不能嵌套的原因)。
- ; C语句结束语,否则需要用{}括起来。
- C关键字 不能作为常量名、变量名或其他标识符名称。更多内容参考下表(摘自附录),并注明不常见的关键字。
auto | 声明自动变量 |
break | 跳出当前循环 |
case | 开关语句分支 |
char | 声明字符型变量或函数返回值类型 |
const | 声明只读变量 |
continue | 结束当前循环,开始下一轮循环 |
default | 开关语句中的"其它"分支 |
do | 循环语句的循环体 |
double | 声明双精度浮点型变量或函数返回值类型 |
else | 条件语句否定分支(与 if 连用) |
enum | 声明枚举类型 |
extern | 声明变量或函数是在其它文件或本文件的其他位置定义 |
float | 声明浮点型变量或函数返回值类型 |
for | 一种循环语句 |
goto | 无条件跳转语句 |
if | 条件语句 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数返回值类型 |
register | 声明寄存器变量 |
return | 子程序返回语句(可以带参数,也可不带参数) |
short | 声明短整型变量或函数 |
signed | 声明有符号类型变量或函数 |
sizeof | 计算数据类型或变量长度(即所占字节数) |
static | 声明静态变量 |
struct | 声明结构体类型 |
switch | 用于开关语句 |
typedef | 用以给数据类型取别名 |
unsigned | 声明无符号类型变量或函数(正数) |
union | 声明共用体类型 |
void | 声明函数无返回值或无参数,声明无类型指针 |
volatile | 说明变量在程序执行中可被隐含地改变 |
while | 循环语句的循环条件 |
- 空格 描述空白符、制表符、换行符和注释,空格分隔语句的各个部分,让编译器能识别语句中的某个元素(如int)在哪里结束,下一个元素在哪里开始。同时也是ASCII表中的特殊字符,由于在C语言中具有特殊的意义,故列出。
- 函数与存储类型 除主函数main之外的其他函数,需要命名为除main之外的名字以便识别,常见写法为“函数名(需要返回的数据类型和参量)”(C99之后的存储类型没有必要写出),这里的参量与函数内局部声明的参量不同(需要返回!),这也是当参量为空时写return 0的原因。更多地,计算机硬件部分分为外存→内存→快存(cache,预测CUP动作,算法固定,不受人工干预)→寄存器(与CPU伴生,存储中间运算过程),调用速度是递增的,存储类型分为"内存"和"寄存器"两种类型,默认是"内存",故没必要写出。
- 引号 单引号表示一个字符,双引号表示字符串(指针),前者被编译为字符编码(注意ASCII表中的对应关系,也即char类型),后者被编译为内存,有关指针的内容在后续指出。
1.利用星号和空格输出一个爱心形状。 2.键盘输入x的值,求方程y=x*x+2*x-10所对应的y值。 3.以下程序求两个输入的整数的和,请找出其中的错误。Week2——结构化与基本语句 程序的灵魂是算法,算法的核心是逻辑,语言只是表达给机器的工具(尤其是C,既面向机器,又面向用户)。不同于其他语言,C面向过程,只能实现函数与函数的互相调用,而不能嵌套,其逻辑本质可以平延到高级语言对包的调用。C语言中最常见的语句列表如下。 常用语句解释: 顺序结构
文章图片
文章图片
1 #include 2 3 int main() 4 { 5int a,b,sum; 6 7sum=a+b; 8a=1; 9b=2; 10 11printf("sum=%d\n",sum); 12 }
题目3的代码 4.以下程序求1到100的和,请找出其中的错误。
文章图片
文章图片
1 #include 2 3 int main() 4 { 5int a,i,sum; 6 7i=0; 8while(i<=100) 9{ 10sum=sum+i; 11i=i+1; 12} 13 14printf("1+2+...+100=%d\n",sum); 15 16 }
题目4的代码 5.已知在某C语言编译系统中表达式 sizeof(int) 的值是2,如果希望将常量-70000正确的保存在一个变量a中,该变量声明语句应当是()
A. int a; B.long int a;
C. unsigned int a; D.unsigned long int a;
6.设int类型的数据长度为2个字节,则unsigned int类型数据的取值范围是()
A.0~255B.0~65535
C.-32768~32767D.-256~255
7.在C语言中,数字029是一个()
A.八进制数B.十六进制数
C.十进制数D.非法数
8.以下标识符中不能用做变量名或自定义函数名的是()
A.mainB. scanfC._floatD. sizeof
9.在以下各组标识符中,均可以用作变量名的一组是()
A.A01, IntB. table_1, a *.1
C.0_a, W12D. for, point
10.以下叙述中正确的是()
A. 在C程序中,main函数必须位于程序的最前面
B. C程序的每行只能写一条语句
C. C语言本身没有输入输出语句
D. 在对一个C程序进行编译的过程中,可发现注释中的拼写错误
11.以下叙述不正确的是()
A. 一个C源程序可由一个或多个函数组成
B. 一个C源程序必须包含一个main函数
C. C程序的基本组成单位是函数
D. 在C程序中,注释说明只能位于一条语句的后面
12.C语言规定:在一个源程序中,main函数的位置()
A. 必须在最开始
B. 必须在系统调用的库函数的后面
C. 可以任意
D. 必须在最后
13.编写程序,判断并输出所使用的编译器每种基本类型变量所占的存储空间大小。
14.编写程序,输入一个长方体的长、宽和高(整数),输出这个长方体的体积。
15.编写程序,读取一个在0和1000之间的整数,并将该整数的各位数字相加。
16.编写程序,提示用户输入分钟数(例如10000000),然后显示这些分钟代表的时长(多少年多少天),为了简化问题,假设一年有365天。
17.编写程序,计算将水从初始温度加热到最终温度所需的能量Q=M×(最终温度 – 初始温度)× 4184。
18.编写程序,从键盘输入一个4位正整数,输出该数的反序数。
19.一个美国政府的研究实验室得出结论,认为在肥宅快乐水中常用的人造甜味剂会导致实验室老鼠的死亡。你的一个朋友在拼命的减肥,但是他不能放弃肥宅快乐水。你的朋友想知道能够喝多少汽水而不会导致死亡。请编写程序,帮他回答这个问题。已知实验时,杀死一只老鼠所用的人造甜味剂是5g,老鼠的重量为35g。假设老鼠的致死量(lethal dose)成比例对应于人的致死量。一罐肥宅快乐水350g,其中所含的人造甜味剂占0.1%。输入你的朋友的体重(Kg),输出他最多可以喝的肥宅快乐水的罐数。
20.(未完待续)
- 表达式语句:赋值和调用函数。
- 复合语句:用{}括出,通常含局部声明和语句两部分。
- 空语句:例如连续输入字符,遇到a则停止,可用getchar表示, while(getchar()!='a'); 。
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
1 | [] | 数组下标 | 数组名[整型表达式] | 左到右 | |
() | 圆括号 | (表达式)/函数名(形参表) | |||
. | 成员选择(对象) | 对象.成员名 | |||
-> | 成员选择(指针) | 对象指针->成员名 | |||
2 | - | 负号运算符 | -算术类型表达式 | 右到左 | 单目运算符 |
(type) | 强制类型转换 | (纯量数据类型)纯量表达式 | |||
++ | 自增运算符 | ++纯量类型可修改左值表达式 | 单目运算符 | ||
-- | 自减运算符 | --纯量类型可修改左值表达式 | 单目运算符 | ||
* | 取值运算符 | *指针类型表达式 | 单目运算符 | ||
& | 取地址运算符 | &表达式 | 单目运算符 | ||
! | 逻辑非运算符 | !纯量类型表达式 | 单目运算符 | ||
~ | 按位取反运算符 | ~整型表达式 | 单目运算符 | ||
sizeof | 长度运算符 | sizeof 表达式 sizeof(类型) | |||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | 双目运算符 | ||
% | 余数(取模) | 整型表达式%整型表达式 | 双目运算符 | ||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | 双目运算符 | ||
5 | << | 左移 | 整型表达式<<整型表达式 | 左到右 | 双目运算符 |
>> | 右移 | 整型表达式>>整型表达式 | 双目运算符 | ||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | 双目运算符 | ||
< | 小于 | 表达式<表达式 | 双目运算符 | ||
<= | 小于等于 | 表达式<=表达式 | 双目运算符 | ||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | 双目运算符 | ||
8 | & | 按位与 | 整型表达式&整型表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 整型表达式^整型表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 整型表达式|整型表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 可修改左值表达式=表达式 | 右到左 | |
/= | 除后赋值 | 可修改左值表达式/=表达式 | |||
*= | 乘后赋值 | 可修改左值表达式*=表达式 | |||
%= | 取模后赋值 | 可修改左值表达式%=表达式 | |||
+= | 加后赋值 | 可修改左值表达式+=表达式 | |||
-= | 减后赋值 | 可修改左值表达式-=表达式 | |||
<<= | 左移后赋值 | 可修改左值表达式<<=表达式 | |||
>>= | 右移后赋值 | 可修改左值表达式>>=表达式 | |||
&= | 按位与后赋值 | 可修改左值表达式&=表达式 | |||
^= | 按位异或后赋值 | 可修改左值表达式^=表达式 | |||
|= | 按位或后赋值 | 可修改左值表达式|=表达式 | |||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | 从左向右顺序结合 |
- 运算符运算:括号>单目>算术>关系>逻辑>赋值,以及多目运算.
- if语句: if(){; }else (if){; } ,允许嵌套.
- switch语句:多种情况的另一种表示法 switch(){case (int型) : (语句); [break; ]default: (语句); } ,允许嵌套.
- while语句: while((控制语句)){; } ,允许嵌套.
- do-while语句: do{; }while((控制语句)); ,允许嵌套.
- for语句:for((初值); (控制语句); (控制变量)){; } ,允许嵌套.
- 嵌套语句:与选择结构嵌套.
- break语句:结束switch语句中的cases或者结束循环结构,适用于非结构化语句.
- continue语句:强制开启新一轮循环,没有break语句方便高效,适用于非结构化语句.
- 无条件转移语句:goto转向语句编号代表的循环,需要对循环结构编号,容易使程序结构混乱.
推荐阅读
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- C/C++|C/C++ basis 02
- Qt实战|Qt+OpenCV联合开发(二十一)--图像翻转与旋转
- Qt实战|Qt+OpenCV联合开发(十四)--图像感兴趣区域(ROI)的提取
- Qt实战|Qt+OpenCV联合开发(十三)--通道分离与合并
- opencv|Qt+OpenCV联合开发(十六)--图像几何形状绘制
- Qt实战|Qt+OpenCV联合开发(十七)--随机数与随机颜色
- SNAT的MASQUERADE地址选择与端口选择
- IPTABLES的连接跟踪与NAT分析
- IPVS分析