12.1
实参是取地址符,形参使用指针接收
#include <stdio.h>
void critic(int *units);
int main(void)
{
int units;
printf("How many pounds to a firkin of butter?\n");
scanf("%d", &units);
while (units != 56)
{
//调用该函数,再次输入
critic(&units);
printf("You must have looked it up!\n");
}
return 0;
}
void critic(int *units)
{
printf("No luck, my friend. Try again.\n");
scanf("%d", &units);
return;
}
12.2
pe12-2a.h
//
void set_mode(int n);
void get_info(void);
void show_info(void);
pe12-2a.cpp
#include <stdio.h>
static int mode;
static double range; // 范围
static double fuel; //燃油
void set_mode(int n)
{
if (n > 1)
{
printf("现在的输入是无效的方式指定,上一次的模式是--%s\n",
mode == 0 ? "0(metric)" : "1(US)");
}
else
{
mode = n;
}
return;
}
void get_info(void)
{
if (0 == mode)
{
printf("输入行驶距离,单位为公里:\n");
}
else if(mode == 1)//1
{
printf("输入旅行距离,单位为英里:\n");
}
scanf("%lf", &range);
if (0 == mode)
{
printf("输入燃料消耗(以升为单位):\n");
//putchar('\n');
}
else if (mode == 1)
{
printf("输入燃料消耗(加仑):\n");
//putchar('\n');
}
scanf("%lf", &fuel);
return;
}
void show_info(void)
{
if (0 == mode)
{
printf("燃料消耗是 %.2lf 升/100公里.\n",
(fuel / (range / 100)));
putchar('\n');
}
else if (mode == 1)
{
printf("燃料消耗是 %.1lf, 一英里数.\n",
range / fuel);
putchar('\n');
}
return;
}
pe12-2b.cpp
#include <stdio.h>
#include "pe12-2a.h"
int main(void)
{
int mode;
printf("Enter 0 for metric mode, 1 for US mode:\n");
scanf("%d", &mode);
putchar('\n');
while (mode >= 0)
{
set_mode(mode);
get_info();
show_info();
printf("Enter 0 for metric mode, 1 for US mode");
printf(" (-1 to quit): ");
scanf("%d", &mode);
putchar('\n');
}
printf("Done.\n");
return 0;
}
get_info()第二种方法
if (0 == mode)
{
printf("输入行驶距离,单位为公里:\n");
while (!scanf("%lf", &range))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
while (!scanf("%lf", &fuel))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
}
else
{
printf("输入旅行距离,单位为英里:\n");
while (!scanf("%lf", &range))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
while (!scanf("%lf", &fuel))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
}
结论分析:
12.3
在pe12-2a.h中,为什么三个函数的形参类型不同:
1.值传递(只传送值,实参不做改变)
2.地址传递(传送地址,实参被改变)
.
set_mode()
中要获取我们要从键盘上输入mode,每次不同,实参的值会改变和get_info()
获取到的距离、燃油这两个变量的值也会在该函数中发生变化,对应实参的值也会变
.
.
.
C语言_函数_地址和指针:值传递和地址传递的区别
.
pe12-2a.h
void set_mode(int *mode, int *n);
void get_info(int mode, double *range, double *fuel);
void show_info(int mode, double range, double fuel);
pe12-2a.cpp
#include <stdio.h>
#include "pe12-2a.h"
//static int mode;
//static double range; // 范围
//static double fuel; //燃油
void set_mode(int *mode,int *n)
{
puts("打印-set_mode()已获取到输入的mode值---");
if (*mode > 1)
{
printf("现在的输入是无效的方式指定,上一次的模式是--》%s .\n",
*n == 0 ? "0(metric)" : "1(US)");
puts("打印-此时是无效输入---");
}
else
{
*n = *mode;
puts("打印-此时开始赋值操作---");
}
return;
}
void get_info(int temp, double *range, double *fuel)
{
puts("打印-调用get_info()实现---");
if (0 == temp)
{
printf("输入行驶距离,单位为公里:\n");
while (!scanf("%lf", range))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
//假,进入,真跳出
}
printf("输入燃油:\n");
while (!scanf("%lf", fuel))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
}
else
{
printf("输入旅行距离,单位为英里:\n");
while (!scanf("%lf", &range))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
printf("输入燃油:\n");
while (!scanf("%lf", &fuel))
{
while (getchar() != '\n')
continue;
puts("请输入数字.");
}
}
return;
}
void show_info(int temp, double range, double fuel)
{
puts("打印-调用show_info()实现---");
if (0 == temp)
{
printf("燃料消耗是 %.2lf 升/100公里.\n",
(fuel / (range / 100)));
putchar('\n');
}
else if (temp == 1)
{
printf("燃料消耗是 %.1lf, 一英里数.\n",
range / fuel);
putchar('\n');
}
return;
}
pe12-2b.cpp
#include <stdio.h>
#include "pe12-2a.h"
int main(void)
{
int mode, temp;
double range, fuel;
printf("Enter 0 for metric mode, 1 for US mode:\n");
scanf("%d", &mode);
temp = mode;
putchar('\n');
while (mode >= 0)
{
puts("打印--主函数while循环--");
printf("-------------------------\n");
puts("打印--开始set_mode--");
set_mode(&mode, &temp);
puts("打印--开始get_info--");
get_info(temp, &range, &fuel);
puts("打印--开始show_info--");
show_info(temp, range, fuel);
printf("Enter 0 for metric mode, 1 for US mode");
printf(" (-1 to quit): ");
scanf("%d", &mode);
puts("打印--新输入--");
putchar('\n');
}
printf("Done.\n");
return 0;
}
.
。
12.4
变量count
是具有内部链接的静态变量 :具有静态存储期、文件作用域、内部链接三种属性,这样在主函数和调用函数的实现中都可见。
++count,++在前,先计算后赋值。
.
#include<stdio.h>
static int count = 0;
int counter(void);
int main(void)
{
int i;
int j = 0;
printf("请输入一个正整数:");
scanf("%d", &i);
for (j; j < i; j++)
{
printf("counter = %d\n", counter());
}
printf("函数总共调用了%d次\n", count);
return 0;
}
int counter(void)
{
return ++count;
}
.
。
。
12.5
rand() % 10取余获取到的数都是0-9,所以我们需要为其+1,得到1-10的随机数。
这里的i从1开始,会在最上面单独显示1个数,导致最后一行缺少一个数; 如果i从0开始,而不动对10取余的i,会导致队后一行的最后一个数为负数
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define LEN 100
void show_array(int *a, int n);
void sort(int a[], int n);
int main(void)
{
int i;
int a[LEN];
srand((unsigned int)time(0));
//提供随机数种子~
for (i = 0; i < LEN; i++)
{
a[i] = rand() % 10 + 1;
//调用随机数种子,产生 1~10 之间的随机数
}
printf("最初的%d个数是:\n", LEN);
puts("排序前的数组:");
show_array(a,LEN);
puts("----------------------\n");
puts("排序后的数组:");
sort(a,LEN);
show_array(a, LEN);
return 0;
}
void show_array(int *a, int n)//int a[]也可以
{
int i;
for (i = 1; i < n; i++)
{
printf("%-3d ", a[i]);
if (i % 10 == 0)
{
//每10个换一行
putchar('\n');
}
}
putchar('\n');
return;
}
void sort(int a[], int n)
{
//冒泡排序
int i, j;
int temp = 0;
for (i = 0; i < n - 1; i++)
{
for (j = i+ 1; j < n; j++)
{
if (a[i] < a[j])
{
temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
return;
}
修改
12.6
#include <stdio.h>
#define N 10
#define LEN 1000
int myrand(void);
void mysrand(unsigned int seeds);
static unsigned long int next = 1;//种子
int main(void)
{
int i, temp, a[N + 1];
unsigned int seeds;
for (seeds = 1; seeds <= N; seeds++)
{
printf("第%d次生成随机数:\n", seeds);
mysrand(seeds);
for (i = 0; i < N + 1; i++)
{
//↑将所有元素下标对应的次数,每循环一次清零一次
a[i] = 0;
}
for (i = 0; i < LEN; i++)
{
temp = myrand() % 10 + 1;
//产生1 ~ 1000的随机数
a[temp]++;
//将产生的随机数作为数组下标,在一次循环中统计该下标出现的次数
}
for (i = 1; i < N + 1; i++)
{
printf("%d出现了%d次\n", i, a[i]);
//i作为数组元素1~10出现 ;a[i] 作为数组下标出现
}
printf("随机出现的总数 :%d个\n\n", LEN);
}
return 0;
}
int myrand(void)
{
//↑rand函数的实现;
next = next * 1103515245 + 12345;
return (unsigned int)(next / 65536) % 32768;
}
void mysrand(unsigned int seed)
{
//↑srand函数的实现;
next = seed;
return;
}
12.7
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int dice, count;
int roll;//面数统计
int sides;
int set, sets;
srand((unsigned int) time(0));
printf("输入掷色子后想产生的数量,\nEnter q停止:");
while (scanf("%d", &sets) == 1)
{
puts("有多少面和多少个筛子?");
puts("选择两个正数:");
if(scanf("%d %d", &sides, &dice) != 2)
{
puts("没有整数,终止输入回路");
break;
}
printf("这里有%d次情况产生,有 %d面 %d个筛子-投掷结果:", sets, sides, dice );
putchar('\n');
for(set = 0; set < sets; set++)
{
for(roll = 0, count = 0; count < dice; count++)
{
roll += rollem(sides);
}
printf("%-5d", roll);
if(0 == (set +1) % 8)
{
putchar('\n');
}
}
printf("\nHow many sets? Enter q to stop: ");
}
puts("GOOD FORTUNE TO YOU!\n");
return 0;
}
int rollem(int sides)
{
//产生随机数(随时间变化)
return rand() % sides + 1;
}
12.8
#include <stdio.h>
#include <stdlib.h>
int *make_array(int elem, int val);
void show_array(const int ar[], int n);
int main(void)
{
int *pa;
int size;
int value;
printf("Enter the number of elements: ");
while (scanf("%d", &size) == 1 && size > 0)
{
printf("Enter the initialization value: ");
scanf("%d", &value);
pa = make_array(size, value);//数组大小、给定的值
if (pa)
{
show_array(pa, size);//相当于传递进去数组的首地址以及数组大小
free(pa);
}
printf("Enter the number of elements (<1 to quit): ");
}
printf("Done.\n");
return 0;
}
int *make_array(int elem, int val)
{
int i;
int *pt;
pt = (int *)malloc(elem * sizeof(int));//在堆区创建elem大小的int类型值块,让pt指向这个区域
if (NULL == pt)
{
printf("Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
printf("Output %d numbers:\n", val);
for (i = 0; i < elem; i++)
{
pt[i] = val;
}
return pt;
}
void show_array(const int ar[], int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%d ", ar[i]);
if (0 == (i + 1) % 8)//i从0开始,所以i需要+1再对8取余
{
putchar('\n');
}
}
putchar('\n');
return;
}
12.9
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LEN 100
int main(void)
{
char **pt;
char temp[LEN];
int i, n, length;
printf("How many words do you wish to enter? ");
scanf("%d", &n);
pt = (char**)malloc(n * sizeof(char *));
//指向指针的指针
if (pt == NULL)
{
printf("Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
printf("Enter %d words now:", n);
//每循环一次,对temp中的数据进行一次拷贝
for (i = 0; i < n; i++)
{
scanf("%99s", temp);
length = strlen(temp) + 1;
//↑+1便于保存空字符'\0';
pt[i] = (char *)malloc(length * sizeof(char));
//数组当中包含的元素都是指向 char类型 的指针,pt 是 指向指针的指针
//↑使用malloc分配足够的存储空间来存储单词;
if (pt[i] == NULL)
{
printf("Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
else
strcpy(pt[i], temp);
//这里空间够用,上诉为 pt[i] 创建的堆区空间大小即为 temp 数组对应大小的空间
}
printf("Here are your words:\n");
for (i = 0; i < n; i++)
{
puts(pt[i]);
free(pt[i]);
pt[i] = NULL;
}
free(pt);
pt = NULL;
//↑指针仍然指向malloc分配的存储空间;
//↑因此令指针指向NULL后防止内存滥用;
return 0;
}