C语言学习---(四)

无缓冲输入与缓冲输入:

某些交互式程序使用无缓冲输入,缓冲分为完全缓冲(文件输入)与行缓冲(键盘输入)

C处理文件的方式:

C语言可以通过直接调用主机操作系统的函数底层I/O处理文件,还可以通过标准I/O来处理文件,这涉及到一套标准I/O函数;

C语言处理的是而不是直接处理文件,这意味不同属性与不同种类的输入,由属性更统一的流来表示。打开文件过程就是把流与文件关联,读写都是通过流来完成。

C语言把输入和输出设备视为存储设备上的普通文件;

文件结尾识别:

一种以前是用内嵌 ctrl+z来标记文件结尾;

另一种是存储文件 大小 信息;

无论上述哪种方法,C语言用getchar()读取 文件结尾后会返回EOF,该值在stdio.h中宏定义过了;使用EOF是在程序中将getchar()与EOF其比较,相等则到了文件结尾

stdin流表示键盘输入,stdout流表示屏幕输出,sterr标准错误输出;

程序通过两种方式使用文件,一使用特定的函数,二重定向输入至文件和从文件输出;

重定向:

重定向就是将原本应该从标准输入设备(键盘)输入的数据,改由其他文件或设备输入,或将原本应该输出到标准输出设备(显示器)的内容,改由输出到其他文件或设备上

DOS/Windows的重定向运算符<使得右侧文件与stdin流相关联,重定向输出>,将文件内容导入左侧。
重定向必须一个是 可执行程序 一个是 数据文件,组合重定向必须一对一,不能读取多个文件输入或者输出;

注意:

C把文件和I/O设备放在一个层面;

操作系统有两大阵营,一边是基于微软 Windows NT 的操作系统,一边是由UNIX衍生下来的操作系统。DOS是微软在Windows前为个人电脑开发的计算机软硬件资源管理系统;

UNIX和Linux标准提示符$;Windows/DOS提示符A>或C>;

scanf()在读取数字时会跳过制表符、空格、换行符getchar()读取每个字符,制表符、空格、换行符;

逆序指的是前面大后面小;

pow()函数内的两个数必须都是double类型!!!(似乎隐形转换)

%求模运算必须针对整型!!!

重定向输出至某一文件夹时,若该文件之前已经存在,则通常会擦除该文件的内容;(但一般系统有保护现有文件的选项,使其成为只读。)

Micorsoft Visul Studio把可执行文件(扩展名.exe)放在项目文件夹的子文件夹,称为Debug;

%s是将输入解释成字符串,从第一个非空白字符开始,到下一个空白字符结束;

一些系统要求重定向运算符>、<,左侧要有空格,右侧没有空格;

break语句,出现在多层嵌套循环里面,会终止包含它的所有当前循环,但当break出现在循环体内;的switch语句内,起作用只是跳出该switch语句,并不能终止外层循环体的运行;太牛了!

题目中对输入有附加属性的要求时,一般可设置循环进行输入验证;

在一段程序中混合使用getchar()与scanf(),如果在调用getchat()之前,scanf()留下了换行符,则会导致一些问题,因此需要就行处理;(可以设置while循环判断scanf输入数值个数,丢弃换行符);

strlen()函数用于计算不包含结束位'\0'的字符串长度;

函数:

可以把函数看作是带有激励与响应的黑盒;

函数内部声明的变量、形参均属于局部变量,在程序其他地方使用时是同名的不同变量;

在函数声明、函数定义时最好带形参,形参名可省略,函数声明时,形参可以只写数据类型;

形参是被调函数中的局部变量,实参是主调函数赋给被调函数的具体值;

通过实参+函数调用,把信息从主调函数传递给被调函数,通过函数的返回值,把信息从被调函数返回给主调函数;等于说,函数返回值类型就是和函数定义时数据类型保持一致,不管函数内部是什么返回值类型;函数调用实参类型与函数原型不匹配,自动转换成函数原型;double转换成int可能会丢失数据;

return用在函数末尾,因为它会导致终止该函数,并把控制返回给主调函数。对于void类型的函数,可直接写return;

函数原型可以放在主调函数之内或外,只要放在调用该函数之前即可;

主调函数把它的参数存储在被称为 的临时存储区;

函数的返回值要与函数类型匹配。若不匹配会自动转换成函数类型的值。

递归:

C语言允许函数自己调用自己,称为递归。难点是结束递归的条件测试部分。

