
- 题目概述:
- 输入格式:
- 输出格式:
- 输入输出样例:
- C语言题解:
- 错误的运行结果:
- 错误问题的分析与定位:
- C库的malloc函数讲解:
- 函数原型:
- 函数形参:
- 函数的返回值:
- 内存的释放:
- 内存释放需要注意野指针:
- Bug定位
- 数组与指针的区别:
- 解决Bug
- 正确的此题题解代码
### 题目描述:
某医院进行一项研究,想知道某项疾病是否与年龄有关。因此对以往的诊断记录进行整理,统计 0-18 、 19-35 、 36-60、 61 及以上这四个年龄段的患者人数占总患者人数的比例
输入格式:输入共 22 行。
第一行包含一个整数 NN(0
第二行包含 NN 个整数,代表这 NN 个患者就诊时的年龄。
输出格式:输出共 44 行。
第 11 行包含一个百分数,这个百分数保留小数点后 22 位,代表 0-180−18 岁这个年龄段的患者人数占总患者人数的比例。
第 22 行包含一个百分数,这个百分数保留小数点后 22 位,代表 19-3519−35 岁这个年龄段的患者人数占总患者人数的比例。
第 33 行包含一个百分数,这个百分数保留小数点后 22 位,代表 36-6036−60 岁这个年龄段的患者人数占总患者人数的比例。
第 44 行包含一个百分数,这个百分数保留小数点后 22 位,代表 6161 岁及以上这个年龄段的患者人数占总患者人数的比例。
输入输出样例: C语言题解:首先让我们先来看看如下的代码解题:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main() {
int N;
scanf("%d", &N);
int *People = (int *) malloc(sizeof(int) * N);
int *num = (int *) malloc(sizeof(int) * 4);
printf("%d\n", sizeof(num));
memset(num, 0, sizeof(num));
for (int i = 0; i < N; ++i) {
scanf("%d", &People[i]);
if (0 <= People[i] && People[i] <= 18) {
num[0]++;
} else if (19 <= People[i] && People[i] <= 35) {
num[1]++;
} else if (36 <= People[i] && People[i] <= 60) {
num[2] += 1;
// printf("%d\n", num[2]);
} else if (People[i] >= 61) {
num[3]++;
}
}
for (int i = 0; i < 4; ++i) {
printf("%.2lf%%\n", 100.0 * num[i] / N);
}
free(People);
free(num);
return 0;
}
错误的运行结果:
发现为啥我都开辟了内存,并相应对内存进行了清空 *** 作,可num变量的值还是感觉怎么还是这么奇奇怪怪呢?不要急,来听听我下回分解,嘻嘻
错误问题的分析与定位: C库的malloc函数讲解:C语言编程环境使用本函数之前需要需要使用包含个头文件#include
C库的malloc函数讲解:
void *__cdecl malloc(size_t _Size);
函数形参:
是指定开辟到堆区内存的大小,这里你可以把它类比成数组,类似于
#define Num_Size 10
int N[Num_Size];
函数的返回值:
函数在堆区内存开辟成功则返回指向被分配内存的指针,否则返回空指针。我们一般最好可以用程序看看是否开辟成功,代码如下:
int N;
scanf("%d", &N);
int *People = (int *) malloc(sizeof(int) * N);
if(!People) exit(1);
这段代码的意思是,开辟一个10个int大小的内存,开辟失败程序直接退出。
内存的释放:内存的释放需要使用一个叫free的函数来释放我们在堆区开辟的内存。
函数原型:
void __cdecl free(void *_Memory);
形参我们只需要传入需要释放内存的指向的指针即可。
内存释放需要注意野指针:free()函数只是将内存的大小,释放归还的,**But!!**指向该内存的指针还是存在的!也就是传说中的野指针!避免野指针的方法就是,把指向该内存的指针指向NULL即可!font
int *People = (int *) malloc(sizeof(int) * N);
free(People);
People = NULL;
由于本人刷题,内存就用一次,就没考虑那么多
Bug定位 数组与指针的区别:sizeof计算的是指针占用内存的大小,那我们来看看int占几个字节?
#include "stdio.h"
int main() {
printf("%d", sizeof(int));
};
运行结果
int占4个Byte!
我们再来看如下程序:
#include
int main()
{
int *a = NULL;
printf("%d\n", sizeof(a));
return 0;
}
这程序打印结果是多少呢?
程序运行起来了:
结果是8!
没错sizeof计算的是指针占用内存的大小,在32位系统中输出是4,在64位系统中输出的是8。
那我接下来修改下程序
#include
int main() {
char a[] = "123456";
char *b = "123456";
printf("%d %d\n", sizeof(a), sizeof(b));
return 0;
}
这个打印结果又是多少呢?
打印结果如下:
很容易发现 sizeof(a)打印出来的是数组元素的个数,sizeof(b)打印出来的是指针占用内存的大小
解决Bug那好我们继续回到之前的题目,我们的memset(num, 0, sizeof(num));置0的内存大小是不为8个Byte,可是我们却开开辟了(sizeof(int) * 4) 16Byte的字节,是不是num[2],num[3]内存没有清空。
正确解决办法是:将memse代码替换如下:
memset(num, 0, sizeof(int) * 4);
正确的此题题解代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main() {
int N;
scanf("%d", &N);
int *People = (int *) malloc(sizeof(int) * N);
int *num = (int *) malloc(sizeof(int) * 4);
printf("%d\n", sizeof(num));
memset(num, 0, sizeof(int) * 4);
for (int i = 0; i < N; ++i) {
scanf("%d", &People[i]);
if (0 <= People[i] && People[i] <= 18) {
num[0]++;
} else if (19 <= People[i] && People[i] <= 35) {
num[1]++;
} else if (36 <= People[i] && People[i] <= 60) {
num[2] += 1;
} else if (People[i] >= 61) {
num[3]++;
}
}
for (int i = 0; i < 4; ++i) {
printf("%.2lf%%\n", 100.0 * num[i] / N);
}
free(People);
free(num);
return 0;
}
运行效果
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)