《C程序设计语言第二版》第一章-导言(1.1--1.4)

1.1入门

/* stdio为standard input & output的缩写,意思是文件相关的标准输入/输出库,函数库就好比是一个工具库。

在C语言中(由于其与UNIX历史的关联),作为一个基本原则,键盘和显示器也被视为“文件”。事实上,键盘输入是默认的 stdin 文件流同时显示输出是默认的 stdout 文件流。

.h,表示库的头文件,就好比是它工具库门口的统计表,声明工具的存在和路径,工具库中的工具有很多种,输入输出工具,迭代器,string调用,取绝对值。
你需要什么工具来实现你的算法,先确定工具在哪个工具库(stdio.cpp)里,然后找到它门口的说明书(stdio.h),在你的代码里首先进行预编译,调用头文件(#include<stdio.h>)就相当于是向IDE(集成开发环境,Integrated Development Environment)出示了一份使用许可,允许你在接下来的过程中使用这个函数库里的函数(printf,scanf),使得编译器能找到他们。

include称为文件包含命令,其意义是把尖括号<>或引号"内指定的文件包含到本程序中,成为本
程序的亠部分。被包含的文件通常是由系统提供的。其扩展名为.h,表示文件库的头文件,还有一部分是自己编写的文件库头文件。 */

<stdlib.h>”包含了“内存分配/释放”函数的头信息。
在这里插入图片描述

/int 规定main函数返回值的类型为int,C语言中将声明变量类型写在最前面。
main是c程序的入口函数,也就是首先执行main函数。且main函数唯一,因为如果有多个,系统就找不到入口了。
int main(void)/int main() 这个整体表示main函数不接受任何参数;main函数接受参数则int main(int argc,char
argv[]) */
int main(void) {
printf(“Hello World\n”);
return 0; //return 0 代表程序正常退出。
}

/void main() 从来就不存在于C++或者C
在C和C++中,不接收任何参数也不返回任何信息的函数原型为“void foo(void);”。可能正是因为这个,所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void main(void) 或者是void main()。然而这是错误的!主函数main的返回值是由操作系统接受的,0代表成功,1代表失败。
所以main函数的返回值应该定义为int类型,没有返回值的main是非法的。C和C++标准中都是这样规定的。
虽然在一些编译器中,void main可以通过编译(如vc6),但并非所有编译器都支持void main,因为标准中从来没有定义过void main。g++3.2、dev C++等环境中如果main函数的返回值不是int类型,根本无法通过编译。而gcc3.2则会发出警告。所以,如果你想你的程序拥有很好的可移植性,请一定要用int main。只需要关注你的main函数需不需要参数。
/

/* return是C++预定义的语句,它提供了终止函数执行的一种方式。当return语句提供了一个值时,这个值就成为函数的返回值。
return语句用来结束循环,或返回一个函数的值。
① return -1::表示返回一个代数值,一般用在子函数结尾。按照程序开发的一般惯例,表示该函数失败;
② return 0,说明程序正常退出,返回到主程序继续往下执行。
③ return 1,说明程序异常退出,返回主调函数来处理,继续往下执行。
return 0 或 return 1 对程序执行的顺序没有影响,只是大家习惯于使用 return (0)
最好在main函数最后加上return 0,养成好习惯。 */

/*计算机语言分为描述性语言和编辑性语言

描述性语言就是类似java,python操作起来相对简单的语言,它的特点是结构清晰,可读性强,函数库全面,但是自定义性差,由c语言发展而来。

编辑性语言就是类似C,C++,汇编等比较原始的语言,你也可以理解为是描述性语言的底层内容,特点是原始,自定义性强,但是难度高,编辑复杂。像汇编这种语言,是从数据底层,考虑数据的处理了,举个例子C语言里的4*i只是个简单的乘法,但是其函数在汇编里需要几页代码才可以实现(因为汇编对数据的处理非常底层),但这不代表它是一种很低级的语言,在工业系统和操作系统的底层设计里非常重要。*/

#include <stdio.h>

int main(void)
{
    printf("hello,");
    printf("world");
    printf("\n");
    return 0;
}

