三天学会c语言编程,三天学会C语言编程|下篇

本文是《三天学会C语言编程》的下篇,承接上一篇《三天学会C语言编程|上篇》。本文重点介绍C语言的数据类型、表达式、变量和函数等内容。

数据类型

C语言中有多种数据类型,这些数据的类型与我们日常生活中的数据的类型有些类似。比如整型数和浮点型数(小数),还有一些我们平时接触不到的数据类型,如字符串类型(上文中的hello world!就是一个字符串类型的数据)。如下表是C语言支持的数据类型(部分),这里先不用过多理解,只需要知道有这些类型就行,后面会详细介绍。通过这个表可以看出不同类型的数据占用的内存空间大小是不同的。

2f714e11e72e?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图1 C语言数据类型列表

变量

变量其实是内存的一个区域,用于存储具体的数据,需要说明的是变量是有名称的。变量的名称就好像邮箱的编号一样,这样我们在编程的时候就可以通过这个名字方便的访问(读或者写)变量。

在C语言中变量的名称可以是英文字符、下划线和数字,但只能以英文字符和下划线开头,不能以数字开头。另外,C语言中变量名称是区分大小写的,也就是var_name和var_Name是两个不同的变量。

我们知道在C语言中数据是有不同的类型的,同样变量也有不同的类型。不同类型的变量用于存储不同类型的数据,而且不同类型变量占用的空间大小是不同的。那么如何定义一个变量呢?很简单,其基本格式就是类型+变量名称,如下定义了一个整形的变量:

int var_name;

其它类型的变量与此类似,只是变量的类型不同。至于名称则遵循上文所描述的规范。

表达式

我们知道程序最主要的功能就是进行计算的,因此在程序中会有一些表达式进行计算。表达的形式与日常数学中的表达式基本一致,运算的优先级也类似。如下是一个简单的表达式:

3 + 5 * 6

这个表达式进行简单的数据计算,但该表达式在实际编程时并不没有太大意义,因为计算出的值将被直接丢弃。通常我们需要将表达式计算的值放到一个变量这,这样我们后面才能使用该表达式计算的结果。下面是一个具体的示例:

#include

int main(void)

{

int a; //声明整型变量

long b; // 声明长整型变量

short c; // 声明短整型变量

char d; // 声明字符类型的变量

float e = 1.2; //声明浮点型(小数)变量,在声明的时候可以直接初始化

int f = 0;

unsigined int = 3; // 声明无符号整型变量,无符号整形只能是非负整数

b = 10; //给变量赋值,赋值就是改变变量的内容,让其等于某个值

c = 11; // 注意赋值的方向,变量在等号左边(又称“左值”),数据在等号右面

a = a + 10; // 进行基本的加法运算

c = a + b; /* 可以进行不同类型的变量之间的运算,但可能会丢失数据。因为每种类型变量存储的数值大小是有限的,超过就会溢出。本例中变量c是短整型,范围是-32,768 到 32,767。而变量b是长整形,范围是从-2,147,483,648 到 2,147,483,647。因此,如果计算结果超过了c的范围,将会出现溢出,因此在计算是需要注意。*/

e = a + b * c; // 这里的*是星号,也就是键盘8上面的字符,代表乘法

a = (a + e) * c; //可以使用括弧提升运算的优先级,本例中

a = a /c ; //除法运算

a = a % c; //取模运算

a --; //自减运算,也就是自己减1

a ++; //自加运算

/*除了进行基本的算术运算外,还可以进行位运算。所谓位运算就是逐位运算。*/

a = a & b; //按位“与”运算

a = a | b; //或

a = a ^ b; //异或

a = ~a; //非

/*关系运算,也就是判断两个或者多个变量的关系。*/

a == b; //判断两者是否相等,相等返回真,否则返回假

a >= b;

a > b;

a <=b;

a != b; //判断两者是否相等,相等返回假,否则返回真

a && b; //注意是2个&,两者都为真是结果为真。可以多余2个进行运算

a || b;

}

函数

我们在最一开始的时候已经使用了函数,但还没有对函数进行任何介绍。下面本文将介绍一下什么是函数,为什么要有函数以及函数怎么使用。

函数是对实现某个功能的代码的封装。有了函数之后,具体的功能我们调用该函数就可以完成,而不同将代码黏贴过来,增加了便利性。

#include

/*下面是函数的定义*/

int add(int a, int b) /*这一行成为函数头,其中int是函数的返回值类型,add是函数名称,int a和int b是函数的参数(形参)。

这里返回值和参数可以是任何类型。*/

{ /*函数头后面要紧跟着{,可以与函数头在同一行,或者另起一行,这个代表函数体的开始*/

int c = 0;

c = a + b; //这里是函数的具体实现,根其它地方没有任何差异

return c; //函数的返回值,类型要与在函数头中定义的一直,否则有截断的风险

}/*函数体的结束*/

