# 课程资源

首先环境升级为 IDE

# 程序编译的四步

标题的编译是一个宽泛的概念

  1. preprocessing 预处理,将头文件中的相关函数的 prototype 复制过来。
  2. compiling 编译,变成汇编代码。
  3. assembling 组装,不同的汇编文件变成各自的二进制。
  4. linking 合并,例如 将 hello.c cs50.c printf.c (里面均为二进制)合并为一个二进制可执行文件,如 a.out hello

And in fact, one of the greatest skills you can acquire from programming class is not only how to write code, but how to debug code,most likely your own.

# 关于引号的使用及字节空间

  • 单引号:Single quotes in C are necessary for chars.(字符)
  • 双引号:对于 string 字符串,用双引号。 string s = "HI!" ,三个字符,使用双引号。

字符串的大小是不确定的,我们如何知道它的结尾在哪里呢?
变量的名称足以让我们知道变量从哪里开始,而字符串以 \0 (空字符)结尾,所以 HI! 需要 4 bytes 存储

string s

每个方格以 8 bits(位)二进制表示, \0 用 00000000 表示

Single characters or chars 只有一个字节。
bool / char —> 1 byte
int / float —> 4 bytes
long / double —> 8 bytes
string —> ? bytes

  • Ascii 和 Unicode 是从字符到数字的 mapping(映射)。

例子:如何知道我输入了什么?

  1. 根据空字符确定
    复现1
  2. 根据字符串长度确定
    复现2

例子:大写变换

变换

将 strlen 写在 for 里面,每次循环都要运行(每次都要问这一位到 \0 了吗),于是在之前就定义 int n = strlen(s); 或者写在 for 的头部,和 int i = 0 一起定义(之间仅是逗号,逗号表示 and)。

满足条件的一些写法: and ---> && or ---> ||

# 加深对数据类型的理解

char casting to int
#include <stdio.h>
int main(void)
{
    char c1 = 'H';
    char c2 = 'I';
    char c3 = '!';
    printf("%i %i %i", (int) c1, (int) c2, (int) c3);
}
// 将会输出
~/ $ ./tt
72 73 33

同时,clang 足够聪明,(int) c1 中不写 int 也可以,由于 % i,也会 implicitly casting(隐形投放)。

int casting to char
#include <stdio.h>
int main(void)
{
    int i1 = 72;
    int i2 = 73;
    int i3 = 33;
    printf("%c %c %c\n", i1, i2, i3);
}

# Array 数组

An array is a list of values that can be all the same type in a variable of the same name.

int scores[3]; : 给我足够的内存来容纳三个整数,代表一个变量 scores 中三个值足够的空间,以一个变量为幌子,存储多个值。
scores[0] = 72 : 让第一个位置存 72
如果硬要编码一些值,并且确保你不会意外改变它,将其设为全局常量 const int N = 3 ,往往大写。

在计算学生分数平均值的例子中:

  1. 问清有多少个分数 int n = get_int("Number of scores: ");
  2. 定义一个名为 scores 的数组,大小为 n。
main function
#include <stdio.h>
#include <cs50.h>
int main(void)
{
    int scores[n];
    for (int i = 0; i < n; i++)
    {
        scores[i] = get_int("Score %i: ", i + 1);
    }
    printf("Average: %f\n", average(n, scores));
}
average function
// 首先需要知道两件事:数组的长度、数组本身
float average(int length, array[])
// 并不知道 array 有多大所以 [] 留空,编译器会解决这个问题
{
    int sum = 0; // 因为从零开始加
    for (int i = 0; i < length; i++)
    {
        sum += array[i];
        // 因为数组总是从 [0] 开始计数,到 length 之前停止即可
    }
return (float) sum / (float) length;
    // int / int ---> int
}

The return value of a function is what it hands back to whoever is using it.

float 是 average 函数返回的类型,所以 return 稍作处理。

对于 main function 太多的小数对用户不友好,所以在 printf 中写成这样 ("...%.1f", average(n, scores))

补充:

  • %9.2f 的含义是输出场宽为 9 的浮点数,其中小数位为 2,整数位为 6,小数点占一位。
  • 若结果为 99.45, %.1f 处理后,会 round up(四舍五入)为 99.5。

:若将 int devised float or other type of variable 得到什么呢?
:得到更强大的类型
string 字符串与 array 数组相同吗?
:目前来看 string just an array of characters. Because being able to have mutiple characters is certainly way more useful than having to spell things out one variable at a time with one char at a time.

# 数组和字符串的关系

...
string names[4]; // 定义一个数组
name[0] = "EMMA";
name[1] = "TONY";
name[2] = "JAMES";
name[3] = "BLACK";
printf("%s\n", name[0]);
printf("&c&c&c&c\n, name[0][0], name[0][1], name[0][2], name[0][3]");
...

输出均为 EMMA,而 name[0][4] 将会输出 0。

# 函数输入输出的再次理解

这恰巧解决了我在昨天最后的问题。

—> int main(int argc, string argv[]);
main 函数有两个输入参数,一个是称为 argc (argument count) 的整型变量,一个是存储了字符串的称为 argv (argument vector) 的数组。
就像之前的平均函数 (average function) took in the length of an array and the actual scores in side of it.

int main(int argc, string argv[]);
{
    if (argc == 2)
    {
        printf("hello, %s\n, argv[1]);
    }
    else{
        printf("hello, world\n")
    }
}
  1. argv[1] ?
    argv[0] 指键入的第一个单词 ———— 程序名称 (./helloargv)。
  2. argc 与 2 比?为什么是 2?
    argc 看你键入了几个单词。

可以用来检测人类是否键入了命令行参数,是否是可接受的。