/* 电路的逻辑只有0和1两个状态,这里的0和1并不是数字的0和1,0和1是表示两种不同的状态,0表示低电平,1表示高电平。因为计算机是由无数个逻辑电路组成的,只能根据0和1的无限位数和组合来表达信息。
电脑只认识0和1这两个数字,所有的数据在电脑中都是以带符号的以0和1组成的二进制编码方式存储的。比如“A”这个字母的二进制编码为01000001(这里区分十进制的整数即int类型的,A属于Char字符型数据),它所对应的十进制编码形式值为65。“+”号的二进制编码为00101100,对应的十进制编码形式值为43。
对于数字而言,在计算机中的二进制表示形式,即为数的机器数(>=8位二进制,且包括一位符号位)。

机器数一般是其补码。且在计算机的运算中,是以补码的形式进行加减法运算的。(此处涉及到自然舍弃、溢出,正溢出、负溢出,位宽扩大等。)
如用-32767-1来求-32768:
-1的补码为1111 1111 1111 1111
-32767的补码为1000 0000 0000 0001
所以加起来为:(1)1000 0000 0000 0000 (1)被自然舍去了,溢出。
即两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

计算机用补码进行运算的详细解释:
码狼时代——关于2的补码

对数字而言,十进制数本身的值,称为真值。当然真值可以是数字,也可以是字符如A、加号等。

对数字而言:
原码就是符号位加上真值的绝对值,即用第一位表示符号, 其余位表示值。正数的原码是二进制(>=8位)本身。
反码的表示方法是:正数的反码是其原码本身;负数的反码是在其原码的基础上,符号位不变,其余各个位取反。
补码的表示方法是:正数的补码就是其原码本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)

正数原码、反码、补码(机器数)的形式值等于其真值,负数原码、反码、补码(机器数)的形式值不等于其真值。
比如,十进制中的数+2,计算机字长即其机器数为8位,转换成二进制其原码就是[00000010],正数的补码是其原码本身,则其在计算机中的储存形式———补码为[00000010].
如果是-2 ,转换成二进制其原码就是 [10000010],该二进制的形式值为130;其反码是 [11111101],该二进制的形式值为253;其补码是[11111110],该二进制的形式值为254.均不等于其真值-2.

十进制数1对应的二进制数为1,补码为0000 0001
-1对应的补码为1000 0001(不带符号位的二进制只能表示十进制的0及正数。)
0对应的二进制数为0,机器数为0000 0000/1000 0000(-0=0),所以一般人为额外规定原码0000……的补码1000……表示某个数值。见下面的16位二进制取值范围的例子。

16位二进制本身的范围 :0000 0000 0000 0000 ~ 1111 1111 1111 1111,对应十进制中的0~65535(2^16-1)
对于n位二进制数本身,只能表示十进制的正数,且对应的十进制的取值范围为0~2^n-1.

在引入原码、反码、补码、机器数的概念之后(目的就是为了表示、运用、运算负数),对16位二进制 1111 1111 1111 1111而言,65535(2^16-1)变成了其形式值,其表示的真值是个负数。同样,对16位二进制1000 0000 0000 0000而言,32768(2^15)变成了其形式值,其表示的真值是个负数。

【根据补码求原码及真值的方法:
对正数而言,根据正数的原码、补码、反码均相同的规则,直接根据其补码求其真值即可;

对负数而言,必须先求出其原码,再求其真值。对十进制负数,根据其补码求原码及真值有下面两种方式:
如真值负数-10,4位二进制原码为:11010,反码为10101,补码为10110;
用该补码10110反推原码及真值:
方法一(待验证):根据二进制的运算规则,带补码符号位一起进行运算,减1得其反码,除符号位之外取反得其原码(即求补码的逆过程。)
减1得其反码10101,除符号位之外取反得其原码11010.与原原码相同,因此真值也必定相同。第一位是符号位,其余位为真值的绝对值,得出真值为-10;
方法二:无论正负数,补码的补码即为原码(注意与反码无关)。
补码10110的反码是11001,补码10110的补码是11010,可以看到该补码的补码是其原码,因此真值也必定相同。】

现在有两个16位二进制原码可以表示十进制真值中的0(十进制0用带符号位的16位二进制原码有两种表达方式),一个是+0:0000 0000 0000 0000,还有一个是-0:1000 0000 0000 0000.
它们两个的反码是:0111 1111 1111 1111,1111 1111 1111 1111
它们两个的补码是:1000 0000 0000 0000,1 0000 0000 0000 0000(因为限定是16位,最高位进位的1会被舍弃,计算机中表示/储存/显示的补码是0000 0000 0000 0000.)
但是有必要用两个去表示一个数吗?用1000 0000 0000 0000的补码0000 0000 0000 0000去表示0就好了嘛,用到0的地方就是0000 0000 0000 0000.
那这个0000 0000 0000 0000的补码1000 0000 0000 0000不能浪费了啊,总得表示一个数吧.
此时而在16计算机中-32768不能用原码表示出来,32768的二进制形式为1000 0000 0000 0000,加上符号位,会变成17位二进制11000 0000 0000 0000。
于是人为规定用0000 0000 0000 0000的补码1000 0000 0000 0000表示-32768.
因此在计算机中,16位二进制的范围,形式上仍然是 :0000 0000 0000 0000~1111 1111 1111 1111,但根据补码的表达方式,及对1000 0000 0000 0000等的人为额外规定,综合之后其对应的十进制取值范围是-215~215-1,即-32768 ~ +32767.保证了补码(对十进制数表示)的唯一性(如对十进制0的表示)和连续性(如对十进制-32768的表示)。(十进制数本身本就具备唯一性和连续性。)
【不过因为原码没有这种规定,因此16位整数的原码的范围只有:-32767~32767,而且对于十进制的0,仍然有两种原码表达方式。但原码、反码,在计算机中,都是不存在的,不必关心。】

对每一位数的二进制都做这样的规定,综合之后,对于有n位的二进制数,其对应的十进制最小值为-2^(n-1),最大值为 2(n-1)-1;可表示2n个十进制数。
最终,计算机中所有补码(对所有十进制数)的表示都是唯一且连续的。
如1 byte,1字节,1byte = 8bits,其二进制数共8位,即 0000 0000~1111 1111,其对应的十进制最小值为-27,最大值是27-1;可表示2^8个十进制数。

【2的14次方:16384
2的15次方:32768

二进制的位数从十进制的零开始取值,16位二进制的位数用十进制的数表示是从0,1,2,……,15.
当n位二进制数转化为十进制时,第一位乘以的是2(n-1),而不是2n,因此二进制的位数总比十进制范围二的次方多一位。
而又根据等比数列求和公式,最终留在公式中的是2n.因此n位二进制转化为十进制时,常出现的是2n-1,但次方仍然是n-1.】

2的7次方:128
2的8次方:256
2的9次方:512
2的15次方:32768
2的16次方:65536
2的31次方:2147483648
2的32次方:4294967296

1个字节(byte)等于8位(bit)二进制,1Byte = 8bits.
字节是计算机内部存储二进制数据的最小单位,即八位二进制形式,是计算机内部存储数据(数字,文字,符号等)的最小单位。

字符是字母、数字、运算符号、标点符号和其他符号,以及一些功能性符号的统称,是一种数据类型,英文简称是char(全称是character)。字符在计算机中也是以二进制的形式存在。

所有的数据类型都是用字节来度量大小。自然也是其中一种——字符的,即在32位系统中,一个字符存取时占用内存的大小是一个字节,即8个二进制。

从本质上来说,char字符数据类型也是一个整数(这里的整数是8位二进制的形式值,可能是十进制表示法中的一位,也可能是两位、三位),对应的十进制取值范围是:-27~27-1(-128 ~ +127).
这个整数(无论在十进制中是一位还是两位、三位)在32位系统的内存中均占据一个字节(8个二进制)(不要把十进制数占的大小与八位二进制占的内存大小混淆,后者一直为一个字节,无论对应的十进制位数是多少。)且该数值与ASCII码表相对应。
signed char unsigned char,取值范围: 0-2^8-1(0~255)

比如常用的ASCII码表的对应关系是:
十进制数字43(八位二进制编码的形式值)表示字符’+‘,二进制编码为00101011;
十进制数字48表示字符(十进制中的数字)‘0’,二进制编码为00110000;
十进制数字65表示字符’A’,二进制编码为01000001;
十进制数字97表示字符’a’,二进制编码为01100001
在这里插入图片描述
标准ASCII 码也叫基础ASCII码,使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符。(只能表示这些,无法表示颜色等。)

HEX(十六进制)在数学中是一种逢16进1的进制。
在使用二进制的地方基本都可以使用十六进制,有些地址空间使用二进制因位数太长不便记忆,所以很多场景使用HEX编码,例如颜色#000000表示黑色,#FFFFFF表示白色。
HEX编码(十六进制编码)就是使用数字 0-9 加上字母 A-F 一共16个字符表示的一种编码解码方式,其中 A-F 相当于十进制的10~15,总计16个,这些称作十六进制数字。

-----------------------------------------------分割线-----------------------------------------------------

【字符 和 字符串 的区别:
在C语言中,“字符”,如上所述,属于基本的数据类型的一种,为char,在32位系统中占用1个字节的存储空间。
①在字符常量两边,使用单引号作为定界符;
②定义时,用法同整形int;
③打印时,在printf函数中使用“%c”这个占位符。
在这里插入图片描述

而“字符串”,并不是基本数据类型,但可以通过char的数组代替,即除了前面的每个字符部分,在“字符串”的结尾处,自动被编译器加上了’\0’这个字符。在ASCII码中,'\0’表示的是一个空字符NULL.

(存储上,技术上,字符和字符串的区别就是是否在末尾处有‘\0’.)

字符串及char型数组的相同点及不同点:
相同点:在32位系统中均占用固定长度的连续空间(实际上就是数组的定义),多个字节。
定义时char型数组和字符串在形式上没有区别。

区别: 注意:字符串和char型数组并不是一回事。 字符串是一维的,char型数组是一维及一维以上的。 因此字符串一定是一个char型数组,但是char型数组不一定是字符串。
char型数组中的每个元素可以是字符串,叫做字符串数组,每个元素末尾处有‘\0’;也可以是单个字符,每个元素末尾处都没有‘\0’,叫做字符数组。

如果在定义一个字符串常量的时候,使用了单引号,程序就会报错。在定义字符串的时候,需要在变量名后面加上“中括号”,类似于定义“数组”时候的格式。

总结:
①在字符串和char型数组的常量两边,不管是几个字母,都使用双引号作为定界符(即使是单个字符,如下图);
②char型数组和字符串定义时在形式上没有区别。
尤其是定义字符串时,还是char类型,但使用的是char类型的一维字符串数组格式,即变量名称后加中括号“[ ]";(整个语句,包括等号后面的值,当作整体看。分开看没意义。)
③打印时,字符串在printf函数中使用“%s”这个占位符。
(对应string这个单词,虽然同char(character)一样有对应的英文名称,但却是char类型数组合末尾处的‘\0’组合形成的一种表达方式,因此字符串并不属于基本数据类型。)
char型数组打印时用%c,打印的是char型数组中的元素,即字符char.

在这里插入图片描述

也可以定义多个字符的字符串:char str[] = “abc”; 或者 const char * str = “abc” ;
在这里插入图片描述

int,整形, 8位二进制,一个字节byte的大小, [-128 : 127]
16位二进制,2个字节,十进制取值范围:-215~215-1(-32768 ~
+32767),可表示十进制2^16个(65536个)数,最多取5位十进制数; 32位二进制32bits,四字节4bytes,十进制取值范围:-231~231-1(-2147483648~2147483647),可表示十进制2^32个(4294967296个)数,最多取10位十进制数;
64位二进制,[-9223372036854775808 : 9223372036854775807]

对于除数字之外的char字符与整型int型
字符是用ASCII来表示的,因此字符char ‘A’ 和 十进制整形int数 65 ,在计算机中的二进制编码是一样的,即: char x=‘a’; 和 int x=65 在计算机中的二进制编码是完全一样的。
在显示的时候,你就可以决定是显示65(%d) 还是显示 ‘A’(%c).

对于十进制数字0-9
char型字符共计128个,十进制数字只存放了0-9,没有负值。
十进制正数0-9,可以整型int型,也可以是字符型char型。
char型十进制正数0-9,在内存中是以其ASCII码存放的,但是在计算机中的二进制编码,与整型int型是不一样的。
如char型十进制数字6,在计算机中的二进制编码,对应其ASCII码是00110110;
而整型int型十进制数字6,在计算机中的二进制编码是根据十进制与二进制的转换之后,取原码的补码。十进制数字6的原码是00000110,在计算机中的二进制编码补码为00000110,与char型十进制数字6在计算机中的二进制编码是不同的.
对十进制正数0-9,char型可以和int型进行运算。

对于字符串
根据字符串的存储方式,int类型的数组也完全能够用来存放字符串,但这样做没有意义,我们存储数据是为了访问和使用,用int类型的数组来存放字符串,如果有除数字之外的字母、特殊字符则无法访问!

unsigned int,缩写UInt,无符号整型, 16位,取值范围0 ~ 65535 32位,取值范围0~4294967295

short int,短整型,16位,取值范围-32768~32767 unsigned short/unsigned short
int无符号短整型,16位,取值范围0~65535

long int,缩写long,长整型,32位,取值范围-2147483648~2147483647 unsigned long
0~4294967295

long long,超长整数类型;长长整型。 long long的最大值:9223372036854775807 long
long的最小值:-9223372036854775808 unsigned long long
0~18446744073709551615

float单精度浮点型,占4字节(32位)内存空间,整数部分和小数部分一共的有效数字为6~7位,其数值范围为(约等于之后):-3.4 x
10^(-38)~ 3.4 x 10^(+38) (-3.4E38~3.4E+38); double
双精度浮点型,占8个字节(64位)内存空间,整数部分和小数部分一共的有效数字为15~16位,其数值范围为(约等于之后):-1.7 x
10^(-308)~ 1.7 x 10^(+308) (-179769313486232E308~79769313486232E308);
long
double,占16个字节(128位)内存空间,整数部分和小数部分一共的有效数字为18~19位,其数值范围为(约等于之后):-1.210(-4932)~1.210(4932).

-----------------------------------------------分割线-----------------------------------------------------

C语言中数组长度的计算方法总结(sizeof与strlen)

求数组长度

strlen是用来求一个字符串(string)的长度,因此strlen不能用来求int类型的数组长度,只能求char类型的数字长度。

char arr6[] = "abc";//没有定义元素个数,用双引号定义3个字符,末尾数组会自动加上结束标志(\0)
printf("length arr6 = %d\n", strlen(arr6));
//3

char arr7[10] = "abc";//定义10个元素个数,用双引号赋值三个字符串,其余7个元素均自动定义为\0
printf("length arr7 = %d\n", strlen(arr7));
//3
/* 从arr6和arr7中可以看出,用双引号定义的字符串数组都能正确计算出数组长度。
这是因为这两个数组的****末尾都含有结束标志"\0" */


