【C language part 2】变数&资料型态、输入输出、运算子&运算式

撰写第一支程序!!

#include <stdio.h>
#include <stdlib.h>

void main() {
	
    /* some comments */

	printf("Hello World!");
	
	system("PAUSE");
	return 0;
}

我们一步一步拆开来看看

First Block

#include <stdio.h>
#include <stdlib.h>

这是在 C program 编译之前要处理的内容,我们称为预处理命令(preprocessing command)。预处理命令还有很多,它们也都以 # 开头,并且不用分号结尾
stdio 是 standard input output 的缩写,也就是有关输入输出的标头档(head file)
stdlib 也就是 standard library,包含了 C 与 C++ 里最常用的一些函数。

Second Block

void main()

main function,从这里开始执行 C program。

Third Block

/* some comments */

注解,C program 不会编译执行里面的任何内容。单行注解的话使用双斜线 //

Fourth Block

printf("Hello World!");

printf 指令可以输出内容显示在萤幕上。

Fifth Block

system(“PAUSE”);
return 0;

程序暂停,按任意键继续。

Steps to Write C Programs and Get the Output

  • 以下四个步骤任何 C program 都要遵循的步骤,对所有专案都通用。
  • 无论是只有数行的小程序或是包含好几个档案的大专案无一例外。
  1. Create
  2. Compile
  3. Execute or Run
  4. Get the Output

资料型态 Data Type

  • 资料型态(data type)是在执行程序时用来定义变数(variable)的。
  • 变数、常数(constant)和阵列(array)在记忆体所占的空间大小是由资料型态所决定的。
  • C 的基本资料型态主要区分为:
Types Data Types
Basic data types int, char, float, double
Enumeration data type enum
Derived data type pointer, array, structure, union
Void data type void

列举 (enumenumeration) 是另一种复合型别,主要是用在宣告仅有少数值的型别,像是一星期内的日期 (day of week) 或是一年内的月份等。

Basic data types – Integer

  • 整数资料型态(integer data type)允许变数来储存数值(numeric values)。
  • 关键字 int 是用来宣告整数资料型态。
  • 记忆体所占的储存空间可以是 2、4 或 8 byte。配置的记忆体长度在不同编译器上各不相同,可容纳的大小各不相同。

Basic data types – Floating Point

  • 浮点数(floating point)是用来将实数数位化表示的一种表示法,简单来讲就是可以用来宣告含小数点的数字。我们现在使用的是由 IEEE 制定的浮点数表示标准。
  • 资料型态分为两种:
    1. float
    2. double
  • 而两者的差异在於「精确度」。
Keyword Byte Format String Comment
float 4 bytes %f 浮点数
double 8 bytes %lf%l 双精度浮点数

Basic data types – Character

  • 字元(character)资料型态只允许变数储存一个字元。
  • 所占用的记忆体空间为 1 byte。
  • 用来储存英文字母及 ASCII 码。(字元可以跟整数型态互相转换,也就是 ASCII 码)
  • 关键字 %c 用来宣告字元资料型态。

ASCII Code

变数 Variable

Variable is a named location in a memory where a program can manipulate the data. This location is used to hold the value of the variable.

  • 在程序设计的过程中,我们会需要纪录某些资料,我们需要把这些资料纪录在记忆体的某个位址中,并且给它一个名称,这就是所谓的变数。
  • 变数的值(value)可以在程序中发生变化。
  • 变数可被宣告成任何 data type。

Rules for naming C variable

  • 变数名称必须是由英文字母或是底线()开头。
  • 英文字母大小写有差。
  • 可以由数字或字母组成。
  • 除了底线以外,不得使用任何特殊符号
  • 不能跟 C语言的保留字(reserved word)相同。
  • 举例合格的变数名称:
    1. sum
    2. height
    3. value

保留字 Reserved word

变数宣告与初始化 Declaring and initializing C variables

  • 在 C 语言里变数需要在使用前进行宣告。
  • 而变数初始化(variable initialization)是指设定变数的值(value)。

变数宣告需要在变数「初次」使用前完成,不可在其被使用後才进行宣告。
至於宣告的位置并没有特别规定,可以在任何地方进行宣告。
不过还是习惯於最一开始的时候先进行宣告。

常数 Constant

  • C 常数观念跟变数一样,唯一的差别是:一旦定义其值,程序将无法对其进行修改。简单来说,常数就是一个「唯读」的变数。
  • 代数(algebra)里所谓的常数与程序语言里的常数概念上有些不同:
    • 代数中的常数,例如:在 $?(?)=?^3+?$ 中的 $?$ 表示在自变数与因变数改变时维持固定的数字,它的值不是问题观察的重点,但可以是某些合理的数字中的一个。
    • 程序语言中的常数在观念上和程序中的变数是一致的,也就是说,常数是一个 CPU 纪录数值资料的地方,只是 CPU 在整个程序执行过程中,只会去读取该资料,而不会修改它。
  • 经宣告并给定初始值後,就不再(且不允许)变更其数值的资料。

