if 在条件(condition)为真时运行一个代码块。C 默认没有真正的布尔值(boolean)类型:0 为假,任何非零值为真。用 else if 和 else 串联多个选择。用 ==、!=、<、>、<=、>= 比较。
#include <stdio.h>
int main(void) {
int score = 72;
if (score >= 90) {
printf("A\n");
} else if (score >= 60) {
printf("Pass\n");
} else {
printf("Fail\n");
}
return 0;
}
if 选择真分支;else 选择假分支
2.2
switch
switch 根据一个整数值选择一个 case。每个 case 都需要一个 break 来跳出(jump out)——否则 C 会"贯穿"到下一个 case。当没有匹配时运行 default。
#include <stdio.h>
int main(void) {
int day = 3;
switch (day) {
case 1: printf("Mon\n"); break;
case 2: printf("Tue\n"); break;
case 3: printf("Wed\n"); break;
default: printf("Other\n");
}
return 0;
}
#include <stdio.h>
int square(int x) { // x 是一个参数
return x * x; // 交回一个值
}
int main(void) {
int r = square(5);
printf("%d\n", r); // 25
return 0;
}
Parameters in; return value out
4.2
函数原型与作用域
C 从上往下读,所以函数在被调用之前必须先被认识。函数原型(prototype)——就是头部那一行加上 ;——提前声明它,这样你就能把 main 放在最前面。变量的作用域(scope)是它所在的代码块:它是局部(local)的,代码块结束时就消失。
#include <stdio.h>
int add(int a, int b); // 函数原型:在使用前声明
int main(void) {
printf("%d\n", add(3, 4)); // 7
return 0;
}
int add(int a, int b) { // 定义放在后面
int sum = a + b; // sum 是 add 的局部变量
return sum;
}
#include <stdio.h>
int main(void) {
int scores[3] = {88, 71, 95};
printf("%d\n", scores[0]); // 88
scores[1] = 100;
printf("%d\n", scores[1]); // 100
int n = sizeof(scores) / sizeof(scores[0]);
printf("%d\n", n); // 3
return 0;
}
Array slots are indexed from 0
5.2
数组算法
用 for 循环遍历(traverse)数组,求最大值、总和或计数。始终从 0 循环到 n - 1。
#include <stdio.h>
int main(void) {
int a[] = {3, 9, 2, 7};
int n = sizeof(a) / sizeof(a[0]);
int max = a[0], total = 0;
for (int i = 0; i < n; i++) {
if (a[i] > max) max = a[i];
total += a[i];
}
printf("%d %d\n", max, total); // 9 21
return 0;
}
结构体(struct)把相关的值组合成一个类型。其中每个值是一个成员(member)。typedef 给结构体起一个短名字,这样你就能写 Dog 而不用写 struct Dog。对结构体值用 .,但对指向结构体的指针用 ->。
#include <stdio.h>
typedef struct {
char name[20];
int age;
} Dog;
int main(void) {
Dog d = {"Rex", 3};
printf("%s is %d\n", d.name, d.age); // Rex is 3 (对值用 .)
Dog *p = &d;
p->age = 4; // 对指针用 ->
printf("%s is %d\n", d.name, d.age); // Rex is 4
return 0;
}
常见错误
对结构体值用 .,对结构体指针用 ->。
typedef 让你声明时省去 struct 这个词;没有它就要写 struct Point p;。
#include <stdio.h>
int linear(int a[], int n, int target) {
for (int i = 0; i < n; i++)
if (a[i] == target) return i;
return -1;
}
int binary(int a[], int n, int target) {
int lo = 0, hi = n - 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (a[mid] == target) return mid;
else if (a[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int main(void) {
int a[] = {2, 5, 8, 12, 16, 23};
int n = sizeof(a) / sizeof(a[0]);
printf("%d %d %d\n", linear(a, n, 12), binary(a, n, 12), binary(a, n, 9));
return 0; // 3 3 -1
}
#include <stdio.h>
#include <string.h>
int main(void) {
char *s = "aaabbc";
int n = strlen(s);
for (int i = 0; i < n; ) {
char c = s[i];
int run = 0;
while (i < n && s[i] == c) { run++; i++; }
printf("%d%c", run, c); // 3a2b1c
}
printf("\n");
return 0;
}
#include <stdio.h>
#define MAX 100 // macro: text replaced before compiling
enum Color { RED, GREEN, BLUE }; // named integers 0, 1, 2
int next_id(void) {
static int count = 0; // keeps its value between calls
count++;
return count;
}
int main(void) {
const double PI = 3.14; // cannot be changed
printf("%d %.2f\n", MAX, PI); // 100 3.14
printf("%d %d %d\n", RED, GREEN, BLUE); // 0 1 2
int a = next_id();
int b = next_id();
printf("%d %d\n", a, b); // 1 2
return 0;
}