前言

前几天有个刚刚上大一的小朋友突然找到我,说自己选修了一门课程《C 语言程序设计》,明明已经很努力了,可就是怎么也学不会,需要我的帮助。我问需要哪方面的帮助,他犹豫了一下,说现在也不知道。

我很理解他,想起自己上大学那会儿,第一次上机调试打印 Hello World,对着 TC 2.0 那种经典的蓝色,搞了三四个小时才搞定,至今还记着走出机房下楼时的喜悦。

代码里的每个单词、每个字母都认识,可在编程的世界里连起来就是不知道啥意思,这种无力感相信困惑着很多人。

你可能听过一些老司机上手一门新的编程语言可能只需要几个小时,也许时间会更短。不用怀疑,这事儿不神奇,人也都是普通人,只是因为有方法。

每个人用的方法不一样,我只说说我自己实践过的,主要包含以下几个方面:

  1. 什么是代码
  2. 什么是写代码
  3. 怎么学代码
  4. 代码的组成
  5. 怎么写代码

仅供参考,大家有其他想法的,欢迎随时交流。

写代码还是很有意思的,祝大家玩的愉快。

什么是代码 ?

代码有一个别名,叫做“语言”。我们都知道人和人之间交流的重要工具就是语言,既然代码被称作语言,它也应该是一种交流工具才对。没错,代码就是人和计算机交流的工具。人和人之间交流使用的语言是汉语、英语、日语等;人和计算机之间使用的语言是 C/C++、Java、Python等。

不同的是,人是一种智慧的生物,会有自己的思考,你让一个人去吃饭,这个人可能自己改去喝水;计算机只是一台死板的机器,它绝对不会违背人的意志,只会机械地执行。与其说人和计算机是交流,不如说是人向计算机下达命令,计算机严格按顺序执行,最后把结果反馈给人。

命令就是代码 !

什么是写代码 ?

写代码就是下命令 !

既然是下命令,我们就需要搞清楚两件事情:

  1. 有哪些命令? 机器支持的命令是有限的,我们需要知道一共有哪些命令,每一条命令可以做什么事情。

  2. 下哪些命令? 机器要做哪些事情,第一步做什么、第二步做什么、...、最后做什么。

代码就是命令的合集 !

怎么学代码 ?

抓大放小 ! 先牢牢地抓住主干,再慢慢地搞定枝叶。

我们人类使用的语言实在是太复杂了,同样的一个意思可以使用很多种方式来表达。

貌似天仙、仙女下凡、花容月貌、如花似玉、花颜月貌、玉洁冰清、冰雪聪明、明艳动人、沉鱼落雁、闭月羞花、...,这些词语都是说人长得漂亮的,我们只需要知道 好看 就够了。

孔已己说过回字有四种写法,我们只需要知道 就够了。

主流的编程语言也已经演化发展很多年,细枝末节的东西特别的多,同样的一个事情可以使用不同的命令来表达。一开始的时候,不要陷入到过多的细节里(枝叶),掌握核心的东西(主干)最重要,可能一个事情一个命令就足够了。

相比于成百上千页的经典著作,你需要的是十几页的简明教程。代码不是文章,不需要词藻华丽,简单、直接、有效更重要

也不是说枝叶就不重要,只是说先从主干入手,理清脉络,然后再慢慢地向枝叶延展,这个事儿需要时间。

代码的组成

不管是哪种编程语言写出来的代码,剥离掉细节,基本的组成部分都是类似的,这些 组成 就是我们需要优先掌握的主干,我们就是使用这些主干来下命令的。

因为不同的编程语言要求的语法不一样,我们这里统一使用伪代码,大家理解意思即可。

变量

还记得上小学的时候学过的 x 和 y 么?

x = 1
y = 2

...

x = 11
y = 22

x 和 y 就是变量,它们可以存储一个值(1 或 2),而且它们的值可以随着计算过程发生变化(11 或 22)。

我们是在作业本或草稿纸上面写变量的,计算机则是在内存里存储变量的,每一个变量在内存里都有自己专属的空间存储对应的变量值。

变量是有类型的,变量的类型决定着计算机使用多少内存空间存储变量值,也决定着变量值的数值范围、精度或长度之类的。不同的编程语言支持的变量类型略有不同,即使是相同的类型,占用内存空间的大小可能也是不同的。

常见的变量类型:

  • 整数(int)
  • 小数(double)
  • 字符串(string)
  • 布尔(boolean)
int a = 1
double b = 2.0
string c = "abc"
boolean d = true

变量 a、b、c 和 d 分别被声明为整数类型、小数类型、字符串类型和布尔类型。变量的值可以发生变化,变量的类型是不允许变化的。

布尔类型是一种特殊的变量类型,它的值只有 true 和 false。

示例中的这些变量是使用变量类型符号(int/double/string/boolean)显式声明的,有些编程语言是不需要显式声明类型的,它会自动根据变量值推断出变量类型。

