C语言笔记(28)柔性数组及文本相关知识

#include <stdio.h>
struct S
{
	int n;
	int arr[];//柔性数组成员
};
int main()
{
	int sz = sizeof(struct S);
	printf("%d\n", sz);
	return 0;
}

柔性数组特点:

1.结构中的柔性数组成员前面必须至少一个其他成员。

2.sizeof返回的这种结构大小不包括柔性数组的内存。

3.包含柔性数组成员的结构用malloc()函数进行内存的动态分配没并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

柔性数组的使用:

#include <stdio.h>
struct S
{
	int n;
	int arr[];
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 40);
	if (ps == NULL)
	{
		return 1;
	}
	ps->n = 100;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d", ps->arr[i]);
	}
	realloc(ps, sizeof(struct S) + 80);
	struct s* ptr = (struct S*) ps;
	if (ptr != NULL)
	{
		ps = ptr;
	}
	//释放
	free(ps);
	ps = NULL; 
	return 0;
}

原理图:

普通方式:

#include <stdio.h>
struct S
{
	int n;
	int* arr;
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		return 1;
	}
	ps->n = 100;
	ps->arr = (int*)malloc(40);
	if (ps->arr == NULL)
	{
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d", ps->arr[i]);
	}
	//扩容80字节
	int* ptr = (int*)realloc(ps->arr, 80);
	if (ptr == NULL)
	{
		return 1;
	}
	return 0;
}

原理图:

C语言结构体里的成员数组和指针,陈皓

文件:

程序设计中,文件谈的有两种:程序文件,数据文件。

程序文件:包括源程序文件(后缀为.c),目标文件(widows环境后缀为.obj),可执行程序(windows环境后缀为.exe)

数据文件:文件的内容不一定是程序,二十程序运行时的读写的数据,比如程序运行需要从中读取数据的文件或者输出内容的文件。

文件名包括三部分:

文件路径+文件名主干+文件后缀

每个被使用的文件都会在内存开辟相应区域

fopen创建文件信息区并将起始地址返回来用指针接受FILE*(文件指针)

通过FILE*可以找到文件信息去,又可以简介维护文件

#include <stdio.h>
FILE* fopen(const char* filename, const char* mode);
int main()
{
	FILE* pf = fopen("text.txt", "w");
	return 0;
}

文件打开失败:

#include <string.h>
#include <errno.h>
#include <stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//关闭文件
	pf = NULL;
	return 0;
}

//写文件
char i = 0;
for (i = 'a', i <= 'Z'; i++)
{
    fputc(i, pf);
}

//读文件(一个一个读)
int ch = fgetC(pf);
printf("%c\n", ch);

//全读
int ch = 0;
while ((ch = fgetC(pf)) != EOF);
printf("%c", ch);

写文件时如果文件本身有内容会直接清空写入

//读一行数据

char arr[20];

fgets(arr, 5, pf);

printf("%s\n",arr);

fgets读取数据会放入\0

如读hello,若5个字节,只会都hell,最多读20个

#include <stdio.h>
fprinf()
struct S
{
	char arr[10];
	int age;
	float score;
};
int main()
{
	struct S s = { "zhangsan", 25, 50.5f };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fprintf(pf, "%s %d %f", s.arr, s.age, s.score);
	fclose(pf);
	pf = NULL;
	return 0;
}


fsanf(pf, "%s%d%f", s.arr, &(s.age), &(s.score));
printf( "%s%d%f", s.arr, &(s.age), &(s.score));
//fprintf(stdout...)打印到屏幕上

原理图:

任何一个C程序,只要运行起来就会默认打开三个系统:

FILE* stdin 一个标准输入流(键盘)

FILE* stdout 输出(屏幕)

FILE* stderr 错误(屏幕)

二进制输入输出:

#include <stdio.h>
struct S
{
	char arr[10];
	int age;
	float score;
};
int main()
{
	struct S s = { "zhangsan", 25, 50.5f };
	//以二进制的形式写到文件中
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//以二进制形式写
	fwrite(&s, sizeof(struct S), 1, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

fwrite

size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream);

fread

size_t fread(void* ptr, size_t size, size_t count, FILE* stream);

159.19:00 改通讯录

scanf是针对标准输入的格式化输入语句

printf是针对标准输出的格式化输出语句

fscanf是针对所有输入流的格式化输入语句

fprintf是针对所有输出流的格式化输出语句

sprintf:把一个格式化的数据写到字符串中,本质是把一个格式化的数据转换成字符串,

printf("%s", buf);

sprintf(buf,"%s%d%f", s.arr...);

//"zhangsan 20 55.500000"

按字符串来打印

sscanf:从一个字符串转化出一个格式化数据

sscanf(buf, "%s %d %f", tmp,arr....);

//从字符串buf中获取一个格式化数据到tmp

printf("%s%d%f", tmp.arr...)

文件和二进制文件

根据数据的组织形式,数据文件被称为文本文件或者二进制文件。

数据在内存中以二进制的形式存储,如果不加转化的输出到外存,就是二进制文件。

如果要求在外存上以ASCII码的形式存储,则需要在存储的文件就是文本文件。

一个数据在内存中是怎样存储的?

字符一律以ASCII码的形式存储,数值型数据即可以用ASCII码形式存储,也可以使用二进制形式存储。

如有整数1000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节

测试代码:

#include <stdio.h>
int main()
{
	int a = 10000;
	FILE* pf = fopen("test.txt", "wb");
	fwright(&a, 4, 1, pf);
	//二进制形式写到文件中
	fcloase(pf);
	pf = NULL;
	return 0;
}

文件读取结束判定:

被错误使用的feof

牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件是否结束。

而是应用于当文件读取结束时,判断是读取失败结束,还是遇到文件尾结束。

1.文本文件读取时否结束,判断返回值是否为EOF(fgetc),或NULL fgets

例如:

fgetc判断是否为EOF

2.二进制文件读取结束判断,判断返回值是否小于实际要读个数,例如:fread判断返回值是否小于实际要读个数

#include <stdio.h>
#include <windows.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcdef", pf);
//先将代码放在输出缓冲区
	printf("睡眠10s写好数据,打开头文件,发现无内容\n");
	Sleep(10000);
	printf("刷新缓冲区");
	fflush(pf);
	//刷新缓冲区时,才会将输出缓冲区的数据写到文件
	printf("在睡眠10s,打开,有内容");
	Sleep(10000);
	fclose(pf);
	//在屏蔽文件时,也会刷到新缓冲区
	pf = NULL;
	return 0;
}

结论:因为有缓冲区的存在,C语言在操作文件时,需要做刷新缓冲区或在文件操作结束时关闭文件,若不做可能导致读写文件的问题。

程序环境分为两个:翻译和执行

编译器:cl.exe

链接器:link.exe

预处理的操作:

1.头文件的包含

2.define定义符号的替换

3.注释

文本操作

编译操作

gcc test.i-s

生成 test.s

把C语言代码转换成汇编代码

语法分析一词法分析——符号汇总——语义分析

汇编操作:

gcc test.s ——生成了test.

把汇编代码转成二进制指令,形成符号表

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千度vea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值