内存

分配内存的函数calloc,malloc
| 定义于头文件 <stdlib.h> | 功能 | 
|---|---|
| malloc | 分配内存(函数) | 
| calloc | 分配并清零内存(函数) | 
| realloc | 扩充之前分配的内存块(函数) | 
| free | 归还还之前分配的内存(函数) | 
| aligned_alloc(C11) | 分配对齐的内存(函数) | 
函数原型
void *malloc(unsigned int size)  //注意使用时,若要4个int类型数据空间需要使用:4*sizeof(int)也就是16
void* calloc( size_t num, size_t size );   //这里参数则是(4,sizeof(int)),参数规定把数量和数据类型分开
 
其中数据类型size_t可以简单理解为一个无符号整型,
 
 主要是 malloc 和 calloc 的区别。 calloc 会申请内存,并全初始化为 0;而 malloc 只申请内存,并不作初始化。
#include <stdio.h>   
#include <stdlib.h> 
 
int main(void) 
{
    int *p1 = malloc(4*sizeof(int));  // 足以分配 4 个 int 的数组
    int *p2 = malloc(sizeof(int[4])); // 等价,直接命名数组类型
    int *p3 = malloc(4*sizeof *p3);   // 等价,免去重复类型名
 
    if(p1) {
        for(int n=0; n<4; ++n) // 置入数组
            p1[n] = n*n;
        for(int n=0; n<4; ++n) // 打印出来
            printf("p1[%d] == %d\n", n, p1[n]);
    }
 
    free(p1);
    free(p2);
    free(p3);
}
 
可以利用这种动态分配内存和scanf函数得到一个动态长度的数组
代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
	int n=0,i;
	int *pa;
	printf("请输入数组长度:");
  	scanf("%d",&n);
	pa = (int *)calloc(n,sizeof(int));   //指针指向分配空间的首地址
	for(i=0;i<n;i++){
		scanf("%d",&pa[i]);
	}
	
	for(i=0;i<n;i++){
		printf("输入的数据是:%d\n",pa[i]);
	}
	free(pa);  //释放pa指针
	for(i=0;i<n;i++){
		printf("输入的数据是:%d\n",pa[i]);   //这里的指针将指向不定的地址
	}
	system("pause");
   
   return 0;
}
 
文件操作fopen,fclose,FIL
遇到的问题总结
 1. 字符串使用双引号"",字符赋值使用单引号'',(长时间不用c忘了)
 2. 判断语句(fp=fopen("fiel.txt","r+"))==NULL;的括号不能少,否则会出现先逻辑判断后赋值,这样编译不通过
 3. 判断读取文件是否正确一定使用"r"或"r+"模式,因为另外模式都会新建,
 4. 在打开文件读取后想要写入,"一定"使用fseek定位文件指针才行
 5. 一个奇怪的现象,a+模式:写入只是指针移动,不能修改本来的文本;但读取可以从全部文本最开始
 6. 字符串的写入都是自动在结尾包含了\0结束字符,所以指针会比字符串多移动一位
 7. 在r+模式下既可以对原始文本插入,也可以读取,但写入也要满足第4条
 
文件打开函数的模式
FILE *fp;
fp = fopen("路径","打开方式")
 

对文本字符操作的函数
具体功能可查看:https://zh.cppreference.com/w/c/io
 
函数使用实例
如果文件不存在可能会导致编译出现,run: line 1: 3 Segmentation fault (core dumped) ./a.out
Exited with error status 139
读取命令实例
file.txt
123456789
#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE *fp;
	char f_getc,f_gets[4],f_read[4],f_scanf[4];  
	char f_getc,f_gets[5],f_read[8],f_scanf[4];  //换成这句就和预期结果一样了 
	fp = fopen("file.txt","r");
	
	f_getc = fgetc(fp);
	printf("fgetc: %c\n",f_getc);
	
	rewind(fp);
	fgets(f_gets,5,fp);  //这里的“一定”要是一个字符串数组
	printf("fgets:%s\n",f_gets);  //得到n-1个字符,最后一个自动填充\0
	
	fflush(fp);
	fseek(fp,0,0);
	fread(f_read,sizeof(char),3,fp);     //这里读取有问题,但单独使用没问题
	printf("fread: %s\n",f_read);
	//fflush(fp);
	rewind(fp);
	fscanf(fp,"%s",f_scanf);  
	printf("f_scanf: %s\n",f_scanf);
	fclose(fp);
	printf("*************************************");
	printf("文件中全部字符!!!\n");
	system("type file.txt ");   //这里会全部显示一次
	printf("\n");
	system("pause");	
	return 0;
}
 
参考:https://editor.csdn.net/md/?articleId=128229605
 
 参考:https://zh.cppreference.com/w/c/io,https://blog.csdn.net/qq_26768741/article/details/50933598,https://blog.csdn.net/qq_45858169/article/details/103704389
 经过尝试和查找资料发现,确实是有缓存中字符的问题,也有一个错误的地方,fread是针对读取的二进制流文件读取,但不是造成这种显示的主要原因;而最主要的原因是读取字符的数组不够,导致读取数据时,没有将终止符或回车符放入字符串,导致输出时在变成输出缓存中读取了数据,为了深入解释这个输出异常的原因,单独分开一个文件中,测试和分析
“+”模式添加的不同
#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE *fp;
	char b;
	//每次测试保证txt文件中只"有123456"这6个字符;
	fp=fopen("file.txt","a+");   //只仅仅修改这里的模式为a+和a,和保证txt开始文本只有123456
	rewind(fp);  //指针在文件开始
	b = fgetc(fp);
	printf("第一次读:%c\n",b);
	fseek(fp,2,0);
	printf("第二次读:%c\n",fgetc(fp));
	fseek(fp,2,0);
	fputs("sag",fp);
	printf("第三次读:%c\n",fgetc(fp));
	fclose(fp);
	system("type file.txt ");  //只是在cmd窗口显示文本内容,懒得每次打开txt查看
	printf("\n");
	system("pause");	
	return 0;
}
 
显示结果a+和a对比分析:
a模式没有读取数据的功能,但能写入,a+模式有读写的功能,但写指针和读指针不是同一位置,而且写文本时会同时移动两个指针,但会一直在文档结尾追加
 
a+可读写的文件出现的问题
一次写入命令后,若不定位指针,那么紧接着的读取命令也会写入;a+模式下,文档最后写入了6。因此,需要注意每次读取和写入文本命令转换时重新使用feek(fp,n,0)定位
 
r+模式下
读和写命令转换时也会出现问题,
#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE *fp;
	char a[4],b;
	fp=fopen("file.txt","r+");
	rewind(fp);
	b = fgetc(fp);
	printf("第一次读:%c\n",b);
	fseek(fp,2,0);
	printf("第二次读:%c\n",fgetc(fp));
	fseek(fp,1,0);
	fputs("sa",fp);
	//fseek(fp,2,0);
	printf("第三次读:%c\n",fgetc(fp));
	fclose(fp);
	system("type file.txt ");
	printf("\n");
	system("pause");	
	return 0;
}
 
下图中的,虽然是fgetc导致的5被写入,但通过fgetc写入的描述并不准确,只是将5读入缓存,而fputs函数在写入的字符串最后也自动添加换行“\n”和终止符“\0”,因此输入的字符变成了"sa5"




















