#include “a.h”
// 1. main入门
// 包含一个叫stdio.h的文件
//std-标准 standard input output (使用c语言提供的库)
#include <stdio.h>
int main(){
printf("hello");
return 0;
}
// 2. 数据类型(char short int long long long float double)
int main(){
// char 字符类型
char ch = 'A'; // 内存
printf("%c\n", ch); // %c -- 打印字符格式的数据 : A
printf("%d\n", sizeof(char)); // sizeof() 查看类型大小(向内存空间申请大小)
// 整形 int
int age = 20;
printf("%d\n", age); // %d -- 打印整形十进制数据 : 20
return 0;
}
// 3. 输入scanf(“%d”, &price)
int main(){
int price = 0;
printf("请输入金额(元):");
// 获取输入
scanf("%d", &price);
int a,b;
// 获取多个
scanf("%d %d", &a, &b);
// 输出多个
printf("%d + %d = %d\n", a, b, a+b);
int change = 100 - price;
printf("找您%d元。\n", change);
return 0;
}
// 4. 常量和变量
int main(){
// 定义常量
const int AMOUNT = 100;
int price = 0;
printf("请输入金额(元):");
// 获取输入
scanf("%d", &price);
int change = AMOUNT - price;
printf("找您%d元。\n", change);
return 0;
}
// 5. 随机数 srand(time(0))
int main(){
//
srand(time(0));
// 随机数 0.0 - 0.9
int a = rand();
// 生成 0 - 100 的 数 ; 例子:int number = rand()%100+1;
printf("%d\n", a%100);
return 0;
}
// 6. goto out; 语句(一般在多重循环语句段落中使用goto 跳出多重循环结构代码片段)
int main(){
//
for( int i = 1; i < 100 ; i++){
for(int j = i ; j < i; j–){
if(i == 10){
// 跳出 语句 goto (跳到自己指定 的 out 标识符)
goto out;
}
}
}
out:
return 0;
}
// 7. pow() 幂次函数
int main(){
// 10的 4次方
int mask = pow(10, 4);
printf("mask = %d", mask);
// 表示 非负数 表示 , 默认 -128 ~ 127 , 加上 unsigned 范围就是 0 - 255
unsigned char c = 255; // printf("%d", c); == -1
int i = 255; // printf("%d", i); == 255
return 0;
}
// 辗转相除法, 求 两数 最小公约数
// 8. bool 非c语言 默认 数据 类型 ( if 语句 默认是 0false , 1true )
// bool 需要 导入 库
#include <stdbool.h>
int main(){
// 定义 bool 类型 变量
bool b = 6 > 5;
bool t = true;
t = 2;
printf("%d\n", b); // b ==> 1
return 0;
}
// 9. 逻辑 运算符 1. && 2. || 3. ! 取反 , 结果:处理都是 0 / 1
// bool 需要 导入 库
#include <stdbool.h>
int main(){
//1. age > 20 && age < 30
//2. index < 0 || index > 99
//3. ! age < 20
//4. 逻辑与(两边都要运算执行) / 短路与(一边判断成功,后面的运算直接短路结束)
return 0;
}
// 10. 数组
#include <stdbool.h>
int main(){
// 1. 初始化创建空间
int a[10]; //
// 2. 数组的集成初始化
int b[] = {2,4,6,8,10,1,5,7}
// 单独赋值
int c[] = {
[0] = 2, [2] = 3, 6 //表示 c[3] = 6 贴着
}
// 动态创建空间
int d[] = {
[1] = 2, [5] = 6 // 默认数组大小长度就是6
}
// sizeof
// 1. 获取数组的 整体字节 大小 / 4 = 数组的长度
// 2. sizeof(a) / sizeof(a[0]) 整体数组sizeof / 数组首位sizeof
// 不可以讲一个数组变量赋值给另外一个数组定义
//int newarr[] = b; // 这里是错误的!!!
//方法中的 int arr[] 数组形参,不能使用sizeof做计算大小,所以要传递length,如:search(int a , int arr[], int length)
// a : 要查找的数
// b : 要被查找的数组
// c : 要被查找的数组长度
// 调试代码块(可以定义在任意位置,用于调试,并且拥有独立局部变量)
{
// ......
printf("调试........");
{
//...
}
}
return 0;
}
// 函数 声明 + 定义
int sum(int a, int b);
// 11. 二维数组
#include <stdbool.h>
int main(){
// 1. 二维数组的初始化
int a[][5] = {
{0, 1, 2, 3, 4},
{2, 3, 4, 5, 6},
}
// 调用函数
sum(1, 2);
return 0;
}
// 函数定义
int sum(int a, int b){
return a + b;
}
// 12. 获取变量地址 & 符号
#include <stdbool.h>
int main(){
int input;
// 如
scanf("%d", &input);
// 查看 %x
printf("0x%x\n", &input);
// 地址 %p (相邻 变量 / 数组的地址 相差距离是 4)
printf("%p\n", &i);
// 强制转换 (地址)
int p;
p = (int)&input;
printf("%p\n", &input);
// 看强转后的地址大小
printf("lu\n", sizeof(int)); // 类型: 4
printf("lu\n", sizeof(&i)); //地址: 8 (64架构) // 32架构 = 4
return 0;
}
// 12. 指针 * 符号
#include <stdbool.h>
int main(){
// 指针:以scanf()函数为例
scanf("%d", &input); // 此时 scanf函数原型中的&input 就是引用指向
//指针: 保留 地址的变量
int i;
int* p = &i; //p 变量 指向的是 &i 的地址,即p 与 i一样 共享 &i 地址存储空间,栈堆是由上至下存储的,所以先写的变量会在上面
int* p, q; // p 指向 &i 的地址, q则是普通的int变量
int *p,q;
// 数组地址:
int a[10];
// 前面三个都是相同的 %p 输出地址 一致
printf("%p\n", &a);
printf("%p\n", a);
printf("%p\n", &a[0]);
printf("%p\n", &a[1]); // 是 &a[0] 地址值 + 4
// 注意:*表示引用
// 1. 变量的值是内存的地址
// 2. 普通变量的值是实际的值
// 3. 指针变量的值是具有实际值的变量的地址
// 数组作为参数时,与指针时等价的(下列四种参数接收数组*指针时,写法都是等价的,并非类型等价)
int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[], int n);
int sum(int [], int);
// 案例1:在指针中,存储的变量名 a == a[0] , 两者是相同的,这就是指针与数组的奇妙关系(数组变量无需使用&符号,默认赋值的就是地址[引用])
// -- 非数组变量测试,即普通变量 赋地址需要带上&符号
int t1 = 2;
int *t2 = &t1; // t1将地址共享给了t2, 此时 printf("*t2 = %d", t2) ==> 2, 也可以表示print("t2[0] = %d", t2[0]) == > 2
// -- 数组 测试,默认赋值就是地址(引用)无需携带 & 来表示 传地址
int arr1[10];
int *arr2 = arr1; // arr2 与 arr 指向同一地址
// -- 注意:数组变量之前是不能相互赋值的(错误)
int arr3[];
// 可以被看作 int * const b; (数组变量默认是 -> 常量指针const,所以不能被赋值)
int arr4[] = arr3; //写法错误 ,没办法将一串地址当作数组存储,逻辑有误!除非 * 加入指针标识符,告诉计算机这是接收地址
int *arr5 = arr3; // 写法正确
// -- 案例2:
char ac[] = {0,1,2,3,4,5,6,7,8,9,}
// 此时 *p = ac[0] 、 *(p+1) = ac[1] ; 即地址的移动 , 即:*(p+n) <=> ac[n] 等价于【数组特殊的地方】
char *p = ac; // 引用指向正确
// -- 注意 : 如果赋值数组中的某个元素,则该元素不是数组,而是char类型的,所以要加&,表示给地址。
char *p1 = &ac[5];
printf("p1 - p = %d\n", p1-p); // 当两个地址结果相减时,不是实际地址的差,而是实际地址的差 / sizeof(他们的类型大小) = 差值结果。
printf("p=%p\n", p); //0xbffbbd5e
printf("p+1=%p\n", p+1); //0xbffbbd5f(地址16进制,加了个1)
char ai[] = {0,1,2,3,4,5,6,7,8,9,}
char *q = ai; // 引用指向正确
printf("q=%p\n", q); //0xbffbad2c
printf("q+1=%p\n", q+1); //0xbffbad30(地址16进制,2c(0x2c = 44)、30(0x30 = 48),相差4)因为sizeof(char) = 1 / sizeof(int) = 4。
// [*p++] :*的优先级 < ++ 优先级,所以*p可以先++,举例用于数组的便利
{
char ac[] = {0,1,2,3,4,5,6,7,8,9, -1};
char *p = &ac[0];
int i;
// 普通遍历输出
for(i = 0; i < sizeof(ac) / sizeof(ac[0]); i++){
printf("%d\n", ac[i]);
}
// for (p = ac; *p != -1; )
while(*p != -1){
printf("%d\n", *p++);
};
}
//[指针比较:<, <=, ==, >, >=, !=]都可以对指针做 包括 + -
// 1. 比较他们的在内存中的地址、
// 2. 数组中的单元的地址肯定时线性递增的
// 0地址:
// 1. 内存中有0地址,但是0通常时不能随便碰的地址,因此用0地址表示特殊的事情(返回指针无效、指针没有被初始化,即先初始化为0)
// 2. null是一个预定 定义的符号,表示0地址。
// 指针的类型:
// 1. 无论指向什么类型,所有的指针的大小都是一样的
// 2. 但是指向不同类型的指针是不能直接互相赋值的,为了避免用错指针
// 指针的类型转换:(不确定指针类型 void*)
// 1. void* 表示不知道指向什么东西的指针,计算时可以与char*相同(但不相通)
// 2. 指针也可以转换类型,int *p = &i; void*q = (void*)p;
// 3. 这里并没有改变p所指的变量类型,而是让后人用不同的眼光通过p看它所指的变量
// 4. 我不再当你是int,我认为你就是个void!(通过q去看i,就不是int了,通过p去看i,i还是int)
// 指针做什么? 小节:
// 1. 需要传入 较大的数据时用作参数
// 2. 传入数组后对数组做操作
// 3. 函数返回不止一个结果(需要用函数来修改不止一个变量)
// 4. 动态申请的内存......
// [const]
// 举例1【const变量】:指针是 const:表示一旦得到了某个变量的地址,不能再指向其他变量
{
int temp = 10; // 假设地址:0x118967
int *const q = &i; // 此时q 变量 指向这个0x11896地址,就不能再改变,只能改变temp变量的值,因为temp变量的值不是常量,如:
*q = 26; // 正确执行
q++; //错误执行:q 是常量,不能再进行改变,地址指向 / 值已经确定。
}
// 举例2【const类型】:表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)
{
const int *p = &temp; // 也可以写成 int const* p = &temp; 取决于const和*号的前后位置
*p = 26; // 错误,*p 是类型 const
temp = 26; // 正确
p = %j; // 正确
}
// 举例3【转换】:总是可以把一个非const的值转换成const的(即;当要传递的参数的类型比地址大的时候,这是常用的手段:既能用比较少的字节
//数传值给参数,又能避免函数对外面的变量的修改)
{
void f(const int* x); // 此时是 const类型,即*x 无法改变,但x可以变,保护了原来 &a 变量 的 地址的 值
int a = 15;
f(&a); // ok
const int b = a; // 给了指针就表示引用了,即表示指向了,数组默认是引用,即指针
f(&b); // ok
b = a + 1; // 错误
}
// 举例4【数组内部每个元素 / 单元 都为const,即该数组必须初始化赋值】
{
const int a[] = {1, 2, 3, 4, 5};// 1 ~ 5 都为const
// 保护 数组 里面的 每一个 元素
int sum(const int a[], int length); // 保护数组参数 函数
}
return 0;
}
// 13. 动态内存分配 man malloc
#include <stdbool.h>
// malloc 函数 : void* malloc(size_t size);
#include <stdlib.h>
int main(){
// malloc 函数体:void* malloc(size_t size);
// 案例1:
int number;
int *a; // 指针和数组雷同,可以将*a当作数组看待
printf("输入数量:");
scanf("%d", &number);
//malloc返回的时void*,将a指针初始化数组,并且扩容空间,由于返回的时void*,所以需要强转,int a[number];【动态分配空间】
a = (int*)malloc(number*sizeof(int));
// 正序输出
for(i = 0; i < number; i++){
scanf("%d", &a[i]);
}
// 逆序输出
for(i = number-1; i >= 0; i--){
scanf("%d", a[i]);
}
// 注意:malloc是找系统借的,要还给系统
free(a); // free(&a); a时指针,所以看作数组,看作引用,无需加&
// 案例2:如果没有空间了,malloc返回0 / null
void *p;
int cnt = 0;
while( (p = malloc(100 * 1024 * 1024)) ){
cnt++;
}
printf("分配了%d 00MB的空间\n", cnt);
// 案例3:提示:释放指针不是申请来的
int i;
void *p; // 习惯:当定义指针时,默认初始化地址给0,即 void *p = 0; 0 地址指向的是 null,即使*p没有通过malloc借,也可以free(p); 不会报错
int cnt = 0;
p = malloc(100 * 1024 * 1024);
p = &i; // 错误:p 是malloc借来的
p++; //错误: 指针引用,相当于数组,++ 改变了地址
free(p);
free(null);// 正确,因为null 地址是0, 对于malloc来说他是无效地址,所以不会报错
return 0;
}
// 14. 字符串
#include <stdbool.h>
// malloc 函数 : void* malloc(size_t size);
#include <stdlib.h>
int main(){
// 字符数组
char word[] = {'H', 'e', 'l', 'l', 'o', '!',};
// 字符串
char word[] = {'H', 'e', 'l', 'l', 'o', '!', '\0'};
// 1. 以0(整数0)结尾的一串字符
// 2. 0或'\0'是一样的,但是和'0'不同
// 3. 0标志字符串的结束,但它不是字符串的一部分
// 4. 计算字符串长度的时候不包含这个0
// 5. 字符串以数组的形式存在,以数组或指针的形式访问
// 6. 更多的是以指针的形式
// 7. string.h里有很多处理字符串的函数
// 字符串变量
char *str = "hello";
char word[] = "hello";
char line[10] = "hello";
// 如果 指针str 是字符串,又叫做字符数组
char *s = "hello";
s[0] = 'B'; // 赋值错误!(只读!),如果要修改,则用数组 (char s[] = "hello, world!";) 来修改
// 若要修改
char sss[] = "hello";
sss[0] = 'B'; // 赋值正确!
printf("Here!s[0]=%c\n", s[0]);
// 两者地址相同,所以说字符串常量const,存储与常量池(即程序的代码端,只读)
printf("s=%p\n", s); // 地址:0xe1f82
printf("str=%p\n", str); // 地址:0xe1f82
// 对比 普通 字符数组
printf("Here!sss[0]=%c\n", sss[0]);
printf("sss=%p\n", sss);// 地址很大0x777sxxxc
int i = 0;
printf("i=%p\n", &i); // 地址很大0xbff1fd6c
// 指针函数数组?用途?
//1. 数组:这个字符串在这里,作为本地变量空间自动被回收
//2. 指针:这个字符串不知道在哪里,处理参数,动态分配空间
// 小节:如果要构造一个字符串 -> 数组
// 小节:如果要处理一个字符串 -> 指针
char *str = "Hello"; // 指针(常量池地址,只读)
char word[] = "Hello"; // 数组(堆地址)
// 字符串赋值
char *t = "title";
char *s; // 共享地址,赋值指针指向
s=t;
// 并没有产生新的字符串,只是让指针s指向了t所指的字符串,对s的任何操作就是对t做的。
// 字符串的输入输出
char word[8];
scanf("%s", word); // (读入一个单词,到空格、tab或回车为止)
printf("%s##\n", word); // Hello World! ---> 只留下 Hello
char words[8];
scanf("%s", words); // (读入一个单词,到空格、tab或回车为止)
printf("%s##%s##\n", word, words); // Hello (空格/回车)World! ---> 只留下 Hello World!
// 因此scanf是不安全的,因为不知道要读入的内容的长度,超过存储位置则读取为空。
// 此时,可以指定scanf的读取长度 7 + \0 就是 8个长度(在% 和 s 之间的数字表示 最多允许读入的字符的数量,这个数字应该比数组的大小小一)
scanf("%7s", words);
printf("%s##%s##\n", word, words);
//常见错误:以为char* 是字符串类型,定义了一个字符串类型的变量string 就直接使用了,由于没有对string初始化为0,所以不一定每次运行都出错
char *string;
scanf("%s", string); // 错误
//空字符串
char buffer[100] = ""; // 这是一个空的字符串,buffer[0] == '\0';
char buffer[] = ""; // 这个数组的长度只有1!
// 字符串数组
{
// a[0] ---> char[10] (字符数组 / 字符串)
// a[0] ---> char*
char a[][10] = { // (字符串数组)
"Hello",
"World", // 正确写法
// "shshshsshshshhshs", // 错误写法,超过最大限度
};
}
// main函数 参数表:【main函数-程序参数】( argc整数, argv 字符串数组)
int main(int argc, char const*argv[]); // argv[0] 是命令本身(当使用Unix的符号链接时,反映符号链接的名字)
// 输入案例:
{
int i;
for(i = 0; i<argc; i++){
// 第一个参数表示个数,第二个为参数列表,循环写入到字符串数组
printf("%d:%s\n", i, argv[i]);
}
}
//【单字符输入输出】
// putchar
int putchar(int c); // 向标准输出写一个字符、返回写了几个字符,EOF(-1) 表示写失败
// getchar
int getchar(void); // 从标准输出读入一个字符、返回类型是int,是为了返回EOF(-1)
// Windows -> Ctrl-Z 退出
// Unix -> Ctrl-D 退出
// getchar / getchar 案例:
{ // 比作main函数
int ch;
while( (ch = getchar()) != EOF ){
putchar(ch);
}
printf("EOF\n");
}
return 0;
}
// 14. 字符串函数 string.h
#include <stdbool.h>
// malloc 函数 : void* malloc(size_t size);
#include <stdlib.h>
// 字符串函数 string.h
#include <string.h>
/*
1. strlen //
2. strcmp
3. strcpy
4. strcat
5. strchr
6. strstr
*/
int main(){
// 1. 字符串长度strlen // const 不让当前函数体修改字符串形参 s内容
size_t strlen(const char* s); // 返回s 的int字符串长度(不包括结尾的0)
// 案例:
{
char line[] = "hello";
printf("strlen=%lu\n", strlen(line)); // 5
printf("sizeof=%lu\n", sizeof(line)); // 6 以为内存中还有 \0 结尾符号
printf("strlen=%lu\n", mylen(line)); // 5 使用自己定义的函数
}
// 手写一个查询字符串长度函数
size_t mylen(const char *s){
int idx = 0;
while(s[idx] != '\0'){
idx++;
}
return idx;
}
//------------------------------------------------
// 2. 字符串比较strcmp
int strcmp(const char *s1, const char *s2); // 比较两个字符串,返回 0(s1 == s2) / 1(s1 > s2) / -1(s1 < s2)
// 案例:
{
char s1[] = "abc";
char s2[] = "abc";
printf("%d\n", s1 == s2); // 数组默认是引用类型,比较的是地址,所以错误!
printf("%d\n", strcmp(s1, s2)); // 结果: 0 , 相等!
printf("%d\n", 'abc' - 'Abc'); // 结果: 32 (二者不相等时, 给出的是他们之间的差值)
printf("%d\n", 'abc' - 'abc '); // 结果: 0 - 32 , 多了个空格,空格在ascll码中代表32 (二者不相等时, 给出的是他们之间的差值)
// 用自己的函数
printf("%d\n", mycmp(s1, s2));
}
// 手写一个strcmp 字符串比较函数
int mycmp(const char *s1, const char *s2){
int idx = 0;
while( s1[idx] == s2[idx] && s1[idex] != '\0'){
//if( s1[idx] != s2[idx] ){
// break;
//}else if( s1[idex] != '\0'){
// break;
//}
idx++;
}
return s1[idx] - s2[idx];
}
// 优化..........
int mycmp(const char *s1, const char *s2){
while( *s1 == *s2 && *s1 != '\0'){
s1++; // s1 表示 引用地址 , 指针: *s1 <==> s1[0] , 表示值
s2++;
}
return *s1 - *s2;
}
//------------------------------------------------
// 3. strcpy 字符串拷贝: // 把src字符串拷贝到dst, restrict 表明src和dst 不重叠(C99), 返回dst,为了能链起代码来(链式编程)
char* strcpy(char *restrict dst, const char *restrict src);
// 赋值字符串 (经典案例)
char *dst = (char*) malloc( strlen(src) + 1 ); // 向内存申请 src + 1 大小的空间,因为字符串还得留一个空间 \0,strlen是不会判断\0结束符的
strcpy(dst, src); // 进行拷贝
// 归还 申请 空间
free(dst);
// 手写一个字符串copy函数
char* mycpy(char* dst, const char* src){
int idx = 0;
while(src[idx] != '\0'){ // 可以写成: while(src[idx]){...}
dst[idx] = src[idx];
idx++;
}
dst[idx] = '\0';
return dst;
}
// 指针版: 优化....................
char* mycpy(char* dst, const char* src){
// (1)
//while(*src != '\0'){ // 可以写成: while(src[idx]){...}
// *dst = *src; // 指针, 指针指向
// dst++;
// src++;
//}
//(2)
//while(*src){
// *dst++ = *src++;
//}
//(3)
while(*dst++ = *src++)
;
*dst = '\0';
return dst;
}
//------------------------------------------------
// 4. strchr 字符串搜索函数: 返回null表示没有找到!
char* strchr(const char *s, int c);
char* strrchr(const char *s, int c);
// 案例:
char s[] = "hello";
char *p = strchr(s, 'l'); // 返回: llo
p = strchr(p + 1, 'l'); // 返回: lo
printf("%s\n", p);
// 截取llo
char *t = (char*) malloc(strlen(p) + 1);
strcpy(t, s); //
printf("%s\n", t); //llo
free(t);
//截取 he
char c = *p;
// 断层
*p = 0; // 内存地址: s = h e \0 l o \0
char *t2 = (char*) malloc(strlen(s) + 1);
strcpy(t2, s); //
printf("%s\n", t2); // he
// 还原
*p = c; // 内存地址 : s = h e l l o \0
free(t2);
//------------------------------------------------
// 4. strchr 字符串找字符串: 返回null表示没有找到!
char* strstr(const char *s1, const char *s2);
char* strcasestr(const char *s1, const char *s2);
return 0;
}
// 15. 枚举(枚举是一种用户定义的数据类型, 它用关键字enum ,以如下语法来声明)
// enum 枚举类型名字 { 名字0, …, 名字n };
// 枚举类型名字通常并不真的使用, 要用的是在大括号里的名字, 因为它们就是常量符号,它们的类型是int, 值则依次从0 到 n. 如:
// enum colors {red, yellow, green};
// 表示就创建了 三个常量, red 是 0, yellow 是 1, green 是 2 …
// 当需要一些可以排列起来的常量值时, 定义枚举的意义就是 给了这些常量 值 名字…
// 案例 1
#include <stdlib.h>
enum COLOR {RED, YELLOW, GREEN};
int main(int argc, char const *argv[]){
int color = -1;
char *colorName = NULL;
printf("输入你喜欢的颜色的代码: ");
scanf("%d", &color);
swith( color ){
case RED: colorName = "red"; break;
case YELLOW: colorName = "yellow"; break;
case GREEN: colorName = "green"; break;
default: colorName = "unKnown"; break;
}
printf("你喜欢的颜色是%s\n", colorName);
return 0;
}
// 案例 2
// 枚举量 可以作为值
// 枚举类型可以跟上 enum 作为类型
// 但是实际上 是以 整数来做 内部计算和外部输入输出的 (可以当作 int 来 输入输出)
#include <stdlib.h>
enum color {red, yellow, green};
void f(enum color c);
int main(int argc, char const *argv[]){
enum color t = red;
scanf("%d", &t);
f(t);
return 0;
}
void f(enum color c){
printf(“&d\n”, c);
}
// 案例 3 : 这样需要遍历所有的枚举量或者需要建立一个用枚举量做下标的数组的时候就很方便了
#include <stdlib.h>
enum COLOR {RED, YELLOW, GREEN, NumCOLORS};
// 枚举量 : 声明枚举量的时候可以指定值
enum colors {RED = 1, YELLOW, GREEN = 5};
int main(int argc, char const *argv[]){
// 即使给枚举类型的变量 赋值 不存在的整数值, 也没有任何warning 或 error
enum COLOR color = 0;
printf("code for GREEN is %d\n", GREEN);
printf("and color is %d\n", color);
//
int color = -1;
char *ColorNames[NumCOLORS] = {
"red", "yellow", "green",
}
char *colorName = NULL;
printf("输入你喜欢的颜色的代码: ");
scanf("%d", &color);
if(color >= 0 && color < NumCOLORS){
colorName = ColorNames[color];
}else{
colorNmae = "unKnown";
}
printf("你喜欢的颜色是%s\n", colorName);
return 0;
}