笔者大一,对很多c语言知识尚不是很能理解,本人在做这两道题目的时候花了很多时间,因此有必要重新回顾这两道题来加深印象。本次题目对应《C程序设计:方法与实践》第九章习题9.6,9.7.
由于9.7是在9.6的基础上完成的,因此先来分析一下9.6。
习题9.6 利用堆内存管理函数,编写一个程序,构建一个字符数组来存储任意长度的字符串,要求根据字符串的长度来动态申请空间。
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *str; char c;
int n=0;
str=(char *)malloc(10*sizeof(char));
10是任意设置的,因为不知道字符数组的长度,因此先给它假设一个长度值,不够的话以后再重新分配更大的连续内存区域。
之所以没有直接设char str[1000]类似的数组,是因为在对数组进行扩充的时候,不是设置一个有固定大小的数组,这个数组不能通过realloc进行扩容,因为realloc和malloc都是对堆进行操作,而数组声明后是在可执行文件映像中。而通过假设一个数,比如10,先分配空间,到时候不够了再realloc。
while((c=getchar())!='\n')
{
n++;
if(n>10)
str=(char *)realloc(str,n*sizeof(char)); //对前面的malloc进行realloc
str[n-1]=c;
}
str[n]='\0';
puts(str);
free(str); //记得释放堆内存区域
return 0;
}
习题9.7 有一个文本文件,其中每一行有一个整数,但是事先不知道有多少行。编写一个程序,从文本文件中读取所有的整数存放到一个整型数组中。数组大小开始可以设定一个初始值,如果大小不够,再以一定的步长进行动态扩充。
分析:
1.首先要知道怎么从文本文件中读取每一行的整数。我设置的文本文件较为简单,只有单纯的几行整数,且每一行只有一个整数。
2.同时还要了解:fscanf是在文件里读取指定格式的数据,遇到空格和换行符停止,正常情况返回它读取的字符的个数.异常情况返回0。
3.因为该文本文件比较有规律,因此选用fscanf而不选用fgets。
(1)最终答案如下:(先略过,先看(2)(3)再来得到(1))
#include<stdio.h>
#include<stdlib.h>
int main(){
int i=0,*p,n,t;
p=(int *)malloc(4*sizeof(int));
FILE * fp;
fp=fopen("file.txt","r");
if(fp==NULL)
{
printf("无法打开文件!\n");
exit(0);
}
while(fscanf(fp,"%d",&t)==1)
{
if(i<4)
p[i]=t;
if(i>=4)
{
n=i+1;
p=(int *)realloc(p,n*sizeof(int));
p[i]=t;
}
i++;
}
for(i=0;i<n;i++)
printf("%d\n",p[i]);
free(p);
fclose(fp);
return 0;
}
(2)
#include<stdio.h>
#include<stdlib.h>
int main(){
int i=0,a[100],n,*p; /*1.这里犯了一个9.6题提到的问题,不是设置一个有固定大小的数组。2.而数组名的本质是个指针,所以声明一个指针p就可以了。p指向的堆中分配的内存的大小就是根据读取的字符个数来决定的。*/
p=a;
FILE * fp;
fp=fopen("file.txt","r");
if(fp==NULL)
{
printf("无法打开文件!\n"); exit(0);
}
while(fscanf(fp,"%d",&a[i])==1) //利用fscanf的返回值来判断循环条件
{
fscanf(fp,"%d",&a[i]);/*最终结果把这一行删掉了,为什么要删除这一行?因为while里已经有了。。*/
i++;
if(i>=100)
{
p=(int *)realloc(a,n*sizeof(int));
}
}
n=i; /*但这样依然有问题,有循环上的问题,比如n的位置放错了,应该在while里。而且相当于对a[i]扩充,不可以这样用。至此,重新修改跳转(3)*/
for(i=0;i<n;i++)
printf("%d\n",a[i]);
free(a);
fclose(fp);
return 0;
}
(3)#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=0,*p,n;
p=(int *)malloc(4*sizeof(int));
FILE * fp;
fp=fopen("file.txt","r");
if(fp==NULL)
{ printf("无法打开文件!\n"); exit(0); }
while(fscanf(fp,"%d",&p[i])==1)
{
fscanf(fp,"%d",&a[i]);
if(i>=4)
{
n=i+1;
p=(int *)realloc(p,n*sizeof(int));
}
i++; //当i=3,while(...&p[3]==1)后,i++=4,在while判断一下,发现&p[4]并没有申请内存,所以这个循环条件有问题。经过思考,完成(1)。
}
for(i=0;i<n;i++)
printf("%d\n",p[i]);
free(p);
fclose(fp);
return 0;
}