CS50-Notes Week 2 Arrays

CS50 2025课程学习笔记
没有week0和week1,跳着看的,之后可能会补
代码与笔记文档均存放在github仓库CS50-Notes

Week 2 Arrays

编译的过程:
preprocessing
#<include> xxx 是复制粘贴
compiling
assembling
linking
e.g.编译指令中的-lcs50
连接cstdio.c hello.c cs50.c

debugging

1
2
3
4
5
6
7
8
9
10
11
12
13
buggy.c

#include <stdio.h>

int main(void)
{
for (int i = 0; i <= 3; i++)
{
printf("i is %i\n", i);
// 输出i的值从而更好的debug,"printf is ur friend".
printf("#\n");
}
}

%i:
printf中与%d等价,十进制整数
scanf中根据前缀识别进制,如0x为十六进制,0为八进制

1
2
3
4
5
6
7
8
9
10
11
12
scores.c

#include <stdio.h>

int main(void)
{
int score1 = 72;
int score2 = 73;
int score3 = 33;

printf("Average: %f\n", (score1 + score2 + score3) / 3.0);
}

使用数组简化代码
int scores[3]

1
2
3
4
int scores[3];
scores[0] = 72;
scores[1] = 73;
scores[2] = 33;
1
2
3
4
5
6
int scores[3];
int tmp;
for(int i = 0; i < 3; i++)
{
scores[i] = get_int("Score: ");
}

浮点数精度导致输出不同(59.333333 and 59.333332)

将求平均值写成函数
函数返回值可以是int, float…

1
2
3
4
5
6
7
8
9
10
11
hi.c  

#include <stdio.h>

int main(void)
{
char c1 = 'H';
char c2 = 'I';
char c3 = '!';
printf("%c%c%c\n", c1, c2, c3);
}
1
2
string s = "HI!";  
printf("%s\n", s);
  • 值得注意的是c语言并没有string类型(c++有),c语言中一般使用字符数组或指针来表示字符串。课程代码里的 stringcs50 头文件中的。

在这里s的长度是4个字节(字符串三个字节+结束标志’\0’)。

字符串用双引号表示如"HI!",告诉程序这是一个字符串,要在结尾补充‘\0’.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
length.c  

#include <stdio.h>

int string_length(char ch[]);

int main()
{
char name[100];
scanf("%s", name);
int length = string_length(name);
printf("%i\n", length);
}

int string_length(char ch[])
{
int n = 0;
while (ch[n] != '\0')
{
n++;
}
return n;
}

直接使用库函数简化代码
理解思路✔️造轮子❌

string.h 头文件

1
2
#include <string.h>
int length = strlen(name);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
string.c  

#include <stdio.h>
#include <string.h>

int main(void)
{
char s[100];
scanf("%s", s);
printf("Output: \n");
for (int i = 0; i < strlen(s); i++)
{
printf("%c", s[i]);
}
printf("\n");
}

优化:注意到每次for循环都会调用strlen()函数

1
for (int i = 0, n = strlen(s); i < n; i++)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
uppercase.c  

#include <stdio.h>
#include <string.h>

int main(void)
{
char s[100];
scanf("%s", s);
for (int i = 0, n = strlen(s); i < n; i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
// s[i] = s[i] - ('a' - 'A');
printf("%c", s[i] - 32);
}
else
{
printf("%c", s[i]);
}
}
printf("\n");
}
  • ‘a’(97) 和 ‘A’(65) 的ascii值差了32
  • 位运算也可以解决而且似乎能优化运行速度?
1
2
A: 0100 0001  
a: 0110 0001

大写字母在二进制下的第六位变为一即可得到小写。

ctype.h 头文件

toupper()函数

1
2
3
4
for (int i = 0, n = strlen(s); i < n; i++)
{
printf("%c", toupper(s[i]));
}

main函数的参数可以不为空吗?

当然可以

1
2
3
4
5
6
7
8
9
greet.c  

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
printf("hello, %s\n", argv[0]);
}

(argc stands for argument count)

终端输入
./greet chi
返回
hello, ./greet

  • 输入的内容从argv[1]开始。

代码修改后得到返回如:
hello, chi

注意到如果只输入指令./greet会得到如hello, (null)的返回。

1
2
3
4
5
6
7
8
if (argc == 2)
{
printf("hello, %s\n", argv[1]);
}
else
{
printf("hello, world\n");
}

为什么main函数返回int值?

返回值用来表示程序是否成功运行
类似使用软件时会出现的报错”error code: xxx”
类似http状态码如404
常用的return 0; 状态码为0代表程序成功运行。

终端输入echo $?查看最近命令的退出状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
status.c  

#include <stdio.h>

int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Missint command-line argument\n");
return 1;
}
printf("Hello, %s\n", argv[1]);
return 0;
}

Commands

code 创建程序
e.g. code hello.c

ls 列出当前目录下的所有文件(list)

rm 删除文件(remove)
e.g. rm hello.c

mkdir 创建文件夹
rmdir删除文件夹

make 编译并生成可执行文件
e.g. make scores

clang -o hello hello.c 也能达到同样效果

-o用于指定文件名称,直接使用clang hello.c 会创建一个名为a.out的可执行文件,因为并没有制定文件名

-l可在编译指令里引用头文件
e.g.-lm引用了math.h头文件

cp to copy a file
e.g. cp scores.c buggy.c
buggy.c 现在的内容和 scores.c相同

e.g. cp scores.c newcode.c
创建一个新的c文件并将scores.c中的内容复制过去

密码学

Brute force 暴力

Author

Patricia-Chi

Posted on

2026-01-06

Updated on

2026-01-22

Licensed under