您的位置:首页 > 编程语言 > C语言/C++

黑马程序员—(iOS开发)C语言字符串及预处理---(六)

2014-08-28 16:05 381 查看
------- iOS培训PHP培训android培训java培训、期待与您交流!
----------

说明:

1、 字符串

2、 字符与字符串常用处理函数

3、 预处理指令1—宏定义:

4、  预处理指令2—条件编译:

5、  预处理指令3—文件包含:

6、  static 和 extern 关键字1—对函数的作用:

7、  static 和 extern 关键字1—对函数的作用:

 

(一)  字符串

1、 字符串简介:C语言中,由一个或多个字符组成的序列,使用字符数组存储字符串;

1> 字符数组以’\0’标识结束(ASCII中的0字符,空操作符),若无此结束标记,说明此字符数组存储的非字符串;

如:char a[] = mj;



2、 字符串的初始化:

1> char a[3] = {‘m’,’j’,’\0’};

2> char b[3];

b[0] = ‘m’;

b[1] = ‘j’;

b[2] = ‘\0’;

3> char c[3] = ”mj”; // 系统自动添加\0结束符

4> char d[] = ”mj”;

5> char e[20] = ”mj”;

3、 字符串的输出:

1> 可使用stdio.h中的printf和puts函数输出字符串;

2> 使用格式符:%s表需输出一个字符串,直到\0字符为止,但不输出空字符;

3> printf函数:可同时输出多个字符串;

4> puts函数:一次只能输出一个字符串,且输出一个字符串后自动换行;

4、 字符串的输入:

1> 可使用stdio.h中的scanf和gets函数输入字符串;

2> 字符串输入:从a的首地址开始存放用户输入的字符,存放完毕后,系统会自动在尾部加上结束标记\0;

3> scanf函数:可同时读取多个字符串,且不能读取空格、tab的字符串;

4> gets函数:一次仅能读取一个字符串,且能读入包含空格、tab的字符串;

5、 字符串数组:

1> 字符串数组简介:一维数组存放一个字符串,二维数组存放多个字符串(依次累加);

2> 字符串数组的初始化:

如:char names[2][10] = {{‘j’,’a’,’y’,’\0’},{‘j’,’i’,’m’,’\0’}};

char names[2][10] = {{“jay”},{“jim”}};

char names[2][10] = {“jay”,”jim”};

(二)  字符与字符串常用处理函数

1、 字符处理函数:

1> 可使用stdio.h中的字符输出函数putchar和 字符输入getchar函数处理字符;

2> 字符输出函数putchar:

① 用法:putchar(65); // 输出A

putchar(‘A’); 
4000
// 输出A

int a = 65; putchar(a); // 输出A

② putchar一次仅能输出一个字符,ptintf可同时输出多个字符;

3> 字符输入函数getchar:

① 用法::char c;  c = getchar();

② getchar 一次仅能读入一个字符,且可读入空格、tab,直到遇到回车符为止;

scanf 可同时接收多个字符,且不能读入空格、tab、回车换行符;

③ getchar还可读入回车换行符,你需敲2次回车,第1次敲被getchar读入,第二次代表输入结束;

2、 字符串处理函数:

1> 常用string.h中字符串处理函数:strlen 、strcpy;

2> strlen 函数:测量字符串的字符个数,直到遇到\0为止,但不包括\0;

① 用法:int size = strlen(“mj”); //长度为2

char s1 = “mj”; int size1 = strlen(s1) ; //长度为2

char s2 = {‘m’,’j’,’\0’,’l’,’m’,’j’,’\0’}; int size2 = strlen(s2) ; //长度为2 

3> strcpy 函数:拷贝字符串至字符数组,直到遇到\0为止,保留\0至数组中;

①  用法:char s[10]; strcpy(s,”mj”); // 拷贝m/j/\0至s数组中

char c[] = {‘m’,’j’,’\0’,’l’,’m’,’j’,’\0’};  strcpy(s,c); // 拷贝m/j/\0至数组

4> strcat 函数:拼接字符串2至字符数组尾部,直到遇到\0为止,但\0被覆盖后,数组末尾保留\0;

① 用法:

。char s1[30] = “LOVE”; strcat(s1,”OC”); //s1为LOVEOC\0

。char s1[30] = {‘L’,’O’,’V’,’E’,’\0’,’J’,’A’,’\0’};

