.(点)命令的强大功能
.(点)命令是简单的,也是强大的。.命令重复最后一次文件内容影响命令。下面的例子说明.命令的使用。
- 在文件中搜索字符串,使用:/one
- 使用one替换two,使用:cwone
- 搜索下一个one出现地方,使用:n
- 使用two替换one,使用:.(点号)
在上面的例子中,第4步,你不需要再次输入cwtwo。替代的,简单的输入.(点号),它会执行最后一次改变命令,也就是cwtwo。
基础储备知识基本结束了,今天看一下稍微高级点的文件读写,这个主要针对的对象是什么呢,比如要统计学生的分数,一般我们都会有一个文件保存所有的学生的成绩,这个时候如果我们能读取这些信息就会少了很多人工输入的工作,在前面,我们的解决方案可能是输入每一个学生的成绩,这次我们通过读取文件来搞定。
而文件的读写又分为两种:
这个跟程序员的世界很像,因为程序员的世界也是有0和1这两个元素组成的。
先说说直观上比较容易理解的文本文件。
对于文件的读写,一般的步骤为:
对应的函数为:
下面详细说说这几个函数.
其实在刚开始学习输入输出的时候,第一个接触的可能不一定是printf和scanf函数,还有两个关于字符和字符串的输入输出函数。
下面分别来是说说:
从字面意思来看,很容易理解,就是对字符的获取和输出,所以这两个函数你只能输入一个字符,这是限制。
1 | /*beginner/io/io3.c*/ |
这两个函数就比较灵活,处理的为字符串,会等待输入的一行文本,只有在输入回车键或者遇到终止符时,才认为是结束了。
1 | /*beginner/io/io4.c*/ |
NB:不过,对于C语言而言,这两个函数能实现的,printf和scanf都可以实现,并且bug少一些,建议尽量少使用今天提到的4个函数,了解即可。
这次说说C语言的输入和输出,其实从开始的第一个程序,我们已经和C语言的输出打上交道了,对的,就是printf函数,而输入也有提及,就是scanf函数。
而对于用户或者开发者而言,最直观的程序运行的概念就是你输入给程序信息,程序打印输出给你看到。
BINGO,程序正常运行。
这次来详细说说,在C语言或者Linux的世界里面,所有的设备都是文件,所以访问设备就是访问文件,你可以注意到在Linux系统的根目录有一个dev目录,就是设备的交户口所在地。
如何才能交互呢,在C语言里面,在你运行程序的时候,下面的三个默认文件已经同步打开了,这就方便了我们访问键盘,进行输入或者通过屏幕输出信息:
文件 | 文件指针 | 对应设备 |
---|---|---|
标准输入 | stdin | 键盘 |
标准输出 | stdout | 屏幕 |
标准错误 | stderr | 屏幕 |
这里在重温一下C语言中用的最广的printf函数和scanf函数:
参考示例:
1 | /*beginner/io/io1.c*/ |
示例1展示了最简单的输出一句。
1 | /*beginner/io/io2.c*/ |
示例2展示了输入参数,可以看到我们已经学习了47个tips,如果100个可以完成对C语言的入门,那么恭喜,你已经完成一半了。
指针不仅仅能指向变量,也可以指向函数,这个功能主要用在方便快捷地调用函数上。
比如我们结合前面说的三元描述符、子函数来看看如何用函数指针。
看一个例子如下,我们已经写好了如何选择最大值,如下所示:
1 | /*beginner/pointer/pointer2.c*/ |
上面的是比较2个值的大小,如果想比较3个值呢,用上面的代码,新增如下:
1 | /*beginner/pointer/pointer3.c*/ |
在增加一个,4个值呢,
1 | /*beginner/pointer/pointer4.c*/ |
所以看出来,每次新增一个值,就需要多调用一次max函数。
如果使用函数指针就可以很好地解决这个问题,如下所示:
1 | /*beginner/pointer/pointer5.c*/ |
从这里例子也可以看出来,函数的指针的格式如下所示:
不过好像也没有简便很多,不过如果碰到函数名巨长无比的,还是有些作用的,另外我们可以使用内嵌的方法,如下:
1 | /*beginner/pointer/pointer6.c*/ |
指针是C
语言中最有趣的概念,简洁、优美、快速、复杂、难懂,所以有一本书叫做《C和指针》,足见其强悍之处。
C
语言指针一般设计到动态内存分配等高级概念,要想成为一个高手,必须要掌握指针,本节,只需要了解一个概念即可。
即指针是一个变量,指针的值是另外一个变量的地址,可以认为指针指向你这个值的时候,代表的是你家的地址。
看一个例子如下:
1 | /*beginner/pointer/pointer1.c*/ |
1 | $ ./pointer1 |
可以看到变量没有规则,但是出来的地址是有顺序的,按照一定的规则增加或减少。
看一下如何使用指针,规则如下:
1 | type * var-name; |
其中type可以是我们前面说过的所有变量类型,比如int
、double
、float
、char
等。
比如:
1 | int *pi; |
如果你遇到一个简单输入错误,错误放置相邻的字符,你可以使用xp
。例如你输入the
替代teh
,导航到e
,按下xp
,它会自动修正输入。
xp
实际上,xp不是真的修正输入,含义如下:
xp
的含义就是“位置交换”。又到了XP的年代吗,错了。
任何一种编程语言,都会存在作用域的概念,比如C++中的private、public等,在C语言里面,主要根据变量所在的位置来区分,主要有:
所谓的局部变量就是只能被局部访问,一般定义在函数内部或者某个块,在函数的外部是不可知且不能被访问的,比如下面的变量:
1 | /*beginner/scope/scope1.c*/ |
其中的变量a、b、c,也就是1、3、5就是main函数的局部变量。
全局变量按照字母意思就是在整个程序的声明周期都存在,也就是说所有的函数都可以访问到,一般而言,都会位于函数的外面,通常在程序的顶部,比如:
1 | /*beginner/scope/scope2.c*/ |
那么问题就来了,万一全部变量和局部变量定义了相同给的名字,该访问使用哪一个呢,这个记住即可,如果两个名字相同,会使用局部变量,临近原则吧。
1 | /*beginner/scope/scope3.c*/ |
编译也有所不同,方法为:
1 | #beginner/scope/Makefile |
这会产生可执行程序,当程序被执行时,它会产生下列结果:
1 | $ ./scope1 |