C语言学习第九天

1.10 外部变量与作用域
main函数中的变量(如line、longest等)是main函数的私有变量或局部变量。由于他们是在main函数中声明的,因此其他函数不能直接访问他们。其他函数中声明的变量也同样如此。函数中的每个局部变量只在函数被调用时存在,在函数执行完毕退出时小时。这也是其他语言通常把这类变量称为自动变量的原因。以后我们使用“自动变量”代表“局部变量”。
由于自动变量只在函数调用执行期间存在,因此,在函数的两次调用之间,自动变量不保留前次调用时的赋值,且在每次进入函数时都要显示为其赋值。如果自动变量没有赋值,则其中存放的时无效值。
除自动变量外,还可以定义位于所有函数外部的变量,也就是说,在所有函数中都可以通过变量名访问这种类型的变量。由于外部变量可以在全局范围内访问,因此函数键可以通过外部变量交换数据,而不必使用参数表。再者,外部变量在程序执行期间一直存在,而不是在函数调用时产生、在函数执行完毕时消失。即是在对外部变量赋值的函数返回后,这些变量仍将保持原来的值不变。
外部比昂量必须定义在所有函数之外,且只能定义一次,定以后编译程序将为它分配存储单元。在每个需要访问外部变量的函数中,必须声明相应的外部变量,此时说明其类型。声明时可以用extern语句显示声明,也可以通过上下文隐式声明。

我们改写上述打印最长文本行的程序,把line、longest与max声明为外部变量。

#include <stdio.h>

#define MAXLINE 1000    /* 允许的输入行的最大长度 */

int max;    /* 到目前为止发现的最长行的长度 */
char line[MAXLINE];    /* 当前的输入行 */
char longest[MAXLINE];  /* 用于保存最长的行 */

int mygetline(void);
void copy(void);

/* 打印最长的输入行:外部变量版本 */
main() {
    int len;
    extern int max;
    extern char longest[];

max = 0;
    while ((len = mygetline()) > 0)
        if (len > max) {
            max = len;
            copy();
        }
    if (max > 0)    /*存在这样的行 */
        printf("%s", longest);
    return 0;
}

/* getline函数:外部变量版*/
int mygetline(void) {
    int c, i;
    extern char line[];

for (i = 0; i < MAXLINE-1 && (c = getchar()) != EOF && c != '\n'; ++i)
        line[i] = c;
    if (c == '\n') {
        line[i] = c;
        ++i;
    }
    line[i] = '\0';
    return i;
}

/* copy函数: 外部变量版 */
void copy(void) {
    int i;
    extern char line[], longest[];

i = 0;
    while ((longest[i] = line[i]) != '\n')
        ++i;
}

在该例子中,前几行定义了main、getline与copy函数使用的几个外部变量,声明各外部变量的类型,这样编译程序将为他们分配存储单元。函数在使用外部变量之前,必须知道外部变量的名字。要达到该目的,一种方式是在函数中使用extern类型的声明。
某些情况下可以省略extern声明。在源文件中,如果外部变量的定义出现在使用它的函数之前,那么在那个函数中就没有必要使用extern声明。因此,main、getline及copy中的几个extern声明是多余的。在通常的做法中,所有外部变量的定义都放在源文件的开始处,这样就可以省略extern声明。
如果程序包含在多个源文件中,而某个变量在file1文件中定义、在file2和file3文件中使用,那么在文件file2与file3中就需要使用extern声明来建立该变量与其定义之间的联系。人们通常把变量和函数的extern声明放在一个单独的文件中(习惯上称为头文件),并在每个源文件的开头使用#include语句把所要用的头文集包含进来。后缀名.h约定为头文件名的扩展名。
“定义”表示创建变量或分配存储单元,而“声明”指的是说明变量的性质,并不分配存储单元。
过分依赖外部变量会导致一定的风险,因为它会使程序中的数据关系模糊不清——外部变量的值可能会被意外地或不经意地修改,而程序的修改又变得十分困难。

到目前为止,已经对C语言的传统核心部分进行了介绍。借助于这些少量的语言元素,我们已经能够编出相当规模的有用的程序。建议大家花一些时间编写程序作为练习。

练习1-20 编写程序detab,将输入中的制表符替换成相当数目的空格,使空格充满到下一个制表符终止的地方。假设制表符终止的位置是固定的,比如每隔n列就会出现一个制表符终止位。n应该作为变量还是符号常量呢?
练习1-21 编写程序entab,将空格串替换为最少来嗯的制表符和空格,但要保持单词之间的间隔不变。假设制表符终止位的位置与练习1-20的detab程序的情况相同。当使用一个制表符或者一个空格都可以达到下一个制表符终止位时,选用哪一种替换字符比较好?
练习1-22 编写一个程序,把较长的输入行“折”成短一些的两行或多行,折行的位置在输入行的第n列之前的最后一个非空格之后。要保证程序能够智能地处理输入行很长以及在指定列前没有空格或制表符时的情况。
练习1-23 编写一个删除C语言程序中所有注释语句。要正确处理带引号的字符串与字符常量。在C语言中,注释不允许 嵌套。

——————————————————————————————————
#include <stdio.h>

#define TABNUM  8