。strcat(s1,”OC”);//s1为LOVEOC\0

5> strcmp 函数:比较2个字符串大小;

① 调用形式:strcmp(字符串1,字符串2);

② 从左往右逐个字符比较(ASCII码值大小),直到字符不同或遇到\0为止,若所有字符相同则返回0,不同则返回2个字符串中第一个不同字符ASCII码值的差(字符串1>字符串2返回正,否则返回负);

③ 用法:char s1[]=“abc”;  char s2=“abc”;  char s3=“aBc”;  char s4=“ccb”;

int result1 = strcmp(s1,s2); // 相同为0

int result2 = strcmp(s1,s3); // 不同,返回第一个不同字符的码值差b-B=32;

int result3 = strcmp(s1,s4); // 不同,返回第一个不同字符的码值差a-c=(-2);

(三)  预处理指令1—宏定义:

1、 预处理指令简介:

1> C语言中,对源程序编译之前会对一些特殊的预处理指令作解释(如:#include文件包含指令),产生一个新源程序(这个过程称编译预处理),之后再进行编译;

2> 预处理指令一般以符号”#”开头,且结尾不用分号;

3> 预处理指令可出现在程序任意位置,作用范围是从它出现位置到结尾,习惯上尽可能的写在程序开头,其作用为整个程序;

4> C语言提供的预处理指令主要有:宏定义、文件包含、条件编译;

2、 不带参数的宏定义:

1> 一般形式:#define 宏名 字符串

如:#define ABC 10 // 左边字符串可省略为:#define ABC

2> 作用:在编译预处理时,将源程序所有”宏名”替换成右边的”字符串”,常用来定义常量;

3> 使用习惯与注意:

① 宏名一般大写,但小写也无语法错误;

② 对程序中用双引号括起来的字符串内的字符,不进行宏的替换操作;

如:#define R 10   char *s = “Radio”;

③ 在编译预处理用字符串替换宏名时,不做语法检测,只是简单的字符串替换;仅在编译时才对已展开宏名的源程序进行语法检查;

④ 宏名的有效范围:从定义位置到文件结束,若需终止宏定义作用域,可用#undef 宏名 命令;

⑤ 定义一个宏时,可引用已经定义的宏名

3、 带参数的宏定义:

1> 一般形式:#define 宏名(参数列表) 字符串;

2> 作用:在编译处理时,将源程序中所有宏名替换成字符串,并将 字符串中的参数 用 宏名右边参数列表 中参数替换;

如:#define average(a,b) (a+b)/2 int a = average(10,5);

3> 使用注意:

① 宏名和参数列表间不能有空格,否则空格后的所有字符串都作为替换的字符串;

如:如:#define average (a,b) (a+b)/2 //绿色地方不能有空格

② 带参数的宏在展开时,只作简单的字符和参数的替换,不进行任何计算操作。因此,在定义宏时,一般用一个小括号扩住字符串的参数;

如:#define D(d) 2*(a)

③ 计算结果最好也用括号括起来;

如:#define Pow(a) ((a) * (a))

4> 与函数的区别:

带参数的宏定义,在源程序中出现的形式与函数很像,但两者有本质的区别:

① 宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题;

② 函数调用在程序运行时执行,而宏替换只在编译预处理阶段进行,所以带参数的宏比函数具有更高的执行效率;

(四)  预处理指令2—条件编译:

1、 条件编译:希望程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才被执行),这就是条件编译;

2、 基本用法:

1> 如:



2> 条件几成立就把该条件中的code代码编译进去(编译进去,不是执行);

3> 条件编译结束后,在后面加上#endif;

4> #if 和 #elif 后面的条件一般是判断宏定义,而不是判断变量,因为条件编译器在编译前做的判断,宏定义也是编译前定义的,而变量是在运行时才产生的、才有使用意义的;

3、 例子解析:

 


4、 其他用法:

① #if defined() 和 #if !defined() 语法:

。#if 和 #elif后的条件不仅可用来判断宏的值,还可判断是否定义过某个宏;

如图:若前面已定义过MAX宏,就将code编译进去(只要定义过MAX,则条件就成立)



。条件可取反;

如图:若前面没有定义过MAX这个宏,就将code编译进去;

 


② #ifdef 和 #ifndef的使用:

