内存
分配内存的函数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"