编程类型解析
//给定不超过6的正整数A,考虑从A开始的连续4个数字。请输出所有由它们组成的无重复数字的3位数
//输出格式:满足条件的3位数,要求从大到小,每行6个整数,整数间以空格分隔,但行末不能有多余空格
intmain()
{
inta;
scanf("%d",&a);
inti,j,k;
intcnt=0;
i=a;
while( i<=a+3){
j=a;
while( j<=a+3){
k=a;
while( k<=a+3){
if( i!=j ){
if( i!=k ){
if( j!=k){
cnt++;
printf("%d%d%d",i,j,k);
if( cnt==6){
printf("\n");
cnt=0;
}else{
printf(" ");
}
}
}
}
k++;
}
j++;
}
i++;
}
return0;
}
#include
intmain() {
intn;
//scanf("%d", &n);
n=3;
intfirst=1;
inti=1;
while(i<n){
first*=10;
i++;
}
//printf("first=%d\n", first);
//遍历100-999
i=first;
while(i<first*10){
//需要一个临时的变量去记录 i
intt=i;
//需要一个"和"去记录每一位数的 n次幂
intsum=0;
do {
intd=t%10;
t/=10;
//d^2 = d*d; d^3 = d*d*d;
/*
int p = 1;
int j = 0;
while(j < n){
p *= d;
j++;
}
//或者*/
intp=d;
intj=1;
while(j<n){
p*=d;
j++;
}
sum+=p;
} while(t>0);
if (sum==i) {
printf("%d\n", i);
}
i++;
}
return0;
}
#include
intmain() {
intn;
//scanf("%d", &n);
n=9;
inti,j;
i=1;
while( i<=n) {
j=1;
while(j<=i){
printf("%d*%d=%d", j,i,i*j);
//i,j会输出9*1= 9*2=
//我们想要输出1*9= 2*9=
//如果i*j小于10,比如1*1=1 小于 10
if( i*j<10){
//输出三个空格
printf(" ");
} else {
//输出两个空格
printf(" ");
}
j++;
}
//还需要在每一个行加个回车
printf("\n");
i++;
}
return0;
}
#include
intmain() {
intm,n;
inti;
//个数
intcnt=0;
intsum=0;
scanf("%d %d", &m, &n);
//如果m是 1,单独做一个特殊的判断
if(m==1)
m=2;
for(i=m; i<=n; i++){
intisPrime=1;
intk;
//需要有另外一个循环去证明 i是不是isPrime
for(k=2; k<i-1; k++){
if(i%k==0){
isPrime=0;
break;
}
}
// 判断 i 是否素数
if(isPrime) {
cnt++;
sum+=i;
}
}
printf("%d %d\n", cnt, sum);
return0;
}
#include
intmain(){
//随机数,猜测的最大次数
intnumber,n;
//用户每次猜测的数字
intinp;
// finished为 1 则表示猜中,0 没猜中
intfinished=0;
// 记录猜测次数
intcnt=0;
scanf("%d %d",&number,&n);
while(scanf("%d",&inp)){
cnt++;
//如果这个数小于0 或 猜测次数大于最大猜测次数 ,则输入不合法
if(inp<0||cnt>n){
printf("Game Over\n");
break;
}
// 输入猜测数太大
if(inp>number){
printf("Too big\n");
// 输入猜测数太小
}elseif(inp<number){
printf("Too small\n");
// 输入猜测数与随机数相等
}else{
// 1次成功
if(cnt==1){
printf("Bingo!\n");
// 3次以内成功
}elseif(cnt<=3){
printf("Lucky You!\n");
// 3次以上成功
}else{
printf("Good Guess!\n");
}
finished=1;
if(finished==1) break;
}
}
return0;
}
#include
intmain() {
intn;
//分子,分母
doubledividend,divisor;
doublesum=0.0;
inti;
doublet;
scanf("%d", &n);
// n = 2000;
dividend=2;
divisor=1;
for(i=1; i<=n; i++){
sum+=dividend/divisor;
t=dividend;
dividend=dividend+divisor;
divisor=t;
}
printf("%.2f\n", sum);
return0;
}
#include
intmain() {
//分子,分母
intdividend,divisor;
scanf("%d/%d", ÷nd, &divisor);
inta=dividend;
intb=divisor;
intt;
//辗转相除法算出最大公约数
while(b>0){
t=a%b;
a=b;
b=t;
}
printf("%d/%d\n", dividend/a, divisor/a);
return0;
}
#include
intmain() {
intx;
scanf("%d", &x);
if(x<0){
printf("fu ");
x=-x;
}
intmask=1;
intt=x;
//辗转相除法算出最大公约数
while(t>9){
t/=10;
mask*=10;
}
do{
intd=x/mask;
switch(d){
case0: printf("ling"); break;
case1: printf("yi"); break;
case2: printf("er"); break;
case3: printf("san"); break;
case4: printf("si"); break;
case5: printf("wu"); break;
case6: printf("liu"); break;
case7: printf("qi"); break;
case8: printf("ba"); break;
case9: printf("jiu"); break;
}
// 最后不要有行末的空格
if (mask>9) printf(" ");
x%=mask;
mask/=10;
} while(mask>0);
printf("\n");
return0;
}
#include
intmain() {
inta,n;
scanf("%d %d", &a, &n);
intsum=0;
inti;
//每一轮的数字
intt=0;
// 0*10+2 2*10+2 (2*10+2)*10+2
for(i=0; i<n; i++){
t=t*10+a;
sum+=t;
}
printf("%d\n", sum);
return0;
}
C语言的类型
整数
- char:一字节(8比特)-128至127
- short:2字节 -32768至32767
- int:取决于编译器(CPU),通常的意义都是"1个字"
- long:取决于编译器(CPU),通常的意义是"1个字"(4或8字节)
- long long:8字节
*整数的内部表达
- 计算机内部一切都是二进制
- 18 -> 00010010
- 0 -> 00000000
- -18 ->?
*如何表示负数
- 十进制用"-"来表示负数,在做计算的时候
- 加减是做相反的运算
- 乘除时当作正数,计算完毕后对结果的符号取反
*二进制负数
- 1个字节可以表达的数:0000 0000 - 1111 1111(0-255)
三种方案:
- 仿照十进制,有一个特殊的标志表示负数
- 取中间的数为0,如100 0000表示0,比它小的是负数,比它大的是正数
- 补码(实际上使用的,方案1和2都有缺陷)
*补码
补码的意义就是拿补码和原码可以加出一个溢出的0
例子:因为0 - 1->-1,所以-1 = (1)0000 0000 - 0000 0001 ->1111 1111
1111 1111被当作纯二进制看待时,是255,被当作补码看待时是-1
同理,对于-a,其补码就是0-a,实际是2的n次方-a,n是这种类型的位数
数的范围
- 对于一个字节(8位),可以表达的是:0000 0000 ->1111 1111
- 其中0000 0000->0 、1111 1111至1000 0000 ->-1至-128 、 0000 0001至0111 1111->1至127
浮点数
float、double、long double
逻辑
bool
指针
自定义类型
类型有何不同
- 类型名称:int、long、double
- 输入输出时的格式化:%d、%ld、%lf
- 所表达的数的范围:char
- 内存中所占据的大小:1个字节到16个字节
- 内存中的表达形式:二进制数(补码)、编码
sizeof
- 是一个运算符,给出某个类型或者变量在内存中所占据的字节数
例如:sizeof(int)、size(i)
- 是静态运算符,它的结果在编译时刻就决定了
- 不要在sizeof的括号里做运算,这些运算不会进行的
unsigned
- 在整形类型前加上unsigned使得它们变成无符号的整数
- 内部的二进制表达没变,变的是如何看待它们。如何输出
- 1111 1111对于char来说是-1,对于unsigned char来说是255
- 如果一个字面量常数想要表达自己是unsigned,可以在后面加上U或者u,255U
- 用L或者l表示long( long)
- unsigned初衷并非扩展数能表达的范围,而是为了做纯二进制运算,主要是为了移位
整数越界
整数是以纯二进制方式进行计算的,所以:
- 1111 1111+1 -> 1 0000 0000 ->0
- 0111 1111+1 -> 1 0000 0000 ->-128
- 1000 0000-1 -> 0111 1111 ->127
整数的输入输出
只有两种形式:int或者long long
- %d:int
- %u:unsigned
- %ld:long long
- %lu:unsigned long long
8进制和16进制
- 一个以0开始的数字字面量是8进制
- 一个以0x开始的数字字面量是16进制
- %o用于8进制,%x用于16进制
- 8进制跟16进制只是如何把数字表达为字符串,与内部如何表达数字无关
- 16进制很适合表达二进制数据,因为4位二进制正好是一个16进制位
- 8进制的一位数字正好表达3位二进制
- 因为早期计算机的字长是12的倍数,而非8
选择整数类型
- 为什么整数要有那么多种?为了准确表达内存,做底层程序的需要
- 没有特殊需要就选择int
- 现在CPU的字长普遍是32位或者64位,一次内存读写就是一个int,一次计算也是一个int,选择更短的类型不会更快,甚至可能更慢
- 现代的编译器一般会设计内存对齐,所以更短的类型实际在内存中有可能也占据一个int的大小(虽然sizeof告诉你更小)
- unsigned与否只是输出的不同,内部计算是一样的
浮点数
浮点类型
类型 | 字长 | 范围 | 有效数字 |
float | 32 | 正负(1.20×100,正负inf,NaN) | 7 |
double | 64 | 正负(2.20×100,正负inf,NaN) | 15 |
浮点的输入输出
类型 | scanf | printf |
float | %f | %f,%e |
double | %lf | %f,%e |
科学计数法
- 可选的+或者-符号
- 可以用e或者E
- 整个词不能有空格
- 小数点也是可选的
- 符号可以是正负也可以省略(表示+)
- 例如:-5.67E+16
输出精度
在%和f之间加上.n可以指定输出小数点后几位,这样的输出是做四舍五入的
- printf("%.3f\n",-0.0049);
- printf("%.30f\n",-0.0049);
- printf("%.3f\n",-0.00 49);
超出范围的浮点数
- printf输出inf表示超过范围的浮点数:+无穷
- printf输出nan表示不存在的浮点数
浮点运算的精度
- 带小数点的字面量是double而非float
- float需要用f或者F后缀来表明身份
浮点数的内部表达
- 浮点数在计算时是由专用的硬件部件实现的
- 计算double和float所用的部件是一样的
选择浮点类型
- 如果没有特殊需要,只使用double
- 现代CPU能直接对double做硬件运算,性能不会比float差,在64位的机器上,数据存储的速度也不比float慢
字符
字符类型
char是一种整数,也是一种特殊的类型:字符。这是因为:
- 用单引号表示的字符字面量:'a','1'
- "也是一个字符
- printf和scanf里用%c来输入输出字符
字符的输入输出
- 如何输入'1'这个字符给char c?
scanf("%c",&c);->1
scanf("%d",&i);c=i ;->49
- '1'的ASCII编码是49,所以当c==49时,它代表'1'
- 这是一个49的各自表述
混合输入
有何不同
scanf("%d %c",&i,&c);
scanf("%d%c",&i,&c);
字符计算
- 一个字符加一个数字得到ASCII码表中那个数之后的字符
- 两个字符的减,得到它们在表中的距离
大小写转化
- 字母在ASCII表中是顺序排列的
- 大写字母和小写字母是分开排列的,并不在一起
- ‘a’-‘A’可以得到两段之间的距离,于是a+‘a’-‘A’可以把一个大写字母变成小写字母,反之把这个运算中的‘a’与‘A’互相调换即可把一个小写字母变成大写字母
逃逸字符
用来表达无法印出来的控制字符或特殊字,在那些具有特殊符号的前面加上\即可将其当作普通字符使用
字符 | 意义 |
\b | 回退一格 |
\t | 到下一个表格位 |
\n | 换行 |
\r | 回车 |
" | 双引号 |
' | 单引号 |
\ | 反斜杠本身 |
制表位
- 每行的固定位置
- 一个\t使得输出从下一个制表位开始
- 用\t能使上下两行对齐
逻辑类型
bool
- 在宏定义中加上#include
- 之后就可以使用bool和true跟false
bool的运算
- bool实际上还是以int的手段实现的,所以可以当作int来计算
- 也只能当作int来输入输出
类型转换
自动类型转换
- 当运算符的两边出现不一致的类型时,会自动转换成较大的类型
- 大的意思是能表达的数的范围更大
- char->short->int->long->long long
- int->float->double
- 对于printf,任何小于int的类型会被转化成int;float会被转换成double
- 但是scanf不会,要输入short,需要%hd
强制类型转换
- 要把一个量强制转换成另一个类型(通常是较小的类型),需要:(类型)值
- 比如(int)10.2 (short)32
- 需要注意这个时候的安全性,小的变量不总能表达大的量
- 这个只是从那个变量计算出了一个新的类型的值,它并不改变那个变量,无论值还是类型都不改变
- 强制类型转换的优先级高于四则运算
有些运算
逻辑运算
- 逻辑运算是对逻辑量进行的运算,结果只有0或者1
- 逻辑量是关系运算或逻辑运算的结果
运算符 | 描述 | 示例 | 结果 |
! | 逻辑非 | !a | 如果a是true结果就是false如果a是fasle结果就是true |
&& | 逻辑与 | a&&b | 如果a和b都是是true结果就是true否则就是false |
|| | 逻辑或 | a||b | 如果a和b有一个是true结果就是true两个都是false,结果才是false |
try(尝试)
如何判断一个字符c是否是大写字母?
c >= ‘A’&&c<=‘Z’
逻辑优先级
!>&&>||
总体优先级排名
优先级 | 运算符 | 结合性 |
1 | () | 从左到右 |
2 | !+- ++ -- | 从右到左(单目的+和-) |
3 | / % | 从左到右 |
4 | + - | 从左到右 |
5 | < <= > >= | 从左到右 |
6 | == != | 从左到右 |
7 | && | 从左到右 |
8 | || | 从左到右 |
9 | = += -= *= /= %= | 从右到左 |
短路
- 逻辑运算是自左向右进行的,如果左边的结果已经能够决定结果了,就不会做右边的计算了
- 对于&&,左边是false时就不会做右边的运算了
- 对于||,左边是true时就不会做右边的运算了
- 不要把赋值,包括复合赋值组合进表达式
条件运算符
- count = (count>20)?count-10:count+10;
- 当count>20是真的时候执行前者,是假执行后者
- 优先级:条件运算符的优先级高于赋值运算符,但是低于其他运算符
- 不要嵌套条件表达式(很容易出问题)
逗号运算符
- 逗号用来连接两个表达式,并以其右边的表达式的值作为它的结果。逗号的优先级是所有运算符中最低的,所以它两边的表达式会先计算;逗号的组合关系是自左像右,所以左边的表达式会先计算,而右边的表达式的值就留下来作为逗号运算的结果
- 比如在for中使用
- for(i = 1,j=8;i