C 语言的变数四要件

  • C 语言变数包含四个要件:
    1. 资料型态 Data type
    2. 识别字 Identifier
      • 电脑程序中,编译器或是直译器会透过识别字来了解程序码的意义,有些识别字是内建的,像是保留字、内建变数、内建函式、标准函式库的韩式等等。有些识别字则是程序设计者宣告後创造出来的,像是变数。
    3. 值 value
    4. 可视度 Scope
      • Scope 较白话的讲法应该可以解释为「变数范围」,涉及许多层次,由小到大可以分为:区块可见(block scope)、函式可见(function scope)、区域可见(local scope)、全域可见(global scope)。详细内容之後还会再提到。

printf & scanf

  • 输入输出函式(printf, scanf)是 C语言非常重要的函式,也是 C语言必学的两个函式。在 C语言的程序中,几乎每一个程序都会使用到这两个函式,尤其是输出函式。
  • 如果程序中需要使用 printf 或者是 scanf,那麽在撰写时就需要引用标头档(head file)stdio.h。stdio 为 standard input output 的缩写,而这两个函式就包含在这个标头档里。
  • 学习 C 的过程中,通常是从主控台(也就是文字模式)开始,为了与程序互动,在主控台下输出程序结果,或是从主控台取得使用者的输入资料是基本需求。其中 printf 的功能很强大,用法灵活,比较难掌握;而 scanf 用法相对比较固定。

printf

  • printf,print format 的缩写。

Syntax:

# include <stdio.h>
int printf (const char *format, ...);

标准语法如上。
以下举几个例子来示范 printf 的使用方法。

printf("字符串\n");