。#ifdef 的使用 和 #if defined() 用法基本一致;

如图:若前面已定义过MAX宏,就将code编译进去(只要定义过MAX,则条件就成立)



。#ifndef的使用 和 #if !defined() 用法基本一致;

如图:若前面没有定义过MAX这个宏,就将code编译进去;



(五)  预处理指令3—文件包含:

1、 基本概念:使用文件包含指令#include,将一个文件的全部内容拷贝到另一文件中;

2、 一般形式:

1> 调用系统库函数头文件所在目录寻找文件:#include <文件名>;

2> 系统先在源程序当前目录下查找,在到操作系统path路径中查找,最后到库函数文件所在目录中查找:#include “文件名”;

3、 使用注意:

1> #include 指令允许嵌套包含:如a.h 包含 b.h;

2> 使用#include 指令可能导致多次包含同一头文件,降低编译效率;

3> 解决重复包含头文件问题:

   

  


(六)  static 和 extern 关键字1—对函数的作用:

1、 extern 与函数:

1> 了解:

①  外部函数:若在当前文件中定义的函数允许其他文件访问、调用,就为外部函数。C语言规定,不允许有同名的外部函数;

② 内部函数:若当前文件中定义的函数不允许其他文件访问、调用,只能在内部使用,就称为内部函数。C语言规定不同源文件可有同名的内部函数,且互不干扰;

③ 编译:单独检查每个源文件语法是否合理,不会检查每个源文件间的管理关系,一个源文件编译成功就生成一个目标文件;

④ 链接:检查目标文件的关联关系,将相关联的目标文件组合在一起,生成可执行文件;

2> 外部函数:

① 定义:使用extern关键字(默认为外部函数,extern关键字可省略);

如:extern void one(){};

② 声明:在main函数前对该函数进行提前声明:应使用extern关键字,表引用别人的”外部函数”;

如:extern void one();

③ 调用:使用#include “**.c” 文件包含指令;

④ 注意:extern可省略不写,函数默认为外部函数;

2、 static 与函数:

1> 内部函数定义:使用static关键字定义内部函数;

如:static void one(){}

2> 声明内部函数:在main函数前对该函数进行提前声明:static void one();

3> 调用:使用#include “**.c”;

3、 static、extern 与函数的总结:

1> static:

① 在定义函数时,在函数最左边加上static可把该函数声明为内部函数(也叫静态函数),该函数就只能在其定义所在文件中使用,若不同文件中有同名内部函数,互补干扰;

② static也可声明一个内部函数;

2> extern:

① 在定义函数时,若在函数最左边加上关键字extern,则表示此函数是外部函数,可供其他文件调用,C语言规定,若在定义函数时省略extern,则隐含为外部函数;

② 在一个文件中要调用其他文件中的外部函数,则需在当前文件中用extern声明该外部函数,然后可使用,这里的extern可省略;

(七)  static 和 extern 关键字1—对函数的作用:

1、 C语言中,全局变量定义的位置是有限制的(java中无严格限制):

1> 默认情况下,一个函数不可访问在它后面定义的全局变量;

2> 可使用解决方法:

① 将变量定义在main函数前;

② 在main函数前对变量进行提前声明(使用关键字extern);

2、 重复定义同一变量:

1> 重复定义表同一变量;

3、 不同源文件的同名变量:

1> 不同源文件的同名变量,表同一变量;

4、 static关键字:

1> 不想源文件中的全局变量与其他源文件共享,相当于私有的全局变量,就使用static关键字来定义变量;

2> extern是用来声明已经定义过且能够访问的变量;

5、 static和extern的总结:

1> extern可用来声明一个全局变量,但不能用来定义变量;

2> 默认情况下,一个全局变量可供多个源文件共享的,也就是说,多个源文件中同名的局部变量都代表同一变量;

3> 若在定义全局变量时加上static关键字,此时static的作用在于限制该全局变量的作用域,只能在定义该全局变量的文件中才能使用,跟其他文件中的同名变量互补干扰;

PS:这节总结了关于字符串、预处理和extern/static关键字的作用,这节也需要掌握。

这里就是我总结的所有有C语言知识点,当然重要的是:函数、预处理、指针、数组、枚举、结构体等重要知识点需要掌握哟!

------- iOS培训PHP培训android培训java培训、期待与您交流!
----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息