18 局部变量和全局变量
多文件共同访问一个全局变量:
①、在其中一个C/Cpp文件中定义并初始化全局变量,例如:
int sum = 0;
②、在C/Cpp文件都能访问到的一个h头文件中声明该全局变量为支持多文件访问的:
extern int sum; //此时只是声明,所以不需要初始化
③、在其他C/Cpp文件中 #include 这个头文件之后,就可以直接使用这个全局变量 sum 了。
备注:不能在 h 文件中直接定义这个全局变量 int sum = 0;
之前看到很多网友都是这么做的,这样的话如果有多个C/Cpp文件 include 包含这个头文件的时候就会提示 sum 重复定义了。所以一定要在 C/Cpp文件中定义该全局变量,之后在 h 头文件中声明该全局变量才行哦。
简单来说,在a.cpp中定义了全局变量int num;
,要在b.cpp中用这个变量
方法一:在b.cpp加上
extern int num; //这时用的是a.cpp中同一个变量,不是自己另外定义出来的
方法二:新建一个头文件inc.h,在里面写上
extern int num; //这时用的是a.cpp中同一个变量,不是自己另外定义出来的,只是在这里声明而已
在b.cpp中加
#include "inc.h"
static 静态类型变量:
static 静态类型局部变量只初始化一次,之后的调用都不进行初始化!
例:
#include <iostream>
#include<iomanip>
using namespace std;
int add()
{
static int value = 2;
value++;
return value;
}
int main()
{
cout << add() << endl;
cout << add() << endl;
cout << add() << endl;
cout << add() << endl;
cout << add() << endl;
return 0;
}
如果是 int value = 2
(没有static)
20 字符数组
字符数组的初始化:
方式①:定义之后分别对每个字符初始化;
char szbuf[10];
szbuf[0] = 'h';
szbuf[1] = 'e';
szbuf[2] = 'l';
szbuf[3] = 'l';
szbuf[4] = 'o';
备注:未初始化的部分值随机。
方式②:定义即初始化:
char szbuf[10] = {'h', 'e', 'l', 'l', 'o'};
或者:
char szbuf[10] = "hello";
备注:未初始化的部分值为0(其实是 \0
字符),要求初始值的个数小于数组的长度
方式③、自动初始化长度:
char szbuf[] = {'h', 'e', 'l', 'l', 'o', ' ', 'f', 'r', 'i', 'e', 'n', 'd', 's', ' ', 'I', ' ', 'a', 'm', ' ', 'c', 'c', 't', 'r', 'y', '.', 'c', 'o', 'm'};
如果字符串的长度比较长,而且要定义的数组长度就是字符串的长度,那么就可以使用此方法。
或者:
char szbuf[] = "hello friends I am cctry.com";
字符数组与字符串的区别:
区别就是字符串比字符数组多了一个结束标志的字符:’\0’,这个字符的ASCII码就是0
所以作为一个字符串来说:
有效字符就是结束标志\0
之前的字符。
长度是结束标志\0之前的字符,
所占用的字节数或者说所占用的空间,是包含字符串结束标志\0
的。
所以一般情况下关于一个字符串的长度不用很显示的给出或者告诉,直接对当前字符串从头往后找结束标志\0
就可以了,遇到了就表示这个字符串结束了。
用上面方式②的两种语句定义,都满足字符串的条件(最后都是\0)
字符数组的输入与输出:
char szbuf[50];
cin >> szbuf;
cout << szbuf << endl;
char szbuf[5] = { 'h','e','l','l','o' }; //全都初始化了
cout << szbuf << endl;
因为cout对这个数组进行输出时,认为是字符串,就会从头到尾进行输出,所以直到遇到字符串的结束标志\0
才会停止,超出了数组的长度,就变成乱码
如果改为char szbuf[5] = { 'h','e','l','l','\0' };
,就没有乱码:
C++中输出数组数据分两种情况:字符型数组和非字符型数组
当定义变量为字符型数组时,采用cout<<数组名; 系统会将数组当作字符串来输出
当定义变量为非字符符数组时,采用cout<<数组名; 系统会将数组名当作一个地址来输出
如果需要输出数组中的内容,则需要采用循环,逐个输出数组中的元素
21 使用字符串处理函数操作字符数组
字符串连接函数:strcat
作用就是将第二个参数的字符串连接到第一个参数的字符串结尾,
所以在字符数组中,要保证第一个参数的字符数组大小够用,能装的下第1个和第2个字符串的总长度才行,不然就会发生内存溢出啦!
返回值是第一个字符串的首地址
字符串拷贝函数:strcpy
其作用就是将第2个参数的字符串拷贝到第一个参数的字符数组中,
所以在字符数组中要保证第1个参数的字符数组大小够用。注意:第2个参数的结束符 ‘\0’ 也会拷贝过去哦。
(与上一个的区别,strcat是把第二个接在第一个后面,strcpy是用第二个覆盖掉第一个)
但并不是全覆盖,只覆盖第二个的长度,剩下的还是第一个的。但是输出时,cout遇到\0
就停了,所以后面的没有输出
字符串比较函数:strcmp
其作用就是对比第1个和第2个参数的字符数组字符串,逐个字母比对,直到字符串结束(遇到\0)。即比较每个字母的ASCII码值。
当第1个参数大于第2个参数,返回 > 0 的数,
当第1个参数小于第2个参数,返回 < 0 的数,
当第1个参数和第2个参数相等,返回0
字符串求长度函数:strlen
其作用就是求得参数字符串的长度,通过返回值返回。
(这个长度是指有效长度,不包括 \0)
sizeof求得的是占用字节数
例:
char s1[50] = "abc";
int s2[10];
int length = strlen(s1); // length=3
int size = sizeof(s1); //size=50 (一个字符占一个字节)
size = sizeof(s2); //size=40; (因为s2有10个int,一个int占4个字节)
小作业:
不用系统提供的strcat函数,自己使用字符数组编写一个函数,实现两个字符串的连接功能。
#include <iostream>
using namespace std;
int main()
{
char s1[50] = { 0 };
char s2[50] = { 0 };
cin >> s1 >> s2;
int len1 = strlen(s1);
int len2 = strlen(s2);
for (int i = len1; i < (len1+len2); )
{
for (int j = 0; j < len2; j++)
{
s1[i] = s2[j];
i++;
}
}
cout << s1 << endl;
return 0;
}