a = 1
b = 2.0
c = "abc"
d = true

你只需要记住三点:

  1. 变量是用来存储值的
  2. 变量是有类型的
  3. 变量的值是可以发生变化的

变量有什么用

变量可以用来存储各种各样的数据。比如我们要存储一个人的信息:身份证号、姓名、性别、年龄,就可以使用字符串类型的变量存储身份证号和姓名,使用整数类型的变量存储性别(0 表示男,1 表示女)和年龄。

常量

常量就是一种特殊的变量,常量的值不允许发生变化,仅此而已。

常量有什么用

常量可以用来存储那些不会发生变化的数据。比如我们要存储一个口号:为人民服务,就可以使用一个字符器类型的常量来存储。

数组

如果值的数目不多,我们可以像 变量 中描述的那样,逐个声明变量;如果值的数目有很多呢,我们也机械似的一个个的声明么?必须不用!

如果值有很多,这些值的类型又是一样的,就可以把它们打包存储到一个大块的内存空间里去。这个大块的内存空间也对应着一个变量,只不过这个变量存储的不是一个值,而是多个同类型的值。

我们把这种特殊的变量叫做 数组,根据存储值类型的不同,又可以细分为整数数组、小数数组或字符串数组。

int[] a = {1, 2, 3, 4, 5}

数组里存储着多个值,这些值是有编号的:第一个数、第二个数、...,我们可以使用编号读取数数组里特定位置的值,也可以使用编号往数组里的特定位置写入值。编号在编程语言里也称为下标,只不过它是从 0 开始的。

// 读取第一个数
a[0]

// 写入第二个数
a[1] = 22

数组有什么用

数组就是多个数据的集合,这些数据的类型是相同的。比如我们要存储很多人的信息,每一个人的信息包括身份证号、姓名、性别、年龄。我们可以分别创建四个数组:

  1. 用于存储身份证号的字符串数组
  2. 用于存储姓名的字符串数组
  3. 用于存储性别的整数数组
  4. 用户存储年龄的整数数组

这四个数组的大小是相同的。对于第一个人的信息:

他的身份证号存储到身份证号数组的第一个位置; 他的姓名存储到姓名数组的第一个位置; 他的性别存储到性别数组的第一个位置; 他的年龄存储到年龄数组的第一个位置;

第二个人的信息、第三个人的信息、...,以此类推。

运算符

我们已经知道,一个数据叫做变量,多个数据叫做数组。有了数据之后,如果想要对数据进行计算,还需要知道计算规则是什么,这个计算规则有个专用术语:运算符

数据 + 运算符 = 表达式

赋值运算符

x = 1

= 就是赋值运算符,表示把 1 赋值给变量 x。

算术运算符

z = x + y

+ 就是算术运算符,表示 x 加 y。常见的算术运算符:

  • 加(+)
  • 减(-)
  • 乘(*)
  • 除(/)
  • 取余(%)

比较运算符

z = x < y

< 就是比较运算符,表示 x 小于 y。常见的比较运算符:

  • 大于(>)
  • 大于或等于(>=)
  • 小于(<)
  • 小于或等于(<=)
  • 等于(\=\=)
  • 不等于(!=)

比较表达式的计算结果是布尔类型,即:true 或 false。

如果 x 小于 y,那么 z 为 true;否则,z 为 false。

逻辑运算符

e = a < b && c > d

&& 就是逻辑运算符,表示且。常用的逻辑运算符:

  • 与(&&,也称作且)
  • 或(||)
  • 非(!)

逻辑运算表达式的计算结果也是布尔类型。

e = a < b && c > d

如果 a < b 为 true,而且 c > d 为 true,那么 e 为 true;否则,e 为 false。

e = a < b || c > d

如果 a < b 为 true,或者 c > d 为 true,即两者其中之一为 true,那么 e 为 true;否则,e 为 false。

e = !(a < b)

如果 a < b 为 true,那么 e 为 false;否则,e 为 true。

运算符有什么用

假设有一群人,

people_genders[] = {0, 1, 1, 0, ..., 1}

使用数组 people_genders 存储这群人的性别,我们需要统计人群中男女各有多少人。

使用变量 man 表示性别为男的人数,使用变量 woman 表示性别为女的人数,统计开始之前两个变量均赋值为 0,需要用到 赋值运算符

man = 0
woman = 0

获取第一个人的性别,判断性别是否为男或女,需要用到 比较运算符

// true 表示性别为男
people_genders[0] == 0

// true 表示性别为女
people_genders[0] == 1

如果性别为男,则男的人数加一;如果性别为女,则女的人数加一,需要用到 算术运算符

man = man + 1
woman = woman + 1

依次获取其他人的性别,重复上述过程,直到最后一个人处理完成。

最后我们想知道男女的人数是否都大于10,需要用到 逻辑运算符

man > 10 && woman > 10

结构

整体上代码都是从上到下按 顺序 执行的,有两种特殊情况:分支循环

