串与线性表相似,但它的组成是字符,而且操作不是以单个数据元素操作,而是以子串进行操作。
6.1串的结构定义
顺序结构:
typedef struct{
char *ch;
int length; //定义和顺序表相同
}HString;
串的销毁:
int Destroy_SString(SString *S){
if(!S){return -1;}
free(S);
return 0;
}
链式结构:
串的的链式存储特殊性在于,每个结点可以是多个字符,结点(块)大小直接影响存储效率。
串的链式存储
#define CHUNKSIZE 80 //可由用户定义的块大小
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head,*tail; //串的头指针和尾指针
int len; //串的当前长度
}LString;
易错点:
- 以下代码在UpperCase和main函数里都用sizeof()计算数组的项目。一般sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。main中的str是一个静态定义的数组,因此其大小为6,因为还有’\0′,UpperCase内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。
void UpperCase(char *str){ // 将 str 中的小写字母转换成大写字母
for(int i=0;i<sizeof(str)/sizeof(str[0]);i++){
if('a'<=str[i]&&str[i]<='z'){
str[i]=str[i]-('a'-'A');
}
}
}
int main(){
char str[] ="aBcDe";
cout << "str字符长度为:"<< sizeof(str)/sizeof(str[0]) << endl;
UpperCase(str);
cout << str << endl;
}
注:以上代码在CPP中执行是成功的,以后如果使用sizeof()计算字符串大小出错可以换一种写法:
s=str;
for(len=0;*s;len++,s++);//循环在s指向内容(*s)为0(到达字符串尾)时跳出
另外,数组在传参时,形参可以像上例写为char *str,也可以写为char str[]。实参可以写为UpperCase(str),即用头指针指代整个数组。
- 计算机的栈区、堆区和全局区(静态区):
1、栈区—由编译器自动分配释放,存放函数的参数值,局部变量的值等。如以下在free这一步会内存错误,因为这里的a数组时存在栈区的,不能手动释放。
int main(){
int a[5];
for(int i=0;i<5;i++){
a[i]=0;}
free(a[4]);
printf("%d",sizeof(a));
}
2、堆区—由程序员分配释放,即动态申请的区域,若程序员不释放,程序结束时可能由系统回收。C或C++的Malloc或new是用的堆空间,需要手动用Free或delete释放。
3、全局区(静态区)(static)存放全局变量和静态变量,在程序编译的时候就已经分配好。
静态变量:指在程序执行前系统就为之静态分配,也即在运行时中不再改变分配情况的一类变量。
全局变量:程序在所有函数外面定义的变量,main函数里的是局部变量。
计算机内存
- 字符串的申明。C语言字符串申明可以用char *x或char x[],两者本质上是一样的,都是以字符数组形式存储。两者区别在于,用char *定义的x,会自动在末尾加上'\0',但用char []定义x,可能末尾没有'\0'。而C语言在输出x时,会一直到'\0'为止,所以char []定义的可能输出时会有乱码出现。
char *x="abc";
char x[]="abc";
当然我们可以在字符数组初始化时人工加上\0(位数多1)。用char *x申明时如果没有赋值,那么只是一个野指针,需要手动申请空间,如以下代码是错误的:
int *a;
for(int i=0;i<5;i++){
a[i]=0;
}
改成:
int *a=new int[5];;
for(int i=0;i<5;i++){
a[i]=0;
}
char str[]={'I',' ','a','m',' ','h','a','p','p','y','\0'};
说明:
(1)上述这种字符数组的整体赋值的形式,只能在字符串初始化时使用,程序执行过程中只能一一赋值,如下面的赋值方式是错误的:
char str[];
str="I am happy";
(2)定义为指针所指向的字符串是常量字符串,只能读取不能写入。如以下程序执行会出错。
int main() {
char *str = "media";
char *tmp = "aaa";
printf("str: %s\n",str);
strcat(str,tmp);
printf("str: %s\n",str);
return 0;
}
*上面把char *str = "media"改成char str[20]= "media"就对了。