char arr8[10] = { 'a', 'b', 'c' };//定义10个元素个数,用大括号和单引号赋值三个字符串,则数组只含有三个字符,剩余7个均为\0
printf("length arr8 = %d\n", strlen(arr8));
//3

char arr9[10] = { 'a', 98, '98' };//char定义数组,元素中出现没有用单引号的数字,会根据ASCII码输出字符
printf("length arr9 = %d\n", strlen(arr9));
//3

char arr10[] = { 'a', 'b', 'c' };//没有定义元素个数,用大括号定义字符串,数组的元素个数则只有三个,结尾没有数组结束标志(\0)
printf("length arr10 = %d\n", strlen(arr10));
//15

另外要注意的是,arr10输入了三个字符,但结果却是15个,
这是因为在没有定义数组个数的时候,用大括号的形式赋值,结尾不会自动补充结束标志\0,导致这个结果是个随机数,strlen会在内存中一直计数,知道在内存中遇到了0才会停止计数。
但是对比arr8和arr9,也是用了大括号赋值,结果却是正确的,这是因为开始定义了数组的个数,没有初始化赋值的数组会默认赋值为0(与\0有一样的效果)。

如果用strlen用来求int类型数组的长度,会发现strlen不能用了。

int arr1 [10] = {0};//定义了元素个数,且给第一个元素赋值为0,则其他元素均为0
printf("length arr1 = %d\n", strlen(arr1));
//0

