一、字符串:
C中没有专门的变量来保存一个字符串,例如:
char a[6]="hello";,计算机会在尾部自动补'\0',所以该字符数组为6个字节。同样,也可以用一个指针来指向字符串常量的首地址,此时不可以改变具体的值,否则会发生段错误,因为该常量不可更改;
#include <stdio.h>
int main()
{
char *p="hello world!";
p=p+3;
printf("%s\n",p);//更改p的起始地址,此时输出结构为lo world!
*p='H';
printf("%s\n",p);//更改常量的值,发生段错误
return 0;
}
若想改变字符串,则先将字符串存储在一个数组变量中,然后进行更改;
当要保存一串数组时,可以使用字符数组指针,格式:
char* name[]={"Apple","Pear","Banana"};
对字符串进行操作实例:
将字符串中的空格去除(此时不可选用scanf函数,因为改函数不识别空格,换gets或fgets函数)
#include <stdio.h>
#include <string.h>
remove_space(char* dest,char* src)
{
int i;
for(i=0;src[i]!='\0';i++)
{
if(src[i]!=' ')
{
*dest=src[i];
dest++;
}
}
*dest='\0';
return;
}
int main()
{
char src[32];
char dest[32];
printf("请输入一个字符串:\n");
gets(src);
remove_space(dest,src);
printf("去除空格为:%s\n",dest);
return 0;
}
1、strcpy、strcat、strcmp函数的使用:
这三个函数为操作字符串函数,使用时需要包含stdstring.h函数,分别是字符串覆盖,尾部添加以及比较函数;
(1) strcpy[char* dest,const char* src]前侧放置的被覆盖函数,后侧放置为覆盖函数,使用例如:
#include <stdio.h>
#include <string.h>
int main()
{
char name[1024];
strcpy(name,"hello");
printf("%s\n",name);
return 0;
}
此时输出结果为hello
(2)同理strcat尾部追加函数则是在前一个字符串后的‘\0’位置开始进行追加,如:
char name[1024]="hello";
strcat(name," world!");
此时打印输出name的结果为:hello world!;
(3)strcmp函数为一个比较函数,比较两个字符串的大小
int strcmp(char *dest,const char* src);
返回值为int类型,从dest指针指向的第一个字符与src指向的第一个字符开始比较,相同则指向下一个,若出现不同,dest较大则返回一个大于0的数,小于则返回一个小于0的数,相等则返回0;
由此来判断两字符串是否相同;
为了加深理解,自己写了一个函数来实现strcmp,strcpy,strcat的功能;
char* strcat_fun(char* dest,char* src)
{
while((*dest)!='\0')
{
dest++;
}
while((*src)!='\0')
{
*dest=*src;
src++;
dest++;
}
*dest='\0';
return dest;
}
int strcmp_fun(char* dest,char *src)
{
int ret=0;
while((*dest)!='\0')
{
if((*dest)==(*src))
{
ret=0;
dest++;
src++;
}else
{
ret=(*dest)-(*src);
break;
}
}
if((*dest)=='\0')
{
ret=-(*src);
}
return ret;
}
char* strcpy_fun(char *dest,char *src)
{
while((*src)!='\0')
{
*dest=*src;
src++;
dest++;
}
return dest;
}
二、结构体
struct student
{
int num;
char name[1024];
};
struct student s={1,"zhang"};
struct student* p=&s;
此时想访问结构体内部的值有两种方法:
(1)p->name p->num;
(2)(*p).name (*p).num;
.与->优先级很高,类似与小括号,使用时需要注意;
当结构体嵌套调用时,只能逐级访问,而不能直接访问;
同时,当结构体需要赋值时,也不能直接赋值,因为没有直接存储结构体的变量,特别是当赋值字符串时,需要使用strcpy进行赋值,而不能直接赋值;
结构体大小的计算:
例如:
如上:第一个结构体,首先short的大小时2,第二个int的大小为4,但因为前面为2不是4的整数倍,所有需要补空即在short类型后补两个字节的空方便对齐,然后填入int类型,之后double类型变量所占字节大小为8个,前面的大小为8,无需补空,总大小为2+2+4+8=16,16是最大类型8的整数倍,所以第一个结构体大小为16
第二个结构体同理,int类型4个字节大小,double为8个,int后面需要补空4个字节,之后为short类型2个,总大小为4+4+8+2=18个,18不为8的整数倍,继续补空至24个,所以第二个结构体的大小为24个字节
三、函数四区
函数四区为数据段、堆区、栈区以及正文
1、数据段
数据段分为未初始化、初始化以及常量区,作用时间为从程序开始到结束
一般存储全局变量、静态变量以及常量
const加静态/全局变量时是放到常量区来存储的
注意:如果用const修饰局部变量,则变为具有常量属性的变量还是存储在栈区
2、栈区
临时数据存储 变量,形参,返回值,函数调用时保护现场的下一行代码的地址等存放在这个地方
3、堆区
由用户自己管理使用的区间,通过malloc函数来申请空间,free函数来释放空间
一般存放一些较大的数据,以及需要长时间使用的数据
4、正文
存放代码正文,只读属性
在程序运行时,专门申请一段内存空间,分为以上四区,一旦程序结束,该段内存释放
四、文件的读写操作
打开文件fopen
二进制读写fread fwrite rb/wb
文本读写 fprintf/fscanf r/b
使用格式:
fopen(pathname(文件路径),打开模式)成功的话返回一个FILE* 的地址表示文件的起始地址,若为NULL则用perror报错;例如:
FILE* fp=NULL;
fp=fopen("./st.txt","wb");
if(fp==NULL)
{
perror("open");
}
fwrite 返回值为写入的个数
fwrite(写文件的起始地址,元素大小,元素个数,文件地址);
fread(存放数据内存起始地址,数据的单位大小,个数,文件地址);
若读完返回值为0;