字符串转其他型字符
变量定义:
atoi:字符串 转 整数
int atoi(const char *str1);
atof:字符串 转 浮点数
double num2 = atof(str2);
atol:字符串 转 长整数
long num3 = atol(str3);
使用这类函数进行转换,要求,原串必须是可转换的字符串。
int main(void) {
char str1[] = "10";
int num1 = atoi(str1);
printf("num1=%d\n",num1);
char str2[] = "0.123f";
double num2 = atof(str2);
printf("num2=%.2lf\n",num2);
char str3[] = "123L";
long num3 = atol(str3);
printf("num3=%ld\n",num3);
system("pause");
return EXIT_SUCCESS;
}
局部变量:
定义在函数内部的变量。
作用域:从定义位置开始,到包裹该变量的第一个右大括号结束。
void test1(void) {
if (1) {
int a = 10;
}
printf("a=%d\n",a); //此时a无法打印,因局部变量原因不承认IF中的a在本段结束
}
if语句,for循环,while循环等中的变量定义仅在循环括号中有定义
全局变量:
概念:定义在函数外部的变量
作用域:从定义位置开始,到本文件内部。其他文件如果想使用,可以通过声明将作用域导出。
extern int a; //显示声明,将其他文件的定义值导出到此文件
void test1(void) {
printf("a=%d\n",a);
}
int main(void) {
printf("a=%d\n", a);
system("pause");
return EXIT_SUCCESS;
}
//同时其他文件定义a的值
static全局变量:
定义语法: 在变量定义之前添加static关键字。 static int a=10;
作用域:被限制在本文件内部,不允许通过声明导出到其他文件。//即加上静态就无法从别的文件中导出定义。
static局部变量:
定义语法:在局部变量定义之前添加static关键字。
特性:静态局部变量只定义一次,在全局位置。 //通常用来做计数器。
作用域:从定义位置开始,到包裹该变量的第一个右大括号结束。
全局函数:
定义语法:函数原型+函数体
static函数:
定义语法:static+函数原型+函数体
static函数 只能在 本文件内部使用。其他文件即使声明也无效。
生命周期:
局部变量:从变量定义开始到函数调用完成。----函数内部
全局变量:程序启动开始,程序终止结束。 ----程序执行期间
static局部变量:程序启动开始,程序终止结束 -----程序执行期间
static全局变量:程序启动开始,程序终止结束 -----程序执行期间
全局函数:
内存4区模型:
代码段:text段,程序源代码(二进制形式)
数据段:只读数据段.rodata段,初始化数据段.data ,未初始化数据段.bss
stack:栈。在其中开辟 栈帧。 Windows 1m-----10m LINUX:8m-----16M
heap:堆。给用户自定义数据提供空间。约1.3G+
命名冲突就近原则:
例1:
int m = 100;
int main(void) {
int m = 30;
printf("m=%d\n",m);
}
输出:
m=30
例2:
int main(void) {
int m = 30;
for (size_t m = 0; m < 10; m++) {
printf("m=%d\n",m);
}
printf("m=%d\n",m);
system("pause");
return EXIT_SUCCESS;
}
输出:
m=0
m=1
m=2
m=3
m=4
m=5
m=6
m=7
m=8
m=9
m=30
堆空间的申请和使用:
开辟释放heap空间:
void *malloc(siuze_t size); 申请size大小的空间
返回实际申请到的内存空间首地址。【我们通常拿来当数组用】
void free(void*ptr);释放申请的空间
int main(void) {
int* p = (int*)malloc(sizeof(int) * 10);
if (p == NULL) {
printf("malloc error\n");
return -1;
}
//申请malloc空间
for (size_t i = 0; i <10; i++)
{
p[i] = i + 10;
}
//写数据到malloc空间
for (size_t i = 0; i < 10; i++)
{
printf("%d ",*(p+i));
}
//读出malloc空间中的数据
free(p);
//释放申请的内存
}
使用heap堆空间:
空间时连续。当成数组使用。
free后的空间,不会立即失效,通常将free后的地址重置为NULL。
free地址必须是malloc申请地址。否则出错
如果malloc之后的地址一定会变化,那么使用临时变量tmp保存。
二级指针malloc空间:
int main(void) {
int** p = malloc(sizeof(int *)*10);
//int **p ==>int *p[10];==>[int *,int *,int *]
for (size_t i = 0; i < 10; i++)
{
p[i]=malloc(sizeof(int) * 5);
}
for (size_t i = 0; i <10; i++)
{
for (size_t j = 0; j<5; j++)
{
p[i][j] = i + j;
}
}
//使用空间 -- 写
for (size_t i = 0; i < 10; i++)
{
for (size_t j = 0; j < 5; j++)
{
printf("%d",*(*(p+i)+j)); //p[i][j]==*(p+i)[j]==*(*(p+i)+j)
}
}
//使用空间 -- 写
for (size_t i = 0; i < 10; i++)
{
free(p[i]);
p[i] = NULL;
}
//释放空间时, 先释放内层空间。
free(p);
p = NULL;
//释放外层空间
system("pause");
return EXIT_SUCCESS;
}
申请外层指针:char **p=malloc(sizeof(char)*5);
申请内层指针:
for (i=0;i<5;i++)
{
p[i]=(char*)malloc(sizeof(char)*10);
}
使用:
for (i=0;i<5;i++)
{
strcpy(p[i],"helloheap");
}
释放内层:
for (i=0;i<5;i++)
{
free(p[i]);
}
释放外层:
free(p);
fprintf()函数:
printf---sprintf---fprintf: 都是变参函数:参数形参中,有“...”,最后一个固参通常是格式描述串(包含格式匹配符),函数的参数个数、类型、顺序由固参决定。
fprintf()和printf()一样工作.
printf是打印输出到屏幕,fprintf是打印输出到文件。
fprintf()的返回值是输出的字符数,发生错误时返回一个负值.
printf("hello");
printf("%s","hello");
printf("ret=%d+%d\n",10,5);
printf("%d=%d%c%d\n","10+5",10,'+',5); ---》屏幕
char buf[1024];
sprintf(buf,"%d%c%d\n",10+5,10,'+',5); -->buf中
FILE *fp=fopen();初始化
fprintf(fp,"%d%c%d\n",10+5,10,'+',5); --》fp对应的文件中
void write_file() {
FILE* fp = fopen("abc.c","w");
if (!fp) {
perror("fopen error");
return -1;
}//fp ==NULL
printf("%d%c%d=%d\n",10,'*',7,10*7);
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}
int main(void) {
write_file();
system("pause");
return EXIT_SUCCESS;
}
perror函数简介
perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和errno所对应的错误一起输出。
scanf---sscanf---fscanf
scanf("%d",&m); 键盘---》m
char str[ ]=="98";
sscanf(str,"%d",&m); str---》m
FILE *fp=fopen("r");
fscanf(fp,"%d",&m); fp指向的文件中 --》m
例1:
void write_file() {
FILE* fp = fopen("abc.c","w");
if (!fp) {
perror("fopen error");
return -1;
}//fp ==NULL
printf("%d%c%d=%d\n",10,'*',7,10*7);
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}
void read_file() {
int a, b, c;
char ch;
FILE* fp = fopen("abc.c","r");
if (!fp) //fp=NULL
{
perror("fopen error");
return -1;
}
fscanf(fp, "%d%c%d=%d\n", &a, &ch, &b, &c);
printf("%d%c%d=%d\n",a,ch,b,c);
fclose(fp);
}
例2:
void write_file() {
FILE* fp = fopen("abc.c","w");
if (!fp) {
perror("fopen error");
return -1;
}//fp ==NULL
fprintf(fp, "%d\n", 10);
fprintf(fp, "%d\n", 8);
fprintf(fp, "%d\n", 6);
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}
void read_file() {
int a;
FILE* fp = fopen("abc.c","r");
if (!fp) //fp=NULL
{
perror("fopen error");
return -1;
}
fscanf(fp, "%d\n", &a);
printf("%d\n",a);
fscanf(fp, "%d\n", &a);
printf("%d\n", a);
fscanf(fp, "%d\n", &a);
printf("%d\n", a);
fscanf(fp, "%d\n", &a);
printf("%d\n", a);
fclose(fp);
}
输出第四次时与之前第三次一样,但实际这属于边界溢出。
int fscanf(FILE * stream,const char * format,...);
1.边界溢出。存储读取数的数据空间。在使用之前清空。
2.fscanf函数,每次在调用时都会判断下一次调用是否匹配参数2,如果不匹配提前结束文件读操作。(feof(fp))
fgets:
C库函数char *fgets(char *str, int n, FILE *stream) 从指定的流stream读取一行,并把它存储在 str 所指向的字符串字符串字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
void read_file3() {
char buf[1024];
FILE* fp = fopen("abc.c", "r");
if (!fp)//fp=NULL
{
perror("fopen error");
return -1;
}
while (1) {
fgets(buf, 1024, fp);
printf("%d\n",a);
if (feof(fp))
break;
}
fclose(fp);
}
文件排序练习
void write_rand() {
FILE* fp = fopen("text123.txt", "w");
if (!fp) {
perror("fopen error");
return -1;
}
srand(time(NULL)); //随机数种子
for (size_t i = 0; i < 10; i++){
rand() % 100; //0 - 99
}
fprintf(fp,"%d\n",rand()%100);
}
void BubbleSort(int* src, int len) {
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (src[j] > src[j + 1]) {
int tmp = src[j];
src[j] = src[j + 1];
src[j + 1] = tmp;
}
}
}
}
//排序
void read_rand() {
int arr[10], i = 0; //定义循环因子给初值
int tmp;
FILE* fp = fopen("text123.txt","r");
if (!fp) {
perror("fopen error");
return -1;
}
while (1) {
fscanf(fp, "%d\n",&arr[i]);
i++;
if (feof(fp)) {
break;
}
}
for (size_t i = 0; i < 10; i++){
printf("%d\n",arr[i]);
}
BubbleSort(arr, sizeof(arr) / sizeof(arr[0])); //排序
fclose(fp);
fp = fopen("text123.txt", "w"); //清空原未排文件
if (!fp) {
perror("fopen error");
return -1;
}
for (size_t i = 0; i < 10; i++) {
printf("%d\n", arr[i]);
}//排好序的文件
fclose(fp);
}
int main() {
read_rand();
system("pause");
return EXIT_SUCCESS;
}
fwrite函数:
fgets--fputc
fgets--fputs
fprintf-fscanf
默认处理文本文件。用来处理二进制文件
fwrite()函数:写出数据到文件中。
size_t发write(const void *ptr,size_t size,size_t nmemb,FILE*stream);
参数1:待写出数据的地址
参数2:待写出数据的大小
参数3:写出的个数
---参数2 x 参数3=写出数据的总大小
返回值:
成功:一直是参数3的值
失败:0
typedef struct student {
int age;
char name[10];
int num;
}stu_t;
int main(void) {
stu_t stu[4] = {
18,"lzx",10,
19,"wzh",20,
20,"wxf",30,
21,"cl",40,
};
FILE* fp = fopen("text123.txt", "w");
if (!fp) {
perror("fopen error");
return -1;
}
int ret =fwrite(&stu[0], sizeof(stu_t), 1,fp);
if (ret == 0) {
perror("fwrite error");
return -1;
}
printf("ret==%d\n",ret);
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}
输出:
ret ==1
fread函数:
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
参数1:读取到的数据存储的位置
参数2:一次读取的字节数
参数3:读取的次数 ----参数2 x 参数3 =读取数据的总大小
参数4:文件
返回值:
成功:参数3
失败:0
0:读取失败 --feof(fp)--到达文件结尾
typedef struct student {
int age;
char name[10];
int num;
}stu_t;
void write_struct() {
stu_t stu[4] = {
18,"lzx",10,
19,"wzh",20,
20,"wxf",30,
21,"cl",40,
};
FILE* fp = fopen("text123.txt", "w");
if (!fp) {
perror("fopen error");
return -1;
}
int ret = fwrite(&stu[0], sizeof(stu_t), 1, fp);
if (ret == 0) {
perror("fwrite error");
return -1;
}
printf("ret==%d\n", ret);
fclose(fp);
}
void read_struct() {
FILE* fp = fopen("text123.txt", "r");
if (!fp) {
perror("fopen error");
return -1;
}
stu_t buf[1024]; //stu_t *buf=malloc(sizeof(stu_t)*1024);
int ret=fread(&buf, sizeof(stu_t), 1, fp);
printf("ret=%d\n",ret);
printf("age=%d,name=%s,num=%d\n",buf.age,buf.name,buf.num);
fclose(fp);
}
int main(void) {
read_struct();
system("pause");
return EXIT_SUCCESS;
}
大文件拷贝实现:
已知一个任意类型的文件,对该文件复制,产生一个相同的新文件。
1.打开两个文件,一个“r”,另一个“w”
2.从r中fread,fwrite到w文件中。
void myfile_cp() {
FILE* rfp = fopen("C:\\XXXX\\XXX.TXT","r");
FILE* wfp = fopen("C:\\XXXX\\XXX.TXT", "w");
char buf[128] = { 0 }; //缓冲区
int ret = 0;
while (1) {
ret = fread(bug, 1, sizeof(buf), rfp);
if (ret == 0) {
break;
}
fwrite(buf,1,ret,wfp);
}
fclose(wfp);
fclose(rfp);
}
int main(void) {
myfile_cp();
printf("---finish\n");
system("pause");
return EXIT_SUCCESS;
}
随机位置 读:
文件读写指针
fseek():
int fseek (FILE *stream, long offset, int whence);
参数1:文件
参数2:偏移量(矢量:+向后, -向前)
参数3:SEEK_SET:文件开头位置
SEEK_CUR:当前位置
SEEK_END:文件结尾位置
ftell():
获取文件读写指针的位置
long ftell(FILE *stream);
返回:从文件当前读写位置到起始位置的偏移量。
借助ftell+fseek(seek_end):来获取文件大小。
rewind():
回卷文件读写指针,将读写指针移到起始位置。
void rewind(FILE*stream):
typedef struct student {
int age;
char name[10];
int num;
}stu_t;
int main(void) {
stu_t stu[4] = {
18,"lzx",10,
19,"wzh",20,
20,"wxf",30,
21,"cl",40,
};
stu_t s1;
FILE* fp = fopen("text1.txt", "wb+");
if (!fp) {
perror("fopen error");
return -1;
}
int ret=fwrite(&stu[0],1,sizeof(stu),fp); //以二进制形式写入
fseek(fp, sizeof(stu_t), SEEK_SET); //从文件起始位置开始,向后偏移一个stu结构体
ret=fread(&s1, 1, sizeof(s1), fp);
rewind(fp); //将文件读写指针回卷到起始位置。
printf("ret=%d\n",ret);
printf("age=%d,name=%s,num=%d\n",s1.age,s1.name,s1.num);
int len=ftell(fp); //获取文件当前偏移位置到文件起始位置的偏移量。
fseek(fp, 0, SEEK_END);//获取文件大小
len = ftell(fp);
printf("文件大小为:%d\n", len);
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}
LINUX和windows的文件区别:
1.对于二进制文件操作,Windows使用“b”,Linux下二进制和文本没区别。
2.windows下,回车\r ,换行\n。LINUX下\r\n会转换成\n
3.对文件指针,先写后读。windows和linux效果一致。
先读后写。LINUX无需修改,windows下需要在写操作之前使用fseek(fp,0,SEEK_CUR);来获取文件读写指针,使之生效。
int main(int argc,char *argv[]) {
FILE* fp = fopen("text1.txt", "r+");
char buf[6] = { 0 };
char* ptr = fgets(buf, 6, fp);
printf("buf=%s,ptr=%s\n,ptr,buf");
int ret = fputs("AAAAA",fp);
printf("ret=%d\n",ret);
fclose(fp);
return 0;
system("pause");
}