int arr2 [10] = {1, 2, 3, 4, 5};//定义了元素个数,但只给前五个元素赋值,则后五个元素均为0
printf("length arr2 = %d\n", strlen(arr2));
//1

int arr4 [10];//什么都不放,编译器会给数组的每个元素放置随机数。
printf("length arr4 = %d\n", strlen(arr4));
//49

-----------------------------------------------分割线-----------------------------------------------------

sizeof能计算变量或者数据类型所占用的内存(以字节为单位)。用sizeof计算数组长度时,sizeof不关心数组内部存储的是什么类型的数据。
所以常常用 sizeof(arr)/sizeof(arr[0]) 来计算数组的长度。其中“sizeof(arr)“计算了整个数组arr占据了多少内存(字节为单位),”sizeof(arr[0])“计算了数组中第一个元素所占多少字节,两者相除就是数组的长度。

代码如下:

int arr1 [10] = {0};//定义了元素个数,且给第一个元素赋值为0,则其他元素均为0
int len1 = sizeof(arr1) / sizeof(arr1 [0]);
printf("length arr1 = %d\n", len1);  //10

int arr2 [10] = {1, 2, 3, 4, 5};//定义了元素个数,但只给前五个元素赋值,则后五个元素均为0
int len2 = sizeof(arr2) / sizeof(arr2 [0]);
printf("length arr2 = %d\n", len2);  //10