1、每级函数调用都有自己的变量;

2、每次函数调用执行完毕,控制权会返回上一级;

3、递归调用前的语句,按被调函数顺序执行;

4、递归调用后的语句,按相反顺序执行;

5、递归函数必须包含结束递归调用的语句,每次递归调用形参要使用不同的值,通常用测试条件,当形参等于某特定值则终止递归。

尾递归 即将递归调用放在函数结尾return之前,相当于循环;

一般而言,在尾递归与循环中优先选用循环,因为每一次递归创建的变量在栈中占用内存,且每一次执行耗时;

递归很适合处理倒序问题;

递归的优点在于对某些问题解决十分方便,但是十分消耗计算机内存资源、占内存、耗时长;故对于效率优先的程序,使用递归时要十分注意;

指针:

可以看做一个值为内存地址的变量。用于存储变量的地址;%p以十六进制显示指针的值(若编译器不支持用%n或%lu代替);PC地址通常用十六进制表示;

声明指针变量必须指定指针所指向变量的类型; int * pur;表示pur是指向整型变量的指针;

指针变量把地址作为基本量,把值作为通过解引用运算符*获得的派生量;

指针的值以 所指对象的大小 为单位 改变;

地址运算符&:

后跟变量名表示该变量的地址;pur=&bab;

间接运算符*:

后跟指针名或地址,给出存储在指针所指地址上的;ptr=*pur; *又称解引用运算符

注意:

主调函数把它的参数存储在叫做 是临时存储区,被调函数从栈中读取这些参数;

把函数原型和已定义的字符常量放在头文件中是一个良好的编程习惯;

在main()函数内部声明的变量也仅是main()函数内部的局部变量;当在主调函数中进行进行函数调用时,实参传递到函数的形参,传递的仅仅是值,各自有独立的地址;

return 只能被调函数中的一个值传递给主调,要传递多个,则需要指针;

一般,要计算或处理值,用形参是变量的函数定义;若想在被调函数中改变主调函数的值,用形参是指针的函数定义;

函数: 返回类型 名称(形参声明列表)

注意!!!形参声明列表用逗号,分隔一系列变量声明;

函数无法直接访问别的函数中的变量,当确实需要时,可以把指针作为函数的参数;

如果函数返回值类型是地址,那么格式为: 返回类型 * 名称(形参声明列表)

void 放在返回值位置上,说明此函数执行完不返回任何值;放在参数位置上则显示说明无形式参数。

0!为1,负数没有阶乘;

数组:

格式: 数据类型 数组名 [元素个数],元素个数可以省略,访问数组数据时数组名[0]是数组第一个元素,数组名[元素个数-1]是数组最后一个元素;数组初始化 in arr[2]={1,3};

使用数组之前一定要赋初值!!!!否则存储的是垃圾值,初始化一部分,剩余元素会被初始化为0;

数组存储的是同一类型的元素,下标的索引是从0开始的,陷阱在于C语言中不会检查数字索引号是否正确;

数组也可以存储字符串,字符串的标志在于最后一位由空字符\0;

同理,也可以用const把数组限定为只读;

数组元素个数 推荐 用#define来定义符号常量表示;

指定初始化器:可以指定要初始化数组中某个元素,如int array[50]={[18]=32};

数组赋值用循环一个个赋,array[end-1]仅仅代表最后一个元素

C语言不检查数组边界索引(相信程序员,运行更快),使用了越界索引程序可能会运行,但的结果是未定义的;

指定数组大小用 整型常量、整型常量表达式、sizeof被视为整型常量;数组大小 必须大于>0,且必须为正整数;

多维数组:

数组是按顺序存储的,处理几维数组用几重嵌套循环; flost array [10] [12] ;

若某一个列表元素不够会自动补零,元素太多会出错,但都 不影响其他行初始化;

二维数组可想象成数据表,三维可想象成一叠数据表;

指针与数组:

两者关系十分密切,数组元素array[n]  等价于  *(array+n)也可以理解为 “到内存的array位置,移动n个单元,检索存储在那里的值”;指针表示法、数组表示法等价,也就是说可以用指针表示数组也可以用数组表示指针;

编写用于处理数组的函数,函数调用时实参写数组名即可,数组名代表数组首元素地址,应传递给为指针的形参;

上图中int ar[]中的空括号表明ar是一个指针;