/* 练习1-20 编写程序detab,将输入中的制表符替换成相当数目的空格,使空格充满到下一个制表符终止的地方。假设制表符终止的位置是固定的,比如每隔n列就会出现一个制表符终止位。n应该作为变量还是符号常量呢?*/
main() {
    int c, pos, i; /* 输入的字符、用于记录每一个8位(tab数)输入当前到第几位了*/

i = pos = 0;
    while ((c = getchar()) != EOF) {
        if (c == '\t') {
            for (i = 0; i < TABNUM-pos; i++)
                putchar(' ');
            pos = 0;
        } else {
            ++pos;
            putchar(c);
            if(pos == 8 || c == '\n') { // 如果字符串大于8就要从头开始算,如果换行了也要重新算
                pos = 0;
            }
        }
    }
}

C语言学习笔记(九)相关推荐

  1. 计算机二级C语言学习笔记(十八)

    上一篇:计算机二级C语言学习笔记(十七) 程序填空题(二) 题型二:平均值 首先求和,然后将和除以项数 ===================================== ========== ...

  2. 【Go语言 · 学习笔记】

    文章目录 Go语言 · 学习笔记 一.Go包管理 1. 什么是Go语言中的包 2. 包的命名 3. main包 4. 导入包 5. 远程包导入 6. 命名导入 7. 包的init函数 二.Go开发工具 ...

  3. 易语言学习笔记——命令篇

    易语言学习笔记20180711 一. 命令概述 1.     什么是命令:命令是一个功能调用的开始. 2.     命令的参数:调用一个功能方法时候输入的数据或者条件. 3.     命令的返回值:调 ...

  4. IOS学习笔记(九)之UIAlertView(警告视图)和UIActionSheet(操作表视图)基本概念和使用方法...

    IOS学习笔记(九)之UIAlertView(警告视图)和UIActionSheet(操作表视图)基本概念和使用方法 Author:hmjiangqq Email:jiangqqlmj@163.com ...

  5. 梓益C语言学习笔记之链表&动态内存&文件

    梓益C语言学习笔记之链表&动态内存&文件 一.定义: 链表是一种物理存储上非连续,通过指针链接次序,实现的一种线性存储结构. 二.特点: 链表由一系列节点(链表中每一个元素称为节点)组 ...

  6. 6.方法(go语言学习笔记)

    6.方法(go语言学习笔记) 目录 定义 匿名字段 方法集 表达式 1. 定义 方法是与对象实例绑定的特殊函数. 方法是面向对象编程的基本概念,用于维护和展示对象的自身状态.对象是内敛的,每个实例对象 ...

  7. 梓益C语言学习笔记之指针

    梓益C语言学习笔记之指针 一.32位平台下,地址是32位,所以指针变量占32位,共4个字节 二.内存单元的地址即为指针,存放指针的变量称为指针变量,故:"指针"是指地址,是常量,& ...

  8. c语言中void arrout,c语言学习笔记(数组、函数

    <c语言学习笔记(数组.函数>由会员分享,可在线阅读,更多相关<c语言学习笔记(数组.函数(53页珍藏版)>请在人人文库网上搜索. 1.数组2010-3-29 22:40一维数 ...

  9. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者 http://www.admin10000.com/document/9 ...

  10. 吴恩达《机器学习》学习笔记九——神经网络相关(1)

    吴恩达<机器学习>学习笔记九--神经网络相关(1) 一. 非线性假设的问题 二. 神经网络相关知识 1.神经网络的大致历史 2.神经网络的表示 3.前向传播:向量化表示 三. 例子与直觉理 ...

最新文章

  1. 使用pydub做静音帧去除
  2. mysql发生系统错误2系统找不到指定文件_电脑运行错误代码大全,遇到报错请自己对照断电原因所在吧...
  3. 临床研究和医疗保健行业实现数据湖架构的机会和挑战
  4. BM微型计算机2283,微型计算机原理及接口技术钢琴课程设计最新.doc
  5. Delphi 与 DirectX 之 DelphiX(6): 让 TDXImageList 和常规 VCL 交互使用
  6. linux中Tomcat 8 文件上传后无访问权限
  7. mysql链路跟踪工具_EasySwoole利用链路追踪组件制作甩锅工具
  8. 基友扫雷通关跟我炫耀!于是用Python自动扫雷程序十秒通关
  9. python中filter(),reduce()函数
  10. 潘建伟团队再次刷新世界纪录:实现18个光量子比特纠缠
  11. 2019美赛b题:基于Weighted-K-means聚类模型的选址
  12. 北京化工大学研究生学堂在线矩阵论及其应用答案
  13. Python 和Java 哪个更适合做自动化测试?
  14. 深度总结:软件设计七大原则
  15. 威纶触摸屏如何设置数值输入元件的上下限和用户密码登录?
  16. Android - Md5加密 工具类
  17. Unity3D教程笔记——unity初始02
  18. cad2017单段线_cad2017新功能介绍
  19. AndroidStudio(Idea) 快捷键错乱,insert键乱入,复制粘贴查找快捷键无效
  20. 评分卡模型开发(十)--总体流程

热门文章

  1. [ArcGIS] 栅格计算器
  2. Informatica 中文字符
  3. 工作区子系统设计时,同时也要考虑终端设备的用电需求,下面关于信息插座与电源插座之间的间距描述中,哪一个是正确的呢?
  4. Retrofit + RxJava 的结合使用
  5. c++ 正则表达式验证手机号码
  6. iOS 【invalid nib registered for identifier(Cell)】
  7. Android-图像识别项目OpenCV(2):运行官方例子中的脸部识别程序
  8. Fun with Unit Tests – Testing abstract classes
  9. 任正非霸气回应:没有谷歌,华为也能成为世界第一!
  10. 【三维目标检测】Second 模型 (一)