int arr3 [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//定义了元素个数,且给所有元素均赋值
int len3 = sizeof(arr3) / sizeof(arr3 [0]);
printf("length arr3 = %d\n", len3); //10

int arr4 [10];//什么都不放,编译器会给数组的每个元素放置随机数。
int len4 = sizeof(arr4) / sizeof(arr4 [0]);
printf("length arr4 = %d\n", len4); //10

int arr5[] = {1, 2, 3};//不定义元素个数,给几个元素赋值就有几个元素。
int len5 = sizeof(arr5) / sizeof(arr5 [0]);
printf("length arr5 = %d\n", len5); //3

从arr1、2、4可以看出,如果你一开始就定义了数组的大小,那么不管你插入多少个元素,sizeof求出来的结果永远是你定义的数组大小。

如果你没有定义数组大小,那么算出来的就是你实际赋值的数组大小。

char arr6 [] = "abc";//没有定义元素个数,用双引号定义3个字符,末尾数组会自动加上结束标志(\0)
int len6 = sizeof(arr6) / sizeof(arr6 [0]);
printf("length arr6 = %d\n", len6); //4
/* 从arr6可以看出,当用sizeof求char类型数组的长度时,
如果你没有定义数组长度,那么得出的结果会比实际大小大1。
这是因为sizeof吧数组结尾的\0也算了进去。*/

char arr7 [10] = "abc";//定义10个元素个数,用双引号赋值三个字符串,其余7个元素均自动定义为\0
int len7 = sizeof(arr7) / sizeof(arr7 [0]);
printf("length arr7 = %d\n", len7); //10

char arr8 [10] = {'a', 'b', 'c'};//定义10个元素个数,用大括号和单引号赋值三个字符串,则数组只含有三个字符,剩余7个均为\0
int len8 = sizeof(arr8) / sizeof(arr8 [0]);
printf("length arr8 = %d\n", len8);  //10
/* 从arr7和arr8可以看出,如果定义了数组大小,跟int类型一样,
不管怎么定义,定义了多少,结果都是你定义的那个数组大小。*/

char arr10 [] = {'a', 'b', 'c'};//没有定义元素个数,用大括号定义字符串,数组的元素个数则只有三个,结尾没有数组结束标志(\0)
int len10 = sizeof(arr10) / sizeof(arr10 [0]);
printf("length arr10 = %d\n", len10);  //3
/*  从arr10可以看出,如果你输入数组时用了大括号赋值,
并且在结尾没有手动输入\0,那么算出的结果就是实际赋值的个数。 */

总结:

  1. 定义数组时,要先明确数组的类型(int还是char或者其他类型)。
  2. sizeof不能用来计算已经定义好长度的数组的数组长度
    (如int arr[10] = {0},不能有中括号里的10)。
  3. strlen不能用来计算int类型的数组长度。
  4. 用sizeof函数来计算int型、char型数组arr长度时,最好用 sizeof(arr) / sizeof(arr[0]) 来计算数组长度。
    因为sizeof计算的是变量或者数据类型所占用的内存(以字节为单位),除以每个元 素所占的字节,才是数组的长度。
  5. char型数组如果要计算数组长度,一定要用双引号赋值。
  6. char型数组如果要用大括号赋值,一定要注意数组最后是否需要结束标志 \0.

-----------------------------------------------分割线-----------------------------------------------------

关于int型和char型 声明变量及输入输出:

正常情况下,ASCII码表中的128个字符:
33个字符无法显示(一些终端提供了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等8-bit符号)。且这33个字符多数都已是陈废的控制字符。控制字符的用途主要是用来操控已经处理过的文字。ASCII控制字符的编号范围是0-31和127(0x00-0x1F和0x7F),共33个字符。

95个是可显示的字符。用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。ASCII可显示字符在33到126之间(0x20-0x7E),共95个字符。

将变量c定义为char型,对输入的或赋给其的,超过256的int类型的数字,因为char只有8位,所以int类型的数字就会被截断,只保留后面8个2进制位,即305的二进制100110001就会变成(00110001),即49,相当于305 - 256.(在计算机内部进行的int类型的数字以补码的方式显示及其运算此处被忽略,只为了说明可见的十进制数字输入和输出结果。)

因此,声明变量的数据类型时遵循以下规则:
(1)一位或两位数字的,定义为char和int类型的均可;
(2)三位及三位以上数字的(具体是大于127的),定义为int类型; (小数的即用小数的数据类型。)
当给声明为char型的变量传入十进制数字时, 此时输出的情况:
当小于等于127时:
在printf函数中使用“%c”这个占位符,输出该十进制数字对应的ASCII字符;
在这里插入图片描述
在printf函数中使用“%d”这个占位符,正常输出数字,正常输出值。
在这里插入图片描述
当大于127时:
在printf函数中使用“%c”这个占位符,输出规则未知
在这里插入图片描述
在printf函数中使用“%d”这个占位符,输出该值减去256的值(可以为负值)。即发生截断,只输出截断256后的值。例子如下:

# include <stdio.h>

int main() {
	char i;

	i = 370;  
	printf("%d", i);  
	return 0;
}

输出结果为114(370-256)
在这里插入图片描述

# include <stdio.h>

int main() {
int i = 305;
char c;

c = i;  //令c的值为305
i = c;  //令i的值为305
printf("%d", i);  //输出结果为49. 因为char型变量无法正确传输超过256的数字。当传输给int型变量i时,只输出截断256后的那部分。
return 0;
}

在这里插入图片描述

(3)多维的数字,不管位数多少,定义为int型数组;
(4)一个字母,定义为char类型或int类型均可;
【char型一般占一个字节,int型一般占4个字节,int型占用的储存空间比char型大。
当给声明为int型的变量传入一个字母时,计算机自动读取传入字母的ASCII二进制编码进行处理,输出时,要在printf函数中使用“%c”这个占位符。若使用“%d”这个占位符,则输出该字符的ASCII十进制数字。
在这里插入图片描述
在这里插入图片描述
(5)两个及两个以上字母,定义为字符串(一维char型数组)的类型。
【当在程序中以一个字母一个字母的方式处理时,如仅包含getchar函数,putchar函数时,同(4)定义为char类型或int类型均可。
【在计算机中,数字0-127与ASCII中的128个字符是一样的,输出时通过指定printf函数中“%c”/“%d”的占位符,输出十进制数字/字母或字符;
而函数putchar()输出的内容与函数getchar()接受的,即与键盘输入的内容始终保持一致,无需像printf函数一样,通过指定占位符决定输出的内容。 】
(6)多维字符的,不管位数多少,定义为char型数组。

基本数据类型之间的数组、结构、联合。 */

1.2变量与算数表达式

# include <stdio.h>

/* 当fahr=0,20,……,300时,分别打印华氏温度与摄氏温度对照表 */

int main()
{
int fahr,celsius;
int lower,upper,step;

lower = 0; /* 温度表的下限 */
upper = 300; /* 温度表的上限 */ 
step = 20; /* 步长 */

fahr = lower;
while(fahr <= upper){
    celsius = 5 * (fahr-32)/9;
    //写成先乘以5然后再除以9而不是直接写成5/9,是因为在C语言及许多其他语言中,整数除法操作将执行舍位,结果中的任何小数部分
    printf("%d\t%d\n",fahr,celsius);  
    fahr = fahr + step;
}
return 0;
}

printf(“%d\t%d\n”,fahr,celsius) 中:
① %表示其他参数即fahr、celsius之一进行替换的位置,并指定打印格式;
②%d合起来表示指定一个整型参数;
③%f表示%f是输出float(单精度浮点型)型变量;
%m.nf中m代表输出数长,n代表小数点后的数长,即保留n位小数。如果小数点后的数大于n,例如12.4567按照%5.2f输出得12.46(四舍五入),如果总位数大于m(小数只到两位),按照实际位数输出,例如111.4567按%5.2f输出,111.46(总数长6,注意小数点也算一位数字,占据一个数长);如果实际位数小于m,则要补齐空格,例如1.23按照%5.2f输出,_1.23(表示空格)(四位数长加空格一共五位);再来讨论小数小于n的情况,小数小于n空格补齐,例如23.1按照%5.2f输出,得到23.1(_表示空格)。综上,m多了不限制小数点前,n多了四舍五入,m、n少了空格补足;
④\t转义字符,输出tab键,这个tab键的宽度是自己设置的,一般为4或8;
⑤ \n输出回车换行。

#include <stdio.h>
/* 当fahr=0,20,……,300时,打印华氏温度和摄氏温度对照表;
  浮点数版本 */

int main()
{
    float fahr,celsius;
    int lower,upper,step;

    lower = 0;
    upper = 300;
    step = 20;

    fahr = lower;
    while(fahr <= upper){
        celsius = (5.0/9.0)*(fahr-32.0);
        printf("%3.0f %6.1f\n",fahr,celsius);
        fahr = fahr + step;
    }
return 0;
}
#include <stdio.h>

/* 浮点数版本 */

int main(){
    float celsius,fahr;
    int lower,upper,step;

    lower =  0;
    upper = 300;
    step = 20;

    fahr = lower;

    while(fahr <= upper){
        celsius = (5.0/9.0)*(fahr - 32.0);
        printf("%3.0f%8.2f\n",fahr,celsius);
        fahr = fahr + step;
    }
return 0;
}
# include <stdio.h>

/*摄氏温度celsius转华氏温度fahr的转换表*/

int main(){
    float celsius,fahr;
    int lower,upper,step;

    lower = -30;
    upper = 30;
    step = 2;

    celsius = lower;
     while(celsius <= upper){
        fahr = (9.0 * celsius)/5.0  + 32;
        printf("%3.0f%8.2f\n",celsius,fahr);
        celsius = celsius + step;
     }   
return 0;
    }

1.3 for语句

#include <stdio.h>

/* for 循环*/

int main(){

    int fahr;

    for(fahr = 0;fahr <= 300;fahr = fahr + 20)
 /*第一部分:初始化,仅在进入循环时执行一次;
 第二部分:条件。控制循环的测试或条件部分,若其值为真true,则首先执行一次循环体(下面的部分);
 第三部分:增长步长。在对第二部分求值并执行一次循环体之后,根据第三部分的命令对循环变量进行相应处理。
 处理之后先不直接执行循环体,而是再次对第二部分条件进行求值,若其值为真true,则才再执行一次循环体;若其值为false,循环将终止执行。*/
        printf("%3d %6.1f\n",fahr,(5.0/9.0)*(fahr-32));   //for语句的循环体。
    return 0;
}
/* %3d 与 %3.0f 的结果差距很大,
应该是%3d,因为上面已声明变量fahr为int型。区别前面while循环浮点型中,提前声明fahr为float型。 
过程中是如何运算的,与输出的结果及对结果的定义没有关系。前者是系统,后者是自定义。  */






```c
#include "stdio.h"

/*温度的逆序展示。*/

int main(){
    int fahr;

    for(fahr = 300;fahr >= 0;fahr = fahr-20)
        printf("%3d %8.2f\n",fahr,(5.0/9.0)*(fahr - 32.0));
    return 0;
}
/* 这里的%3d和上面的情况相同 。 */

1.4 符号常量

# include <stdio.h>

#define LOWER 0 /*表的下限 */
#define UPPER 300 /*表的上限 */
#define STEP 20  /*步长 */
 /* 打印华氏温度-摄氏温度对照表 */ 
 int main()
 {
     int fahr;

     for(fahr=LOWER;fahr<=UPPER;fahr=fahr+STEP)
         printf("%3d %6.2f\n",fahr,(5.0/9.0)*(fahr-32.0));
    return 0;
 } 

/* for循环中是分号;
printf()中是逗号;
每个句子结尾,除for语句和define语句之外,是分号。 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值