分支

if (表达式1) {
    // 代码1
    ...
} else if (表达式2) {
    // 代码2
    ...
} else {
    // 代码3
    ...
}

if /else 实现的代码称为分支代码块,这个代码块使用表达式拆分成若干个分支,从上到下依次判断表达式的值,哪个表达式的值为 true,就执行这个表达式对应的分支代码,其它分支代码都不会被执行。

如果表达式1为 true,那么执行代码1; 如果表达式2为 true,那么执行代码2; 如果都不是,那么执行代码3。

分支结构中的表达式可以是比较表达式或逻辑表达式。

if 只能有一个,else if 可以有零个或多个,else 可以有零个或一个。

分支有什么用

回忆一下前文性别统计的例子。

如果性别为男,则男的人数加一;如果性别为女,则女的人数加一。

就可以使用分支结构实现:

if (people_genders[0] == 0) {
    // 性别为男
    man = man + 1
} else {
    // 性别为女
    woman = woman + 1
}

循环

for (表达式1; 表达式2; 表达式3) {
    // 代码
}

for 实现的代码称为循环代码块,这个代码块根据三个表达式的结果多次执行代码。

一般情况下,循环用于遍历数组:

表达式1:初始化下标,仅循环开始时执行一次; 表达式2:根据下标和数组长度判断是否继续循环,可以是比较表达式或逻辑表达式,每次运行代码之前执行一次,如果表达式的值为 true,则继续运行代码;否则,结束循环; 表达式3:下标增一,每次运行代码之后会执行一次;

int[] arr = {0, 1, 2, ..., 9}

for(int index = 0; index < arr.len; index++) {
    arr[index]
}

index 是遍历数组 arr 的下标变量,循环开始时:

index = 0

第一次运行代码之前,执行表达式2:

index < arr.len

0 < 10 为 true,运行代码;

第一次运行代码之后,执行表达式3:

index++

index 的值为 1;

第二次运行代码之前,执行表达式2:

...

第十一次运行代码之前,执行表达式2:

index < arr.len

此时 index 的值为 10,10 < 10 为 false,结束循环。

arr.length 表示数组的长度。

可以使用 break 或 continue 结束循环或跳过循环。

数组有什么用

回忆一下前文性别统计的例子。

依次获取其他人的性别,重复上述过程,直到最后一个人处理完成。

就可以使用循环结构实现:

for (int index = 0; index < people_genders.len; index++) {
    if (people_genders[index] == 0) {
        // 性别为男
        man = man + 1
    } else {
        // 性别为女
        woman = woman + 1
    }
}

函数

结果类型 函数名称(参数类型1 参数名1, ..., 参数类型N 参数名 N){
    // 函数体
}

函数是一个特殊的代码块,它有三部分组成:

Input:输入参数,可以有零个或多个参数; Process:函数体,也就是调用函数时会执行的代码; Output:输出结果,可以有零个或一个;

简称:IPO

int add(int a, int b) {
    return a + b
}

调用函数:

int a = 1
int b = 2

int c = add(a, b)

如果一个代码的特别长,我们可以把这个代码按照逻辑拆分成若干片段,每个版本实现成一个函数,用若干个函数调用替换大片代码,代码结构会清晰很多。

如果一个代码片段在代码中多次出现,我们可以把这个代码片段实现成一个函数,把代码片段替换成函数调用,实现代码复用。

函数有什么用

回忆一下前文性别统计的例子。

我们可以把基于性别数组统计性别人数的代码片段实现成一个函数:

(int, int) count(int[] people_genders) {
    int man = 0
    int woman = 0

    for (int index = 0; index < people_genders.len; index++) {
        if (people_genders[index] == 0) {
            // 性别为男
            man = man + 1
        } else {
            // 性别为女
            woman = woman + 1
        }
    }

    return (man, woman)
}

调用函数:

int[] people_genders = {0, 1, 1, 0, ..., 1} 

int man, woman = count(people_genders)

如果有多个人群需要统计性别,使用函数的方式可以使代码结构更简单、逻辑更清晰。

其它

掌握了一门语言的变量、常量、数组、运算符、结构和函数,可以说基本上就掌握了一门语言的核心。但是,这些也仅仅是一门语言的基础,如果你想应用到实际场景中解决具体问题,还需要扩展到线程、IO、网络通信之类的。

怎么写代码?

编程语言只是解决问题工具,人是关键!

写代码之前,你需要先在脑子里把解决问题的流程思考清楚,然后把这个流程转变成伪代码,确保这个流程可以跑的通,最后才是写具体的代码。

还是那个统计性别人数的例子,最好是先把统计的过程梳理清楚:第一步做什么、第二步做什么、...,在纸上把关键节点和处理流程(分支或循环)画一画、写一写,然后再动手写代码。

结语

写代码还是很有意思的,祝大家玩的愉快。

results matching ""

    No results matching ""