int main(void)

{

int a = 0;

a = add(1, 2); /*函数的调用,这里相当于使用add函数的功能,进行加法运算。*/

printf("result: %d

", a);

}

函数可以与入口函数在相同的文件中,也可以在一个单独的文件中。函数的定义通常在.c文件中,而在头文件(.h文件)中添加声明。这样我们只需要包含头文件就可以使用该函数了。

控制语句

通过上面的知识只能写从上往下依次执行的程序。显然这个不能满足实际开发的需求,比如有的时候我们要根据不同的情况执行不同的代码,或者需要重复执行相同的代码等场景。C语言中有多中控制语句,实现对程序不同流程的控制,下面我们以例子的形式进行介绍。

#include < stdio.h >

/*这个函数实现成绩的转换,如果大于等于90分则打印“优秀”, 如果在80到90之间,则打印“良好”,如果在70-80之间则打印“中等”, 如果在60到70之间则打印“及格”,否则打印“不及格”。*/

int print_score(unsigned int score) {

/* if 是C语言的判断语句,用于判断是否执行后面的代码。

* 在if关键字后是具体的判断条件表达式,表达式需要

* 用括弧包括。*/

if (score > 100) {

/* 如果条件判断后执行的代码是多行,则需要有{作为执行体的头。 */

return - 1;

/*由于成绩不会大于100,因此这里返回-1,表示错误*/

}

/* 如果条件判断后执行的代码是多行,则需要有}作为执行体的尾。

* 如果只有一行代码则不需要{和}两个字符*/

/* 下面进行分类打印 */

if (score >= 90) {

/* 语句块标识符{不一定要另起一行,可以与if在同一行。*/

printf("优秀

");

} else if (score >= 80) {

/* 语句 else if 表示另外一种情况。 如果上面符合条件,则不会执行本行。*/

printf("良好

");

} else if (score >= 70) {

printf("中等

");

} else if (socore >= 60) {

printf("中等

");

} else {

/* else后面可以没有if语句,这样该语句不进行任何判断。如果前面都不满足条件,则到最后执行该语句。*/

printf("不及格

");

}

return 0; //返回0表示执行成功

}

/*上面实现了程序的分支控制,也就是不同的条件执行不同的代码。还有一种情况是需要不断执行某一项重复的计算。这时就需要用到循环语句。

下面这个函数执行连续整数的累加和,也就是从begin按1递增,一直到end的累加和。比如从5开始一直到9,也就是5 + 6 + 7 + 8 + 9。下面看看如何用循环语句实现这个功能。*/

int sum(int begin, int end) {

int index = 0;

int result = 0;

/* 循环的关键字是for, 后面()里面的是控制语句。括弧是必须的。括弧内用分号“;”将控制语句分为3部分。第一部分进行初始化,只执行一次;第二部分进行条件判断,每次执行,如果符合条件则执行循环体({}内,这个在单行的情况下可以省略)内的内容,否则跳出循环;最后一个则执行一些额外的运算。上面三部分任何一个都可以为空,三者也可同时为空,但分号不能省略。 */

for (index = begin; index <= end; index++) {

/* 这个是开始字符,同判断语句,这里不做过多解释*/

result = result + index;

}

return result;

}

/* C语言中还有另外一个关键字实现循环控制,那就是while语句。*/

int sum2(int begin, int end) {

int index = 0;

int result = 0;

/*想必大家已经找到规律了,while循环也是关键字后面是括弧,然后是循环体。 while语句在括弧中只有一个条件判断,如果满足条件则执行循环体,如果不满足则从循环退出。*/

index = begin;

while (index <= end) {

result = result + begin;

index++;

}

}

int main(void) {

int score = 80;

print_score(score);

sum(1, 5);

sum2(1, 5);

}

本文作为入门级教程并没有介绍全部的循环语句,但作为入门已经够用了。后续再详细介绍更多的用法。

指针

指针给了我们更大的权限,可以让我们直接操作系统的内存。但是指针也是C语言中最为复杂的部分,也是饱受诟病的部分。只是由于指针的存在使得C语言开发的软件出现问题的复杂度更大,也更难解决。凡事有利有弊,废话少说,我们看看什么是指针。

简单的理解,指针其实就是内存的地址。由于我们要访问内存,内存肯定要有个编号,这样我们才知道访问哪里的内存。有人可能会说,你不是在前面说通过变量名称进行访问吗?是的,但是变量名称只是在我们编程层面使用内存的方式,真正到操作系统层面都是通过内存的地址进行访问的。

了解了指针的概念之后,那我们现在谈一下什么是指针变量。我们知道变量是存储数据的,从名称上可以推测出来指针变量就是存储指针的。没错,指针变量就是存储指针的变量,也就是存储内存地址的变量。

2f714e11e72e?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图2 变量与指针变量示意图

为了便于说明什么是指针及指针变量,我们通过图1进行。假设我们有一个整形变量age,其中的值是0x12345,数据存储在0x1000(这里是为了便于说明,实际位置值的格式大概类似这样,0x7ffc6a95fb14)的位置。

现在我们想用另外一个变量(比如名称为age_tmp)将该变量的地址保存起来,而且可以通过age_tmp访问age变量中的内容,那该怎么办?没错,就是定义一个指针变量。如图1所示,age_tmp就是这个指针变量,它在0x0800的位置,其内部存储的值是age的地址。好了,废了半天话,那具体怎么编写代码呢?下面我们通过一个例子说明。

#include < stdio.h > int main(void) {

int age = 0x12345;

int * age_tmp;

/* 这里是定义一个指针类型的变量,仔细看一下在变量名称前有个星号(*),这个代表变量是指针变量。这里定义的是整形指针变量,我们可以定义任何类型的指针变量。通常,某种类型的指针变量只能存储该类型变量的指针(地址)。 */

age_tmp = &age;

/*这里是将变量age的地址赋值给指针变量age_tmp,注意看age前面有个与符号(&),这个是取变量地址的意思。*/

printf("age value: 0x%x

", age);

/*打印变量的值*/

printf("age address: %p

", &age);

/*打印变量age的地址*/

printf("age_tmp value: %p

", age_tmp);

/* 打印指针变量的值*/

printf("age_tmp address: %p

", &age_tmp);

/* 打印指针变量的地址*/

}

如下是程序执行后的结果,可以看出值的关系与图1是完全一致的。

age value: 0x12345

age address: 0x7ffd64adf68c

age_tmp value: 0x7ffd64adf68c

age_tmp address: 0x7ffd64adf690

好了,关于指针的相关内容就先介绍到这里,关于指针足够专门写一本书了。

复合数据类型

结构体

C语言最为厉害的地方在于可以支持复合数据类型,所谓复合数据类型就是可以将集中数据类型进行组合封装,形成另外一个新的数据类型。实现这种强大功能的名称叫做结构体,结构体通过struct关键字实现,并用{}界定结构体的内容。下面我们看一个具体的例子。

#include < stdio.h >

/*下面是结构体的定义,需要关键字struct,后果是结构体的名字。*/

struct new_type {

/*结构体具体内容有左大括弧开始。*/

int number;

/*成员变量的第一根我们平时定义变量一样 */

long age;

float score;

};

/*结构体的具体内容以右大括弧结束,注意后面还有一个分号。*/

int main(void) {

struct new_type var_name;

/* 如何使用新的变量类型,定义方式与普通变量一样,只是需要有struct关键字。 */

var_name.number = 12;

/* 对新类型变量成员赋值的方法,中间用点符号(.)连接变量名称和成员名称。 */

var_name.age = 15;

var_name.score = 96.5;

printf("score: %f

", var_name.score);

}

结构体同样也可以有指针类型,本文暂时不做介绍。这部分内容我们后续专门介绍。

数组

从名称上也可以看出来,数组是指一组数。数组是用来存储一系列数据,而且是一系列相同类型的数据。

2f714e11e72e?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图3 数组变量示意图

如图2所示,我们假设一个整型的数组变量,名称为new_array,由图可以看出其数据在内存总会依次存放。这样有个有点,我们知道该变量的首地址,就能知道后续其它成员的地址,因此也就可以直接访问。下面我们通过实例解释一下。

#include < stdio.h > int main(void) {

int new_array[4];

/* 数组的定义通过在变量名称后面根一对中括号确定,中括号里面的整数是该数组的大小,也即存储几个成员。*/

printf("first member: %d

", new_array[0]);

/* 数组的访问也是通过在变量名称后面跟一个中括弧,其里面的整数表示要访问哪一个成员,需要注意的是数组的成员是从0开始的,表示第一个成员。另外,这里没有对成员进行初始化就进行访问,因此内容是随机的。 */

new_array[0] = 1;

/*成员初始化的方法*/

new_array[1] = 2;

printf("first member: %d

", new_array[0]);

/* 初始化后再次访问 */

}

下面是运行后的结果:

first member: 4195840

first member: 2

数组可以是任何类型的上面只是数组的基本用法。数组可以一开始就初始化,也可以结合指针使用。

总结

到今天本文就算结束了,学完这些基础知识只能算刚抬起脚迈进门槛,另外一只脚还在外面呢。后面需要学习的内容还多着呢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值