📄 c primer plus
字号:
{
float aboat = 32000.0;
double abet = 2.14e9;
long double dip = 5.32e-5;
printf("%e = %f\n", aboat, aboat); // 3.200000e+004 = 32000.000000
printf("%e = %f\n", abet, abet); // 2.140000e+009 = 2140000000.000000
printf("%e = %f\n", dip, dip); // 5.320000e-005 = 0.000053
return 0;
}
例2、浮点值溢出
#include <stdio.h>
int main(void)
{
float a;
a = 2.0e39; // 溢出
printf("%e = %f \n", a, a); // 1.#INF00e+000 = 1.#INF00
a = 2.0e38;
printf("%e = %f \n", a, a); // 2.000000e+038 = 199999993605713850000000000000000000000.000000
a = 2.0e15;
printf("%e = %f \n", a, a); // 2.000000e+015 = 1999999973982208.000000
a = 1.12345671111e12; // 1.123457e+012 = 1123456647168.000000
printf("%e = %f \n", a, a);
return 0;
}
例3、丢失部分数据
int cost = 12.99; // 实际cost只保存了12
float pi = 3.1415926536; // 实际pi只保存了3.121592,因为只有6位有效数字
例4、float与int同样32位,但解释出来的值绝然不同
#include <stdio.h>
int main(void)
{
float f = 256.0; // f的值为 256.0
void *p= &f;
int b = *(int*)p; // b的值变成 1132462080
printf("%d\n", b);
return 0;
}
5、复数和虚数类型
C99标准支持这两种类型:
复数类型:float_Complex、double_Complex、long double_Complex
虚数类型:float_Imaginary、double_Imaginary、long double_Imaginary
6、其他类型
C从基本类型衍生出其他类型,包括数组、指针、结构、联合。
第四章 字符串和格式化输入
scanf()、printf()
// talkback.c -- nosy, informative program
#include <stdio.h>
#include <string.h> // 提供strlen()函数的原型 for strlen() prototype
// 如果您使用的是ANSI C之前的编译器,可能不必包含 string.h,
// 或者ANSI之前的UNIX系统使用 strings.h
#define DENSITY 62.4 // 人的密度(单位是:英镑/每立方英尺) human density in lbs per cu ft
int main()
{
float weight, volume;
int size, letters;
char name[40]; // name是一个40个字符的数组 name is an array of 40 chars
printf("Hi! What's your first name?\n");
scanf("%s", name); // 输入名字。字符数组名name是指针,不必加&
printf("%s, what's your weight in pounds?\n", name);
scanf("%f", &weight); // 输入重量。&weight是指针,表示取变量weight的内存地址
size = sizeof name; // 数组name的长度是40
letters = strlen(name); // 取字符串长度
volume = weight / DENSITY;
printf("Well, %s, your volume is %2.2f cubic feet.\n", name, volume);
printf("Also, your first name has %d letters,\n", letters);
printf("and we have %d bytes to store it in.\n", size);
return 0;
}
/* praise2.c */
#include <stdio.h>
#include <string.h> /* provides strlen() prototype */
#define PRAISE "What a super marvelous name!" // PRAISE是字符串常量,最终由编译器将PRAISE替换成实际字符串
int main(void)
{
char name[40];
printf("What's your name?\n");
scanf("%s", name);
printf("Hello, %s. %s\n", name, PRAISE);
printf("Your name of %d letters occupies %d memory cells.\n",
strlen(name), sizeof name);
printf("The phrase of praise has %d letters ", strlen(PRAISE));
printf("and occupies %d memory cells.\n", sizeof PRAISE); // sizeof PRAISE 得出的字符串长度包括空字符'\0'
return 0;
}
1、C没有为字符串定义专门的变量类型,可用char数组存放字符串,以'\0'作字符串结束标记。
2、使用%s的scanf()时,遇到第一个空白字符(空格、Tab、换行符)处停止读取,即只读一个单词,需要处理整句可以使用gets()。
3、strlen()用于运行时计算字符串长度,以'\0'为结束;sizeof指示编译器在编译时就计算容量。
4、sizeof对变量或常量可用省去圆括号,但数据类型如char、int不能省。例如sizeof char是不对,正确写法 sizeof(char)。
5、sizeof 常量字符串 可得出字符串的长度,此长度包含空字符'\0'的1字节。
6、'X' 是字符,占1字节;"X" 是字符串,以'\0'结束,所以占2字节。
7、#define 定义常量,例如:
#define PI 3.14159
#define BEEP '\a'
#define TEE 'T'
#define ESC '\033'
#define OOPS "Now you have done it!"
另外,在limits.h中定义有INT_MAX、INT_MAX、CHAR_BIT等常量;在float.h中定义了DBL_DIG、FLT_MAX、DBL_MIN等常量。
8、const 定义常量,这是C90新增的关键字,可将一个变量声明转换成常量声明,例如:
const int MONTHS = 12; // MONTHS是一个只读值,运行时不能改变MONTHS值
9、printf()的转换说明符
%d、%i 有符号十进制数
%u 无符号十进制数
%o 无符号八进制数
%x、%X 无符号十六进制数字
%c 一个字符
%s 字符串
%p 指针
%a、%A 浮点数,十六进制数字和p-记数法(C99),p-notation
%e、%E 浮点数,e/E-记数法,e-notation
%f 浮点数,十进制记数法
%g、%G 自动选择%f或%e,其中%e是在指数小于-4或者大于等于精度时使用
printf()的修饰符
digit(s) 最小宽度,例如:"%4d"最小4个字符宽度,不够宽时自动增宽
.digit(s) 精度,例如:"%5.2f"只打印两位小数,"%.5s"只打印字符串的5个字符,"%.3d"整数不足3位则在前面加0
h 短整型,例如:"%hu"、"%hx"、"%6.4hd"
hh 表示 signed char 、 unsigned char 值,例如:"%hhu"、"%hhx"、"%6.4hhd"
j 表示一个 intmax_t 、 uintmax_t 值,例如:"%jd"、"%8jX"
l 表示 long int 、 unsigned long int 、double 值,例如:"%ld"、"%8lu"、"%lf"
ll 表示 long long int 、 unsigned long long int 值,例如:"%lld"、"%llu",(C99)
L 表示一个 long double 值,例如:"%Lf"、"%10.4Le"
t 表示一个 ptrdiff_t (两个指针的差)值,例如:"%td"、"%12ti",(C99)
z 表示一个 size_t (sizeof的返回值,无符号整型) 值,例如:"%zd"、"%12zx",(C99)
printf()的标志
- 左对齐,例如:"%-20s"
+ 显示正负符号,例如:"%+6.2f"
空格 有符号的值为正,则带前导空格(不带正号);若为负,则带减号。+标志会覆盖空格标志。例如:"% 6.2f"
# 例如:"%#o"八进制数前面加0、"%#x"十六进制数前面加0x、"%#8.0f"即使无数字也打印小数点、"%+#10.E"、"%#g"防止尾0被删除
0 前导0填充最小宽度,例如:"%010d"、"%08.3f"
10、pritnf()参数传递原理
/* floatcnv.c -- mismatched floating-point conversions */
#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); // 3.0e+000 3.0e+000 3.1e+046 4.2e-314
printf("%ld %ld\n", n3, n4); // 2000000000 1234567890
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4); // 0 1074266112 0 1074266112
return 0;
}
参数不匹配打印出的结果不正确,下面以最后一句printf()为例,说明参数传递原量:
(1) 调用printf()时,按参数的类型(如float),将参数值压入栈中
(2) printf()执行时,根据说明符(如%ld),从栈取出参数值
|-------|-
| | } 4字节
|-------|-
| |
|-------| <--- n4 (long int 8字节)
| |
%ld --> |-------| <--- n3 (long int 8字节)
| |
%ld --> |-------| <--- n2 (double 8字节)
| |
%ld --> |-------|
| |
%ld --> |-------| <--- n1 (float 4字节)
| |
|-------|
11、printf() 返回值:正常则返回打印的字符总数,出错则返回负数。
12、长字符串分行。
// 三种分行方式效果一样
/* longstrg.c -- printing long strings */
#include <stdio.h>
int main(void)
{
printf("Here's one way to print a ");
printf("long string.\n");
printf("Here's another way to print a \
long string.\n"); // 注意,左边空白字符也会计算在内
printf("Here's the newest way to print a "
"long string.\n"); /* ANSI C */
return 0;
}
13、scanf()输入
// input.c -- when to use &
#include <stdio.h>
int main(void)
{
int age; // 变量
float assets; // 变量
char pet[30]; // 字符串
printf("Enter your age, assets, and favorite pet.\n");
scanf("%d %f", &age, &assets); // 此处用&
scanf("%s", pet); // 对字符数组不需要使用&
printf("%d $%.2f %s\n", age, assets, pet);
return 0;
}
scanf()的转换说明符与printf()相似,主要区别在于
printf()把%f、%e、%E、%g、%G 同时用于float和double,
而scanf()只把它们用于float,对于double需要使用l修饰符。
scanf()的转换说明符
%c 输入一个字符
%d 输入一个十进制整数
%u 输入一个无符号十进制整数
%i 输入一个有符号十进制数
%x、%X 输入一个有符号十六进制数
%o 输入一个八进制数
%p 输入一个指针(一个地址)
%e、%f、%g、%a 输入一个浮点数(%a是C99新增的)
%E、%F、%G、%A 输入一个浮点数(%a是C99新增的)
%s 输入一个字符串,以输入的内容第一个非空白字符作为开始,直至下一个空白字符的作为结束,并添加'\0'给字符数组作结束标记
scanf()的修饰符
digit(s) 最大字段宽度,例如:"%10s"最多输入10个字符
d、i、o int
e、f、g float
hh "%hhd" 表示 signed char ;"%hhu" 表示 unsigned char
ll "%lld" 表示 long long ;"%llu" 表示 unsigned long long
h、l、L "hd"、"%hi" 表示 short int ;"%ho"、"%hx"、"hu" 表示 unsigned short int
"%ld"、"%li" 表示 long ;"%lo"、"lx"、"%lu" 表示 unsigned long
"%le"、"%lf"、"%lg" 表示 double ;"%Le"、"%Lf"、"%Lg" 表示 long double
14、scanf()按格式输入
(1) scanf("%d, %d", &n, &m);
输入方式1:
77, 100
输入方式2:
77, 100
输入方式3:
77,
100
(2) scanf("%d%d", &n, &m);
输入方式1:
77 100
输入方式2:
77
100
这两个语句结果都一样。
15、scanf()的返回值:
正常收返回成功读入的项目的个数;
输入错误则返回0;
到达文件结尾(end of file)时则返回EOF(EOF一般定义为-1)。
16、getchar()输入一个字符;putchar()输出一个字符;gets()输入一行字符串。
17、printf()和scanf()的*修饰符
/* varwid.c -- uses variable-width output field */
#include <stdio.h>
int main(void)
{
unsigned width, precision;
int number = 256;
double weight = 242.5;
printf("What field width?\n");
scanf("%d", &width);
printf("The number is :%*d:\n", width, number); // "%*d"中的*对应变量width
printf("Now enter a width and a precision:\n");
scanf("%d %d", &width, &precision);
printf("Weight = %*.*f\n", width, precision, weight); // "%*.*f"中的两个*分别对应变量wdith和precision
printf("Done!\n");
return 0;
}
/* skip2.c -- skips over first two integers of input */
#include <stdio.h>
int main(void)
{
int n;
printf("Please enter three integers:\n");
scanf("%*d %*d %d", &n); // 跳过前面两个整数,取第三个整给n
printf("The last integer was %d\n", n);
return 0;
}
输入、输出结果:
Please enter three integers:
1 2 3
The last integer was 3
18、使用scanf(),假设输入行:
-13.45e12# 0
对于%d,读到-13
对于%f,读到-13.45e12
对于%s,读到-13.45e12#
第五章 运算符、表达式和语句
1、计算机不能真正用整数除浮点数,是编译器将整数转化为浮点数,再除。
2、语句中有语句
int c, d;
int d = 6 + (c=3+8); // c被赋值为11,不建议这样使用
for(c=1, d=0; c<10; c++, d=d+2) // 逗号运算符
printf("%d,%d\n", c, d);
3、类型转换
类型转换从高到低顺序是:
long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int
short 和 char 可能被提升为 int 或 unsigned int
#include <stdio.h>
int main(void)
{
char ch;
int i;
float fl;
fl = i = ch = 'C'; // 自动升级转换:int --> float
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); // ch = C, i = 67, fl = 67.00
ch = ch + 1;
i = fl + 2 * ch; // 自动降级转换:float --> int
fl = 2.0 * ch + i; // 自动降级转换:double --> float
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); // ch = D, i = 203, fl = 339.00
ch = 5212205.17; // 自动降级转换:double --> char
printf("Now ch = %c\n", ch); // Now ch = -
i = 1.6 + 1.7; // 自动降级转换:double --> int
printf("i = %i\n", i); // i = 3
i = (int)1.6 + (int)1.7;// 强制转换
printf("i = %i\n", i); // i = 2
return 0;
}
4、运算符优先级
()
- + ++ -- sizeof 从右到左
* / %
+ -
< > <= >=
== !=
= 从右到左
第六章 C控制语句:循环
1、循环写法
initialize;
while(test)
{
body;
update;
}
initialize;
do
{
body;
update;
}
while(test);
for(initialize; test; update)
{
body;
}
2、循环举例
#include <stdio.h>
int main(void)
{
int i;
// while
i = 0;
while(i<=10)
{
printf("%d ", i);
i++;
}
printf("\n", i);
// do...while
i = 0;
do
{
printf("%d ", i);
i++;
}
while (i<=10);
printf("\n", i);
// for
for(i=0; i<=10; i++)
{
printf("%d ", i);
}
printf("\n", i);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -