分析两道“利用与堆内存管理有关的函数动态申请空间”习题

笔者大一,对很多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;
 } 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值