# include <stdio.h>
int main(void)
{
    printf("Hello World!\n");
    return 0;
}
  • 其中 \n 表示换行的意思,是一个跳脱字元。
  • n 为 new line 的缩写。
  • 除此之外要注意的是,printf 里必须使用双引号("),双引号内的字幅串可以是英文,也可以是中文。

printf("输出控制符",输出参数);

# include <stdio.h>
int main(void)
{
    int i = 10;
    printf("%d\n", i);  
    return 0;
}
  • 这个程序的意思就是让变数 i 以十进制的方式输出。
  • 不过 i 本身就是十进制,又为甚麽还要将 i 以十进制输出?因为程序码中,虽然写的是 i=10,但是在记忆体中并不是将「10」这个十进制的值存进去,而是以二进制的方式存进去。所以我们在输出的时候就必须要有「输出控制符」(或称格式指定字,format specifier)来告诉系统应该怎麽解读这个二进制的数值。

跳脱字元 Escape Character

格式指定字 Format Specifier

scanf

  • scanf,scan format 的缩写。
  • scanfprintf 的用法几乎完全一样。但是需要注意以下两点:
    1. scanf 里面绝对不要包含 \n
    2. scanf 後面不是直接放变数,前面需要再加上 & ,不过字元或阵列不需要加上& (至於为甚麽,等之後上到指标的时候会再解释)。

以下也示范几个例子说明 scanf 的使用方法。

#include <stdio.h> 
int main() { 
	int a = 0, b = 0, c = 0, d = 0; 
	scanf("%d", &a); 
	scanf("%d", &b);
	printf("a+b = %d\n", a+b); 

	scanf("%d %d", &c, &d); 
	printf("c*d = %d", c*d); 
	
	return 0; 
}

从键盘上输入 12,按下 Enter 键之後,scanf() 就会读取输入数据并给定给变数 a,本次输入结束。接着执行下一个 scanf(),再从键盘输入 60,按下 Enter 键就会将 60 给定给变数 b
後面的 scanf() 有两个用空格分开的 %d,後面跟着两个变数 cd,这个代表我们要一次输入两个整数,并且会分别给定给 cd。注意,%d %d 之间是有空格的,所以我们在输入数据时也要有空格。对於 scanf(),输入数据的格式要和控制字符串的格式一样。

scanf(“%d %d”, &a, &b); // 获取使用者输入的两个整数,分别给定变数a和b
printf(“%d %d”, a, b); // 将变数a和b的值在萤幕上输出

scanf 和 printf 非常相似,只是功能相反。

两者都有格式控制字符串,都有变数,不同的是 scanf 的变数前需要加一个 & 符号。
&称为取址符号,也就是可以获得变数在记忆体的位址。(详细内容会在指标单元详细介绍)

#include <stdio.h>
int main() {
	int a, b, c; 
	scanf("%d %d", &a, &b); 
	printf("a+b=%d\n", a+b); 

	scanf("%d %d", &a, &b); 
	printf("a+b=%d\n", a+b); 

	scanf("%d, %d, %d", &a, &b, &c); 
	printf("a+b+c=%d\n", a+b+c);

	scanf("%d is bigger than %d", &a, &b); 
	printf("a-b=%d\n", a-b); 

	return 0; 
}

  1. 第一个scanf()格式控制符为”%d %d”,中间只有一个空格,但是输入时,多输入一个空格。
  2. 第二个scanf()格式控制符为”%d %d”,中间有两个空格,输入却只输入一个。不过就算如此,print 出来的格式是正确的。这代表scanf()对输入数据之间的空格处理比较宽松,并没有严格要求空格的对应数量,只要有空格就可以了。
  3. 第三个scanf()的控制符”%d, %d, %d”,中间用逗号分隔,所以输入的整数也要用逗号分隔。
  4. 第四个scanf()要求两整数之间以is bigger than分隔。

使用者每次按下 Enter 键,程序就会认为完成了一次输入操作,scanf() 开始读取使用者的输入内容,并且根据格式控制符中提取有效的数据,只要使用者输入的内容和格式控制符匹配,就能够正确提取。


scanf 连续输入

我们将前两个程序码改写看看!

  • 一开始我们每输入一个数值,就按一次 Enter 键,而这次我们一次输入四个数值(中间以空格分隔)再按下 Enter,可以发现 scanf 都能正确读取。
  • 到这边,我们可以合理推断第一个 scanf() 读取完後并没有抛弃多余的值,而是将它们保存在某个地方,下次接着使用。
  • 而如果我们多输入一个数字,依样可以正确读取,只是最後一个数值没有使用而已。
  • 那如果我们少输入一个数字呢?
  • 输入三个整数後,前两个 scanf() 把前面两个整数给读进去了,此时剩下一个整数 60。而第三个 scanf() 要求要输入两个整数,一个单独的整数 60 并不能满足其要求,所以我们还是必须输入数值凑足两个整数以後,第三个 scanf() 才能正确读取。

所以,从基本上我们可以发现从键盘输入进去的数值并没有直接交给 scanf(),而是放入一个「缓冲区」,直到我们按下 Enter,scanf() 才会到缓冲区去读取数值。如果缓冲区的数值符合 scanf() 的要求,那麽就可以读取结束;如果不符合要求,那麽就继续等待用户输入,或者乾脆读取失败。

运算子 & 运算式 Operators & Expressions

  • 在C语言中,用来执行逻辑和数学运算的符号我们称为 C的运算子(C operator)。
  • 这些 operators 将各个 constants、variables 和 functions 组合起来,我们称为运算式(C expression)。

以此算式为例:

C operators

Types of Operators Description
Arithmetic operators 用於执行数学计算,例如:加减乘除和取余数。
Assignment operators 用在为变数分配值(value)。
Relational operators 用来比较两个变数的值。
Logical operators 对给定的变数执行逻辑运算。
Bit wise operators 对於给定的两个变数执行 bit operations。
Conditional (ternary) operators 如果条件为 true,则条件运算子会回传一个值;如果是 false,则回传另一个。
Increment / decrement operators 用於将变数的值增加或减少一。
Special operators &、*、sizeof() 和 ternary operators。

算数运算子 Arithmetic operators

  • 也就是一般数学四则运算会用到的运算子,再加上 ﹪、递增运算子、递减运算子。

  • ++ 递增运算子与 -- 递减运算子

  • 复合指定运算:指的是同时执行『算术运算子或位元运算子』以及『指定运算子』两件工作。

  • 比较关系运算子

  • 逻辑运算子 Logical Operator

运算子的优先顺序

  • 算术运算子 → 比较运算子 → 逻辑运算子
    • 先乘除,後加减;同一列中的运算,其优先顺序相同时,是由左至右运算。
    • 常见运算子的优先顺序如下:
顺序 运算子
1 () 小括号
2 + 正数、- 负数
3 */%
4 +-
5 <<=>>=
6 =!=
7 &&
8 \|\|
9 = assign、*=/=%=+=-=

<<:  06 - Uptime - 掌握系统的生命徵象 (4/4) - 使用合成监控 (Synthetics Monitor) 从使用者情境验证服务的运作状态

>>:  Day 09 回覆emoji讯息

用 Line LIFF APP 实现信箱验证绑定功能(1) - 取得 user email

先前提过,手动发身份认证码给使用者,再让使用手动输入验证码的流程太不友善,今天就开始着手优化这个步骤...

企业资料通讯 第一周整理

网路是甚麽? 非常多的主机与设备连接起来,交换讯号,媒介可能是光纤、铜线、波(无线),设备间沟通的标...

Day02:新手网页全端工程师的必备知识

一、前言   在大家入行当网页工程师前,一定都会做很多功课,了解前後端工程师技能树与後期发展性等等,...

[ASP.Net MVC] 取得 Request 常用资讯 (IP, 作业系统, 浏览器, 呼叫网址)

在建置网页的时候,有时候会需要知道来源端它的环境是什麽,可能是需要记录来源的 IP,或是依照来源的作...

【Day 17】深度学习(Deep Learning)--- Tip(二)--- ReLU

Vanishing Gradient Problem 昨天我们提到当你的Network很深的时候,设...