对于一个处理数组的函数,函数必须指定何时开始、何时结束(字符串不用)。方法一是一个指针形参标记数组开始地址,一个整形形参表明处理的数组元素个数;方法二是两个指针形参,一个指明数组开始,一个指明数组结束;

对于一个处理数组的函数,实际上是用指针作为参数,编写这样的函数时可选择指针表示法还是数组表示法;数组表示法更接近机器语言,代码效率更高;

*与++优先级相同,但从右往左执行;    *++start与*start++是完全不同的含义,实际最好带括号;

指针操作:赋值、解引用*、取址&、指针与整数相加/相减(整数乘指针指向类型字节数再与初始地址相加/相减)、递增/递减指针(指针移动指向下一个/前一个数组元素)、指针求差(两个元素的距离,距离单位是数组类型单位)、比较(前提两指针指向的类型相同);

一般规则:编写的函数需要修改数组内容,则在声明数组形参时不使用const;否则,声明形参时加上const;

指向const的指针通常用于函数形参/声明指针之中,有两种用法,一是让指针不能改变它所指向的地址,二是指针不能修改指向地址上的值;

指针与多维数组:

例int array[m] [n] 。array是数组首元素的地址,等同于&array[0],而array[0]又是一个n维数组。array[0]的值等于他内部首元素array[0] [0]的是地址。array是一个占用n个int类型对象的地址,array[0]是一个占用1个int类型对象的地址。由于数组起始于同一个位置,故array等于array[0];

array+1与array[0]+1所指向的值不同;

**array与*&array [0] [0]是等价的,其中array是地址的地址必须解引用两次才能获得原始值,这叫双重间接

声明一个指针变量指向二维数组,int (*prt) [2] ;

[]的优先级高于* ;

用数组表示法或指针表示法来表示一个数组,既可以使用数组名也可以使用指针名。如array [3] [2]等价于prt [3] [2];

变长数组VLA:

允许使用变量表示数组维度;变长数组一旦创建大小一直不变;

必须是自动存储类别,即函数内部声明或作为函数形参声明,均不能使用static或extern存储类别说明符,且不能在声明中初始化;在形参列表可这样省略维度 int ar[*][*]

声明变长数组可以用const;

复合字面量:

字面量是除符号常量以外的常量;

 是匿名的,故不能先创建再使用必须在创建的同时使用 ( int [])={10,20,30}或( int [3])={10,20,30}

典型用法是把信息传入函数前不必先创建数组;

复合字面量是指临时提供需要的值的一种手段,定义在最内层的花括号;

注意:

%5s表示字符串长度为5,若原字符串长度超过5则按原长度打印,若小于5则在左侧补空格,若为%-5形式且源字符串长度小于5则在右侧补空格;

%.5s的意思是截取字符串前7个字符,若原字符串长度小于5即是原字符串本身;

 char类型存储字符 1个字节的整数,%c;

qq截图:ctrl+alt+A                     电脑自带截图:win+shift+S

(PC与Macintosh)系统中,地址按字节编址,即内存中每个字节按顺序编号;short占2个字节,int 占4个字节,double占8个字节;一个较大对象的地址通常是该对象第一个字节的地址;

Macintosh又称Mac翻译为苹果电脑;

PC即Personal Computer,译为 个人电脑;

OS即Operation System,译为 操作系统;iOS是由苹果公司开发的移动操作系统。iOS与苹果的macOS操作系统一样,属于类Unix的商业操作系统。

函数原型可以省略参数名,函数定义不能省略;

C语言在保证给数组分配空间时,指向数组后面第一个位置的指针仍然是有效的指针;

指针变量也有自己的地址和值;

用指针前,必须先用已分配的地址初始化;不要解引用未初始化的指针!!!

传递数组问题,就用指针,不要用值传递(特别占用空间);C语言通常按值传递,函数用的是原始数据的副本,不会意外修改原数据,这样占空间;因此,若想要修改原始数据,需要通过指针在函数中直接使用原始数据

指针赋给另一个指针 要求指向类型必须相同!!!把const指针赋值给非const类型指针(c允许,未定义) 与 把非const指针赋值给const类型指针  都不安全。

形参名是可以省略的;

编译器会把数组表示法转换成指针表示法;

在函数形参列表声明数组 实际并未创建数组,是指针,修改的还是原数组的值;

符号常量用#define定义;

C语言将数组看作 派生类型 即建立在其它类型的机车;

字符串类型的数组 不用传递数组大小,通过检测末尾空字符即可;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

amyun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值