Chapter 2 ( C语言概述 )
2.1 ‘’#include" 和头文件
#include<stdio.h>
- #include<stdio.h>相当于把stdio.h文件所有内容都输出到该行所在的位置,类似于复制粘贴操作
- “#”表明,C预处理器在编译器接手之前处理这条指令
- 该文件包含了供编译器使用的输入和输出函数,例如 printf() 的使用
Q: 为什么不内置输入和输出函数?
A: 并非有的程序都会用到 I/O 包,这也使得C语言成为流行的嵌入式语言
2.2 main()函数
int main(void) # 现在的c语言标准
main() # C90可以运行,但最新的C99标准和C11标准不允许这样写
2.3 命名规则
使用小写字母、大写字母、数字和下划线来命名,并且第一个字符必须是字母或下划线,不能是数字
eg.函数调用
#include <stdio.h>
void butler(void);
int main(void)
{
int dogs;
printf("How many dogs\n");
// 用scanf_s 替代 scanf
scanf_s("%d", &dogs);
printf("So you have %d dogs\n", dogs);
butler();
}
void butler(void)
{
printf("调用了第二个函数\n");
}
Chapter 3 ( 数据和C )
eg. (scanf获得用户输入)
#include <stdio.h>
int main(void)
{
float weight;
float value;
// %f 以float形式读取键盘输入数据 &weight 告诉scanf将数据赋值给weight
scanf_s("%f", &weight);
value = 1700 * weight * 14.5833;
// %.2f 指定输出的浮点数只显示小数点后两位
printf("your weight in platinum is worth %.2f", value);
}
3.1 数据类型
3.1.1 数据类型关键字
最初关键字 | C90标准添加关键字 | C99标准添加关键字 |
---|---|---|
int(默认存储) | signed | _Bool |
long | void | _Complex(复数) |
short | _Imaginary(虚数) | |
unsigned | ||
char | ||
float | ||
double(默认存储) |
3.1.2 位、字节和字
Name | 描述 |
---|---|
位(bit) | 最小的存储单位,可以存储0或1 |
字节(byte) | 一个字节为8位,可以表述0-255的整数 |
字(word) | 设计计算机给定的自然存储单位,最初一个字有8位,后来出现16位、32位和目前的64位,字长越大,数据转移越快 |
3.1.4 整数类型
(1) 声明和初始化
long int a; // long int 可以简写为 long
long a;
short int a; // short int 可以简写为 short
short a;
long long int a; // long long int 可以简写为long long
long long a;
unsigned int a; // unsigned int 可以简写为unsigned, 允许取值范围是 0 ~ 65535
unsigned a;
unsigned long a;
unsigned short a;
signed int a; // signed写不写都行,即signed int与int 相同,其它类推也是如此
(2) 各整数类型所占字节数和取值范围 (不同电脑可能不一样):
- short: -27 ~ 27 - 1
- int/long: -215 ~ 215 -1
- long long: -231 ~ 231 - 1
#include <stdio.h>
int main(void)
{
printf("short int占字节数%d\n", sizeof(short)); // 2
printf("unsigned short占字节数%d\n", sizeof(unsigned short)); // 2
printf("int占字节数%d\n", sizeof(int)); // 4
printf("unsigned int占字节数%d\n", sizeof(unsigned)); // 4
printf("long int占字节数%d\n", sizeof(long)); // 4
printf("unsigned long占字节数%d\n", sizeof(unsigned long)); // 4
printf("long long占字节数%d\n", sizeof(long long)); // 8
}
(3) 打印short、long、long long、和unsigned类型
#include<stdio.h>
int main(void)
{
unsigned int us = 3000000000;
short st = 200;
long lg = 65537;
long long ll = 12345678908642;
printf("us = %u 不是 %d\n", us, us);
printf("st = %hd, 也是 %d\n ", st, st);
printf("lg = %ld, 也是 %d\n", lg, lg);
printf("ll = %lld 不是 %ld\n", ll, ll);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wPXfjKv-1665883159516)(C:\Typora\imgs\Snipaste_2022-09-05_18-19-41.png)]
(4) 八进制和十六进制
#include <stdio.h>
int main(void)
{
int x = 100;
// 十进制decimal,八进制octal,十六进制hexadecimal
printf("dec = %d, octal = %o, hex = %x\n", x, x, x);
// 显示各进制前缀
printf("dec = %#d, octal = %#o, hex = %#x\n", x, x, x);
}
3.1.5 char类型(最小整数类型)
-
char类型实际存储的是数字而非字符,按照编码集用特定的整数表示特定的字符
-
使用单引号括起来, 不能使用双引号(字符串类型),不能不加引号(变量)
char demo = 'C';
char b = 65; // 没错,但不是一种好的编程风格
printf("%d",demo); // 67
printf("%c",demo); // C
.png)]
转义字符
\\ \’ \" 用于打印 \ ’ "
// 打印 He said: "I ONCE LOVED YOU"
printf("He said: \"I ONCE LOVED YOU\" ");
3.1.6 浮点型
(1) 声明和初始化
- float取值范围 10-37 ~ 1037, 用 f/F 表示为float类型数据,否则默认为double
float a; // 至少能表示6位有效数字
double a; // 至少能表示10位有效数字
float a = 6.63e-34;
long double a; // 精度比double更高
int cost = 12.9; // double类型的值初始化为int类型变量
float pi = 3.1414 // double类型的值初始化为float类型变量
(2) 浮点型常量书写
1.56E+12 // + 可以省略, 即1.56E12
.2 // 即0.2
.8e3 // 即0.8*10^3
100. // 即100
(3) 浮点数打印
printf()函数使用 %f 打印十进制计数法的float和double; %e 打印指数计数法的浮点数
十六进制问题: C99标准新增用十六进制表示浮点数, 含前缀0x,用p代e, 用2代10的幂
#include<stdio.h>
int main(void)
{
float a = 32000.0;
double b = 2.14e9;
long double c = 5.32e-3;
printf( "%f 等于 %e \n", a, a); // 32000.000000 等于 3.200000e+04
printf("%e 等于十六进制 %a\n", b, b); // 2.140000e+09 等于十六进制 0x1.fe373c0000000p+30
printf("%Lf 等于 %Le", c, c); // 0.005320 等于 5.320000e-03
return 0;
}
(4) 浮点数上溢和下溢
- 当计算结果过大,超过当前类型能表达的范围时,就会发生上溢,printf显示该值为inf 或 infinity
3.1.7 复数和虚数类型
- 三种复数类型:float_Complex double_Complex long double_Complex
- 三种虚数类型:float_Imaginary double Imaginary long double_Complex
- 如果包含complex.h 头文件, 可以用 complex 替代 _Complex, 用 imaginary 替代 _Imaginary
Chapter 4 (字符串和格式化输入/输出)
eg. (scanf获得用户输入)
#include<stdio.h>
#include<string.h>
#define DENSITY 62.4 //人体密度
int main(void)
{
float weight, volume;
int size, letters;
char name[40]; // 容纳40个字符的数组, 40个连续的字节
printf("what's your name?\n");
scanf_s("%s", name, sizeof(name)); // 没有“&”符号
printf("%s,what's your weight in pounds?\n", name);
scanf_s("%f", &weight);
size = sizeof(name);
letters = strlen(name); // 获得字符串长度
volume = weight / DENSITY;
printf("%s,your volume is %2.2f cubic feet\n", name, volume);
printf("%d letters, %d bytes to store\n", letters, name);
return 0;
}
- 用数组(array)存储字符串(string),数组占用内存中40个连续的字节,每个字节存储一个字符值
4.1 字符串简介
4.1.1 char类型数组何null字符
- c语言没有专门用于存储字符串的变量类型,字符串都是被存储在char类型数组里面
- c语言字符串一定以空字符结束,其ASCII码数值也为0
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6QLNEYqz-1665883159518)(C:\Typora\imgs\Snipaste_2022-09-14_15-39-47.png)]
4.1.2 字符串使用
- 不用亲自在字符串结尾加上空字符,scanf()读取输入时完成了这个操作
- scanf()只读取了angela none none的angela,它遇到第一个空白(空格、制表符或换行符)时就不再读取输入
#include<stdio.h>
int main(void)
{
char name[40];
printf("your name is ?");
scanf_s("%s", name, sizeof(name)); // 防止内存泄漏,第三个位置要填上name所占字节数,这里是40
printf("hello, %s", name);
return 0;
}
your name is ? angela none none
hello, angela
4.1.3 strlen()函数
- sizeof()运算符的返回类型提供了%zd转换说明,这同样适用于strlen()
- sizeof()运算对象时类型时括号必不可少,对于特定变量可有可无,但建议一般情况下加上括号
#include<stdio.h>
#include<string.h>
#define PRAISE "You are good" // 12
int main(void)
{
char name[40];
printf("whats your name ?\n"); // cxy
scanf_s("%s", name, sizeof(name));
printf("your name have %zd letters occupies %zd memory cells\n", strlen(name), sizeof(name)); // 3 40
printf("PHRAISE have %zd letters occupies %zd memory cells",
strlen(PRAISE), sizeof(PRAISE)); // 12 13
return 0;
}
- 对于常量,sizeof()把末尾不可见的空字符也计算在内
4.2 printf()
4.2.1 转换符号
- 转换是把以二进制存储在计算机中的值转换成一系列字符(字符串)以便于显示
转换符号 | 转换说明 |
---|---|
%c | 转化为字符并打印 |
%d %o %x | 转化为 十进制整数 八进制整数 十六进制整数并打印 |
%e %f | 浮点数的 e计数法 和 十进制计数法 |
%s | 字符串打印 |
%u | unsigned,无符号十进制整数 |
%% | 百分号打印 |
#include <stdio.h>
#define PAGES 959
int main(void)
{
printf("*%d*\n", PAGES); // *959*
printf("*%2d*\n", PAGES); // *959*
printf("*%10d*\n", PAGES); // * 959*
printf("*%-10d*\n", PAGES); // *959 *
return 0;
}
4.2.2 转换修饰符
修饰符 | 含义 | 例子 |
---|---|---|
标记 | -(左对齐)、+(符号显示)、空格(显示前导空格)、#(进制显示)、0(前导0填充) | %-10d |
数字 | 最小字段宽度,过短则系统默认填充 | %4d |
.数字 | 精度 | %5.2f |
h | 搭配整形转换,%hd(打印short int)、%hu(打印unsigned short int) | |
l | 搭配整形转换,%ld(打印long int)、%lu(打印unsigned long) | |
ll | 搭配整形转换,%lld、%llu | |
hh | 搭配整形转换,%hhd(打印char,),%hhu(打印unsigned char) | 貌似与%d、%u效果相同? |
L | 搭配浮点形转换,%Lf / %Le(打印long double) |
#include <stdio.h>
int main(void)
{
const double RENT = 3852.99;
printf("*%f*\n", RENT); // *3852.99*
printf("*%e*\n", RENT); // *3.852990e+03*
printf("*%4.2f*\n", RENT); // *3852.99*
printf("*%3.1f*\n", RENT); // *3852.9*
printf("*%10.3f*\n", RENT); // * 3852.99*
printf("*%10.3E*\n", RENT); // * 3.85e+03*
printf("*%+4.2f*\n", RENT); // *+3852.99*
printf("*%010.2f*\n", RENT); // *3852.99*
return 0;
}
#include <stdio.h>
#define BLURB "Authentic imitation!"
int main(void)
{
printf("[%2s]\n", BLURB); // [Authentic imitation!]
printf("[%24s]\n", BLURB); // [ Authentic imitation!]
printf("[%24.5s]\n", BLURB); // [ Authe]
printf("[%-24.5s]\n", BLURB); // [Authe ]
return 0;
}
4.2.3 转换不匹配
#include <stdio.h>
int main(void)
{
float n1 = 3.0;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;
printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
printf("%ld %ld\n", n3, n4);
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
return 0;
}
- 出现错误的原因和参数传递的形式和栈的结构有关,不展开叙述了,即要使用正确的转换符号
4.2.4 打印较长的字符串
(1) 方法一
- 使用多个printf,但不用 \n 换行符
(2) 方法二
- 使用 \ 进行断行
printf("im here to print\ a long string"); // im here to print a long string
(3) 方法三
- 两个字符串之间用空格隔开,C语言会把多个字符串看作是一个字符串
printf("im here to print" " a long string");
**4.3 scanf()
如果要输入整数2014,就要键入2、0、1、4。如果要将其存储为数值而不是字符串,程序就需要把字符串依次转化为数值,这就是scanf()要做的事
- scanf() 读取基本变量类型的值,在变量名之前加上一个&
- 如果用scanf()把字符串读入字符数组中,不要使用&
4.3.1 读取规则
- scanf()函数使用空白(换行符、制表符和空格)把输入分为多个部分,再依次把转换说明和被分开的部分进行匹配
- 唯一例外的是%c转换说明,根据%c, scanf()会读取每个字符
#include<stdio.h>
int main(void)
{
int age = 10;
float money = 10.0;
char pet[30];
scanf_s("%f %d", &money, &age);
scanf_s("%s", pet, sizeof(pet)); // 可以载入中文
printf("money=%f,age=%d,pet=%s", money, age, pet);
return 0;
}
4.3.2 转换说明
- 对于float和double类型,printf()使用%f、%e、%g、%a转换说明,而scanf()只把他们用于float类型,对于double类型需要加上l修饰符(如%lf、%le等)
#include<stdio.h>
int main(void)
{
double money;
scanf_s("%lf", &money);
printf("money=%f", money);
return 0;
}
4.3.3 scanf()一些特性
(1) 读取障碍
- 使用%d转换时,scanf()期望遇到整数或者符号(+、-),当遇到时,scanf()读取和保存该字符,直至遇到非数字字符,此时scanf()认为到达了整数的结尾。而且scanf()把非数字字符放回输入,意味着程序在下一次读取输入时,首次读取到的是上一次读取丢弃的非数字字符
- 使用%d转换时,如果遇到A而不是数字,scanf()将停在那里,把A放回输入中,不会把值赋给指定变量。程序在下一次读取时,首先读取的依然是A。如果只使用%d转换说明,scanf()就一直无法超越A读取到下一个字符
#include<stdio.h>
int main(void)
{
int age;
float money;
int something;
scanf_s("%d %f %d", &age, &money, &something);
printf("age=%d, money=%f, something=%d", age, money, something);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i4hC3dih-1665883159524)(C:\Typora\imgs\Snipaste_2022-09-17_16-30-10.png)]
- 如果使用%s转换说明,scanf()会使用除去空白以外的所有字符,scanf()把字符串放进指定数组中,会在字符序列的末尾加上’\0’
(2) 格式字符串的普通字符
scanf("%d,%d", &n, &m);
-
将其解释为:用户将输入一个数字,一个逗号,然后再输入一个数字
-
// 这几种都可以,scanf()自动跳过空格 88,123 88, 123 77 , 123
4.4 printf()和scanf()的*修饰符
4.4.1 printf()的*修饰符
如果不想预先指定字段宽度,可以用*修饰符替代字符宽度,但是需要一个额外参数指定*的值
#include <stdio.h>
int main(void)
{
unsigned width, precision;
int number = 256;
int width = 6;
printf("The number is :%*d:\n", width, number);
printf("Now enter a width and a precision:\n");
scanf("%d %d", &width, &precision);
printf("Weight = %*.*f\n", width, precision, weight);
printf("Done!\n");
return 0;
}
4.4.2 scanf()的*修饰符
scanf()中*的用法与printf()中不同把*放在%和转换符号之间时,会使scanf()跳过相应的输入项
#include <stdio.h>
int main(void)
{
int n;
printf("Please enter three integers:\n");
scanf("%*d %*d %d", &n);
printf("The last integer was %d\n", n);
return 0;
}
4.4.3 printf()的提示用法
#include<stdio.h>
int main(void)
{
printf("%6d %6d %6d\n", 123, 456, 789);
printf("%6d %6d %6d", 3, 6, 7);
return 0;
}
- 使用固定字段长度可以让输出整齐美观
- 两个转换符号之间插入一个空格,可以确保即使一个数字溢出了自己的字段,下一个数字不会紧跟着该数字一起输出
Chapter 5(运算符、表达式和语句)
- 与java等语言的重复性较高,如+、-、*、/、%、++、-- 就不再介绍了
5.1 while循环
- while循环已经很熟悉了,看下c语言下while循环的结构吧, 其实和 java 差不多
#include <stdio.h>
#define ADJUST 7.31 // 字符常量
int main(void)
{
const double SCALE = 0.333; // const变量
double shoe, foot;
printf("Shoe size (men's) foot length\n");
shoe = 3.0;
while (shoe < 18.5) /* starting the while loop */
{ /* start of block */
foot = SCALE * shoe + ADJUST;
printf("%10.1f %15.2f inches\n", shoe, foot);
shoe = shoe + 1.0;
} /* end of block */
printf("If the shoe fits, wear it.\n");
return 0;
}
5.2 基本运算符
5.2.1 术语: 数据对象、左值、右值
(1) 数据对象: 用于存储值的数据存储区域统称为数据对象。
- C标准只有提到这个概念的时候才会用到"对象’'这个术语
- 使用变量名是标示对象的一种方法,除此之外还有指针表达式等方式
(2) 左值: 用于标示对象的名称或表达式
- 对象指的是实际的数据存储,而左值是用于标示或定位存储位置的标签
- 可修改的左值:用于标识可修改的对象
(3)右值: 能赋值给可修改左值的量
5.2.2 运算符
- c语言支持三重赋值
#include <stdio.h>
int main(void)
{
int jane, tarzan, cheeta;
cheeta = tarzan = jane = 68; // 三重赋值,顺序从右向左
printf(" cheeta tarzan jane\n");
printf("First round score %4d %8d %8d\n",cheeta,tarzan,jane);
return 0;
}
- 与java相同的截断效应
/* divide.c -- divisions we have known */
#include <stdio.h>
int main(void)
{
printf("integer division: 5/4 is %d \n", 5/4); // 1
printf("integer division: 6/3 is %d \n", 6/3); // 2
printf("integer division: 7/4 is %d \n", 7/4); // 1
printf("floating division: 7./4. is %1.2f \n", 7./4.); // 1.75
printf("mixed division: 7./4 is %1.2f \n", 7./4); // 1.75
return 0;
}
- 比较浮点数时,尽量只是用>和<, 因为浮点数的舍入误差会导致逻辑上相等的数值不等
5.2.3 优先级说明
关于 ++ 和 --运算符
- ++、–优先级很高,只有圆括号比它们高,因此,x*y++表示的是x*(y++)
- (x+y)++ 这种写法是错误的,因为递增和递减运算符只能影响一个变量
- 可以根据优先级判断该++是否有效
#include <stdio.h>
int main(void)
{
int y = 2;
int n = 3;
int num = (y + n++) * 6; // 答案是30
printf("%d", num);
return 0;
}
5.3 类型转换
- 当作为函数参数传递时,char和short被转换成int,float被转换成double
- 类型从高到低为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int, int。short和long没有列出,因为他们在运算过程中会自动转换为int或unsigned int
#include <stdio.h>
int main(void)
{
char ch;
int i;
float fl;
fl = i = ch = 'C'; // 'C' = 67
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); // ch = 'C', i = 67, fl = 67.0
ch = ch + 1; // ch = 68
i = fl + 2 * ch; // i = 67.0 + 2 * 68 = 203
fl = 2.0 * ch + i; // fl = 2 * 68 + 203 = 339
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); // ch = 'D', i = 203, fl = 339.0
ch = 1107;
printf("Now ch = %c\n", 1107); // ch = 1107 % 256 = 83 = 'S'
ch = 80.89;
printf("Now ch = %c\n", ch); // ch = 80 = 'P'
return 0;
}
(1) 强制类型转换
mice = (int)1.6 + (int)1.2 // 2
5.4 带参数的函数
- 如果函数不接受任何参数,函数头的圆括号应该写上关键字void
- 形参:声明参数就创建了被称为形式参数; 函数调用传递的值为实际参数
#include <stdio.h>
void pound(int n);
int main(void)
{
int a = 3;
pound(a); // ###
} // a 是实参
void pound(int n) // n是形参
{
while (n-- > 0)
{
printf("#");
}
return 0;
}
Chapter 6(C控制语句:循环)
eg.(while循环)
#include <stdio.h>
void pound(int n);
int main(void)
{
int num;
int sum = 0;
printf("输入一个值\n");
int status = scanf_s("%d", &num); // 不再需要加sizeof
while (status == 1)
{
sum = sum + num;
printf("继续输入一个值,'q'退出\n");
status = scanf_s("%d", &num);
printf("status值是:%d\n", status);
}
}
- 输入非数字就返回0 (把char字符作为整数读取失败)
int status = scanf("%c", &num) //测试结果:无论我输入什么都返回1
6.1 关系运算符
6.1.1 0和1/真和假
- 对c语言来说,表达式为真的值是1,表达式为假的值为0
#include <stdio.h>
int main(void)
{
int true_val, false_val;
true_val = (10 > 2); // true_val = 1
false_val = (10 == 2); // true_val = 0
printf("true = %d; false = %d \n", true_val, false_val);
return 0;
}
- 0和1(不一定为1,一般为非0数字)可以被当作if或者while的循环判断条件使用
#include <stdio.h>
int main(void)
{
int n = 3;
while (n)
printf("%2d is true\n", n--);
printf("%2d is false\n", n);
n = -3;
while (n)
printf("%2d is true\n", n++);
printf("%2d is false\n", n);
return 0;
}
6.1.2 "==“和”="混淆造成错误
- scanf()以指定的形式输入失败,即q,就把无法读取的输入留在输入队列中,供下次读取使用
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L;
int status;
printf("Please enter an integer to be summed ");
printf("(q to quit): ");
status = scanf("%ld", &num);
while (status = 1) // 这里'=='被替换为'=', 一直为true
{
sum = sum + num;
printf("Please enter next integer (q to quit): ");
status = scanf("%ld", &num); // q读取失败,则把q留在输入队列中,供下次读取使用
}
printf("Those integers sum to %ld.\n", sum);
return 0;
}
6.2 _Bool类型(C99及以上)
- _Bool变量只能存储1(真)或0(假),如果把其它非0数值赋值给_Bool类型变量,则该变量会被设成1,这反映了C把所有的非0值都视为真
#include<stdio.h>
void main()
{
int sum = 0;
int num;
_Bool boolean;
printf("输入数字, q退出\n");
boolean = scanf_s("%d", &num);
while (boolean)
{
sum = sum + num;
printf("继续输入数字, q退出\n");
boolean = scanf_s("%d", &num);
}
printf("结束循环,和为%d", sum);
}
6.3 其它运算符(+=、-=、*=、/=、%=)
6.4 for循环
- 和java的一样, 不做过多介绍,下面的do while循环同理
- for (初始条件;循环条件;进行一次循环后的变化)
#include <stdio.h>
int main(void)
{
const int NUMBER = 5;
int count;
for (count = 1; count <= NUMBER; count++)
printf("Be my Valentine!\n"); // 打印五次
return 0;
}
6.4.1 逗号运算符
#include <stdio.h>
int main(void)
{
const int FIRST_OZ = 46; // 2013 rate
const int NEXT_OZ = 20; // 2013 rate
int ounces, cost; // 逗号运算符(1)
printf(" ounces cost\n");
for (ounces=1, cost=FIRST_OZ; ounces <= 16; ounces++, // 逗号运算符(2)
cost += NEXT_OZ)
printf("%5d $%4.2f\n", ounces, cost/100.0);
return 0;
}
6.5 do while循环
- 适用于至少要迭代一次的循环
#include <stdio.h>
int main(void)
{
const int secret_code = 13;
int code_entered;
do
{
printf("To enter the triskaidekaphobia therapy club,\n");
printf("please enter the secret code number: ");
scanf("%d", &code_entered);
} while (code_entered != secret_code);
printf("Congratulations! You are cured!\n");
return 0;
}
6.6 数组简介
-
和java等语言不同的是,为了效率,使用下标对数组进行赋值时编译器不会考虑下标是否超出数组的长度范围,这将导致数据存放在该数组以外的地方,会破坏程序结果、导致程序中断
int arr[10]; arr[12] = 6; // 并不会报出"index out of range"错误
-
char类型数组和int类型数组区别是,每个int占4个字节,每个char占1个字节
(1) 和scanf()搭配使用
#include <stdio.h> int main(void) { int arr[10]; arr[1] = 1; printf("arr的第二个元素定义为\n"); scanf_s("%d", &arr[2]); // 如果输入 10 printf("%d", arr[2]); // 打印 10 return 0; }
6.6.1 for循环使用数组
#include <stdio.h>
#define SIZE 10
#define PAR 72
int main(void)
{
int index, score[SIZE];
int sum = 0;
float average;
printf("Enter %d golf scores:\n", SIZE);
for (index = 0; index < SIZE; index++)
scanf("%d", &score[index]); // 读取10个分数
printf("The scores read in are as follows:\n");
for (index = 0; index < SIZE; index++)
printf("%5d", score[index]); // 打印数组
printf("\n");
for (index = 0; index < SIZE; index++)
sum += score[index]; // 求总分
average = (float) sum / SIZE; // 求平均分
printf("Sum of scores = %d, average = %.2f\n", sum, average);
printf("That's a handicap of %.0f.\n", average - PAR);
return 0;
}
6.7 math库
6.7.1 pow()函数
- math.h库提供了一个强大的幂函数power(),可以使用浮点指数
#include<stdio.h>
double power(double base, int alpha);
void main()
{
double result = power(2.0, 3);
printf("%f", result); // 8.000000
}
double power(double base, int alpha)
{
double result = 1.0;
for (int i = 1; i <= alpha; i++)
result = result * base;
return result;
}
// scores_in.c -- uses loops for array processing
#include <stdio.h>
#define SIZE 10
#define PAR 72
int main(void)
{
int index, score[SIZE];
int sum = 0;
float average;
printf("Enter %d golf scores:\n", SIZE);
for (index = 0; index < SIZE; index++)
scanf("%d", &score[index]); // read in the ten scores
printf("The scores read in are as follows:\n");
for (index = 0; index < SIZE; index++)
printf("%5d", score[index]); // verify input
printf("\n");
for (index = 0; index < SIZE; index++)
sum += score[index]; // add them up
average = (float) sum / SIZE; // time-honored method
printf("Sum of scores = %d, average = %.2f\n", sum, average);
printf("That's a handicap of %.0f.\n", average - PAR);
return 0;
}
一些习题
#include<stdio.h>
int main(void)
{
char start = 'F';
for (int i = 1; i <= 6; i++)
{
for (int j = 0; j < i; j++)
printf("%c", start - j);
printf("\n");
}
return 0;
}
Chapter 7 (c语言控制语句:分支和跳转)
7.1 if else / else if 语句
if (all_days != 0)
printf("打印");
else
{
printf("长语句");
printf("else");
}
if (a == 0)
xxxx;
else if (a == 1)
xxxx;
else
xxxx;
7.2 getchar()和putchar()
- getchar()函数不带任何参数,从输入队列返回下一个字符
- putchar()函数打印它的参数
- 两者都只处理字符
// 效果相同
char ch = getchar();
scanf_s("%c", &ch);
// 效果相同
putchar(ch);
printf("%c",ch);
- ch = getchar()返回值是ch
printf("%c",(ch = getchar())); // 返回字符ch,而非true或false
demo(1) 单词转换
// 用getchar()和putchar()完成转换
#include <stdio.h>
#define SPACE ' '
int main(void)
{
char ch;
ch = getchar(); // 可以改成scanf_s("%c",&ch), 不影响运行
while (ch != '\n')
{
if (ch == SPACE)
putchar(ch);
else
putchar(ch + 1);
ch = getchar(); // 从队列中读取下一个字符, 可以改成scanf_s("%c", &ch);
}
putchar(ch);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMJVgmUS-1665884393512)(C:\Typora\imgs\Snipaste_2022-09-21_12-43-50.png)]
demo(2) 单词统计
// 注意:这里单词包括了换行符
#include <stdio.h>
#define END '|';
int main(void)
{
char a;
int words = 0;
// scanf_s("%c", &a);
a = getchar();
while (a != '|')
{
words++;
// scanf_s("%c", &a);
a = getchar();
}
printf("%d", words);
}
7.2 ctype.h头文件
7.2.1 函数-isalpha(xxx)
- 返回boolean类型数据
#include<stdio.h>
#include<ctype.h>
int main(void)
{
char ch;
ch = getchar();
while (ch != '\n')
{
if (isalpha(ch))
{
ch += 1;
putchar(ch);
}
else
putchar(ch);
ch = getchar();
}
}
7.2.2 其它函数(p156)
isalnum() | 字母或数字 | isalpha | 字母 |
---|---|---|---|
isblank() | 空白字符(空格、水平制表符、换行符) | isdigit | 数字 |
… | … | … | … |
7.3 逻辑运算符(&&、||、!)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wXabrRKE-1665884393513)(C:\Typora\imgs\Snipaste_2022-10-05_23-03-01.png)]
7.3.1 iso646.h头文件
- 可以用and替代&&,or替代||,not替代!
if (ch != 1 and ch != 2);
if (ch != 1 && ch != 2);
if (range >= 10 && range <= 100);
if (10 <= range <= 100); // 错误写法
7.4 条件运算符(?)
max = (a > b) ? a : b;
#include <stdio.h>
#define COVERAGE 350 // square feet per paint can
int main(void)
{
int sq_feet;
int cans;
printf("Enter number of square feet to be painted:\n");
while (scanf_s("%d", &sq_feet) == 1)
{
cans = sq_feet / COVERAGE;
cans += ((sq_feet % COVERAGE == 0)) ? 0 : 1;
printf("You need %d %s of paint.\n", cans,
cans == 1 ? "can" : "cans");
printf("Enter next value (q to quit):\n");
}
return 0;
}
7.5 continue、break和switch
和java的语法和意义一样,放上三四个案例demo
(1) continue语句
#include <stdio.h>
int main(void)
{
const float MIN = 0.0f;
const float MAX = 100.0f;
float score;
float total = 0.0f;
int n = 0;
float min = MAX;
float max = MIN;
printf("Enter the first score (q to quit): ");
while (scanf("%f", &score) == 1)
{
if (score < MIN || score > MAX)
{
printf("%0.1f is an invalid value. Try again: ",
score);
continue; // jumps to while loop test condition
}
printf("Accepting %0.1f:\n", score);
min = (score < min)? score: min;
max = (score > max)? score: max;
total += score;
n++;
printf("Enter next score (q to quit): ");
}
if (n > 0)
{
printf("Average of %d scores is %0.1f.\n", n, total / n);
printf("Low = %0.1f, high = %0.1f\n", min, max);
}
else
printf("No valid scores were entered.\n");
return 0;
}
(2) break语句
#include <stdio.h>
int main(void)
{
float length, width;
printf("Enter the length of the rectangle:\n");
while (scanf("%f", &length) == 1)
{
printf("Length = %0.2f:\n", length);
printf("Enter its width:\n");
if (scanf("%f", &width) != 1)
break;
printf("Width = %0.2f:\n", width);
printf("Area = %0.2f:\n", length * width);
printf("Enter the length of the rectangle:\n");
}
printf("Done.\n");
return 0;
}
(3) switch语句
#include <stdio.h>
int main(void)
{
char ch;
while ((ch = getchar()) != '\n')
{
switch (ch)
{
case 'a': printf("这里是%c\n", ch); break;
case 'b': printf("这里是%c\n", ch); break;
case 'c': printf("这里是%c\n", ch); break;
default: printf("没有这个字符\n");
}
while (getchar() != '\n') // 如果输入多个字符,可以抛弃多余字符
continue;
}
}
- switch的多重标签
#include <stdio.h>
int main(void)
{
char ch;
int a_ct, e_ct, i_ct, o_ct, u_ct;
a_ct = e_ct = i_ct = o_ct = u_ct = 0;
printf("Enter some text; enter # to quit.\n");
while ((ch = getchar()) != '#')
{
switch (ch)
{
case 'a':
case 'A': a_ct++;
break;
case 'e':
case 'E': e_ct++;
break;
case 'i':
case 'I': i_ct++;
break;
case 'o':
case 'O': o_ct++;
break;
case 'u':
case 'U': u_ct++;
break;
default: break;
} // end of switch
} // while loop end
printf("number of vowels: A E I O U\n");
printf(" %4d %4d %4d %4d %4d\n",
a_ct, e_ct, i_ct, o_ct, u_ct);
return 0;
}
7.6 goto语句
在C上依然可以使用,但是建议“谨慎使用,或者根本不用”,这里不介绍了。