C语言基础
字符串
字符串:由多个字符构成,最后一个字符必须要是'\0'
字符数组:由多个字符构成
表达方式
char str[10]={'a','b','c'};
char str[10]={"hello"};
char str[10]="hello";
char str[10]="hello";
str[2]='m';
hello存放在文字常量区,但是str扯个字符串存在栈区,度文字常量区的内容进行了拷贝,所以可修改str里的字符创里的变量。
char *p="hello";
用p[2]='m'会出错,因为文字常量区常量字符串只读不可更改
char *p="hello";
char *q="hello";
printf("p=%p,q=%p",p,q)//结果相同
char *p="hello"
printf("%c\n",*(p++));//h
printf("%c\n",*p);//e
char *p="hello"
p++;
printf("%s\n",*p);//ello
#include
int main()
{
char *p="abcde";
printf("%c\n",*p);
printf("%c\n",*p++);
printf("%c\n",*p);
printf("%c\n",*p++);
printf("%c\n",*p);
printf("%c\n",*(p++));
printf("%c\n",*p);
printf("%c\n",*(p++));
printf("%c\n",*p);
}//aabbccdde
在栈区定义恩恩一个指针p指向了文字常量区的内容,所以不可以用p对文字常量区的内容进行更改。
printf是以\0结束的
字符串长度的计算
strlen():计算\0之前的字符,不包括\0这个字符。包含头文件#include 。
char str[10]="hello";
long int lengh=strlen(str);
printf("lengh=%ld\n",lengh);
自己写一个strlen的函数
#include
void mystrlen(int *lengh,const char *str)
{
while(*str!='\0')
{
*lengh+=1;
str++;
}
}
int main()
{
int l=0;
char str[10]="hello";
mystrlen(&l,str);
printf("%d\n",l);
}
字符串的拷贝
strcpy():将右边的字符串完全拷贝到左边的字符串里。而不是覆盖一小部分。
char str1[10]="hello";
char str2[10]="asdaf";
strcpy(str2,str1);
- 注意的问题:
1. 左边字符串的大小必须要大于右边字符串的大小
2. 左边的字符串不能使使用char *p定义出来的。
strncpy():替换字符串前面的字符
#include
#include
int main()
{
char str1[20]="helloasas";
char str2[20]="asaaaworld";
strncpy(str1,str2,5);
printf("%s\n",str1);
}
字符串的比较
strcmp(str1,str2),如果两字符串相同,结果为0.
char str1[10]="hellb";
char str2[10]="hella";
strcmp(str1,str2);
- 如果左边的字符串>右边的字符串,结果是(左边不同字符ascii码减右边对应位置字符ascii码)
- 如果编译器低级
- 左>右,结果=1
- 右>左,结果=-1
strncmp(str1,str2)
#include
int main()
{
char str1[20]="helloasas";
char str2[20]="hellaworld";
int result=strncmp(str1,str2,5);
printf("%d\n",result);o-a
}
字符串链接函数
strcat:会将右边字符串拼接到左边的后面
char str1[10]="hello";
char str2[10]="world";
strcat(str1,str2);
- 注意:左边的字符串要足够大。
strncat():只连接目标行数
#include
int main()
{
char str1[20]="helloasas";
char str2[20]="helloworld";
strncat(str1,str2,5);
printf("%d\n",str1);//helloasashello
}
字符串数组
char str[2][10]={"hello","world"}
指针数组
char *p="123";
char *p1="nihao";
char *str[2]={p,p1};//*str1[2]={"123","hihao"};
程序内存空间分配
栈区:存储局部变量
静态区(全局区):静态变量,全局变量
堆区:存放由程序员调用malloc函数时分配的空间。
文字常量区:常量字符串(只读不能更改)
代码二进制:代码
结构体类型
可以将不同数据类型组合在一起的集合
定义方法
struct 结构体名
{
属性变量;(特征变量)
}
struct Person
{
char name[10];
char sex;
int height;
float score;
};
struct Person//两个加起来算一个数据类型。
//结构体变量的定义
struct Person person;
结构体变量初始方法
.代表‘的’意思。
person.sex='m';
strcpy(person.name,"xxxx");
person.height=180;
person.score=100;
printf("sex=%c\nname=%s\nheight=%d\nscore=%f\n",person.sex,person.name,person.height,person.score);
初始化方法2
struct Person person={"xxx",'w',180,100}
初始化方法3
struct Person person2=person;
内存对齐:
如果结构体里的成员变量都是基本数据类型的成员,那么第一个成员的变量内存从内存偏移量为0的位置,后面的成员变量从内存偏移量是他本身字节数的倍数开始分配。
如果结构体成员变量里面是集合类型,数组,结构体,枚举,那么成员变量。比如struct xxx{char ch,Int score}那么该结构体成员从内存偏移量是该结构体里面最大字节数的成员变量的倍数开始分配。
最后收尾的时候,总的字节数是最大成员变量(字节数)的倍数.
struct Person
{
char sex;//0
int height;//4--7
char ch;8(得9,根据条件3奥球倍数,所以为12)
};
struct Person
{
char sex;//0
char ch[10];//1--10
int height;//12--15
};
printf("%d",sizeof(struct Person));
包含结构体的内存对齐
#include
int main()
{
struct Birthday
{
int year;//0-3
int month;//4-7===double month//8-15
int day;8-11======//16-19=>24
};
struct Person
{
char name[10];0-9
int score;12-15
char sex;16
struct Birthday birth;20-31//32====24-47=>48
};
struct Person person={"xxx",100,'m',{1990,1,1}};
printf("person.name=%s,birthday=%d/%d/%d\n",person.name,person.birth.year,person.birth.month,person.birth.day);
}
无名结构体
struct
{
int a;
char b;
}xx,xx1;
定义这个结构体数据类型的同时定义出来一个变量
struct Student
{
int score;
char sex;
}stu1[2]={{12,'m'},{13,'w'}};
结构体和指针的关系
struct Person;
{
int height;
char sex;
};
struct Person person;
struct Person *p=&person;
(*p).sex='m'
(*p).height='120'
printf("sex=%c,height=%d\n",person.sex,person.height);
p->sex='m'
p->height='120'
printf("sex=%c,height=%d\n",person.sex,person.height);
将现有的数据类型定义成想要的数据类型
typedef
typedef struct Person Person
typedef struct Person * Pstu
typedef struct Stu
{
char name[10];
int num;
}Stu(改结构体名),* Pstu;
struct Student
{
char name[10];
int num;
};
typedef struct Student Student;
Student stu{"xx",10};
printf("name=%s\nnum=%d\n",stu.name,stu.num);
数据类型的定义我们一般放在函数的外面供全局使用。
结构体数组
typedef struct Stu
{
char name[10];
int num;
}Stu;
int main()
{
int i;
Student stu[4]={{"xx",123},{"xx1",123},{"xx",122},{"xx2",124}}
for(i=0;i<4;i++)
{
printf("stu[%d].name=%s,stu[%d].num=%d",i,stu[i].name,i,stu[i].name);
}
}
//编写程序比较结构体名字的大小进行排序
#include
typedef struct Stu
{
char name[10];
int num;
}Stu;
int main()
{
int i,t;
Stu temp;
Stu stu[4]={{"xx3",123},{"xx1",123},{"xx4",122},{"xx2",124}};
for(i=0;i<4;i++)
{
printf("stu[%d].name=%s,stu[%d].num=%d\n",i,stu[i].name,i,stu[i].num);
}
for(i=0;i<3;i++)
{
t=strcmp(stu[i].name,stu[i+1].name);
if(t>0)
{
temp=stu[i];
stu[i]=stu[i+1];
stu[i+1]=temp;
}
}
for(i=0;i<4;i++)
{
printf("stu[%d].name=%s,stu[%d].num=%d\n",i,stu[i].name,i,stu[i].num);
}
}
什么时候形参使用传地址:
在其他的函数空间访问另外一个函数空间里面的数据时,并且是要改变这个内容时。
#include
struct student
{
int num;
char name[10];
};
void changevalue(struct student *p)
{
(*p).num=8;
}
int main()
{
struct student stu;
stu.num=2;
changevalue(&stu);
printf("%d\n",stu.num);
}
//练习:自定义一个结构体数组,对数组里面的信息进行自动输入赋值,再利用选择排序进行整理
struct Student
{
char name[10];
int num;
};