C Primer Plus 第10章 数组和指针 编程练习
这章感觉好难啊,放个别人的总结.
// 多维数组和指针
#include <stdio.h>
int main(void)
{
int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
/*
zippo[0]是一个整数大小对象的地址,而zippo是两个整数大小对象的地址。
因为(一个)整数和两个整数组成的数组开始于同一个地址,因此zippo和zippo[0]具有相同的数值。
验证:
输出也显示出二维数组zippo的地址和一维数组zippo[0]的地址是相同的,均为相应的数组
首元素的地址,它的值是和&zippo[0][0]相同的;
而且,*zippo也是一个指针,它与一维数组zippo[0](也是一个指针)的地址相同,证明了我的猜想!
*/
printf("===========首先验证第一条结论===========\n");
printf("zippo: \t\t%p\n&zippo[0]: \t%p\n", zippo, &zippo[0]);
printf("zippo[0]: \t%p\n&zippo[0][0]: \t%p\n",zippo[0],&zippo[0][0]);
printf("*zippo: \t%p\n&*zippo: \t%p\n", *zippo, &*zippo);
printf("\n");
/*
zippo所指向对象的大小是两个int,而zippo[0]所指向对象的大小是一个int
验证:
zippo[0]指向4字节长的数据对象。对zippo[0]加1导致它的值增加4。数组名zippo是包含
两个int数的数组的地址,因此它指向8字节长的数据对象。所以,对zippo加1导致它的值增加8。
*/
printf("===========然后验证第二条结论===========\n");
printf("zippo: \t\t%p\nzippo+1: \t%p\n", zippo, zippo+1);
printf("zippo[0]: \t%p\nzippo[0]+1: \t%p\n", zippo[0], zippo[0]+1);
printf("\n");
/*
*zippo也是一个指针,它与一维数组zippo[0](也是一个指针)的地址相同,它们指向同一个int变量
即zippo[0][0]
*zippo[0] = zippo[0][0]
**zippo = *zippo[0] = zippo[0][0](得证)
------------------------------------------------
分析*(*(zippo+2)+1)
zippo------------------第1个大小为2个int的元素的地址
zippo+2----------------第3个大小为2个int的元素的地址
*(zippo+2)-------------第3个元素,即包含2个int值的数组,因此也是其第1个元素的(int值)的地址
*(zippo+2)+1-----------包含2个int值的数组的第2个元素(int值)的地址
*(*(zippo+2)+1)--------数组第3行第2列int(zippo[2][1])的值
总结:更一般地,要表示单个元素,可以使用数组符号或指针符号;并且在这两种表示中即可以使用
数组名,也可以使用指针:
zippo[m][n] == *(*(zippo+m)+n)
*/
printf("===========最后验证第三条结论===========\n");
printf("*zippo: \t%p\nzippo[0]: \t%p\n", zippo, zippo[0]);
printf("*(zippo+1): \t%p\nzippo[1]: \t%p\n", *(zippo+1), zippo[1]);
printf("**zippo: \t%d\nzippo[0][0]: \t%d\n", **zippo, zippo[0][0]);
printf("*(*(zippo+2)+1)\t%d\nzippo[2][1]: \t%d\n", *(*(zippo+2)+1), zippo[2][1]);
return 0;
}
===========首先验证第一条结论===========
zippo: 0x7fff1c31a900
&zippo[0]: 0x7fff1c31a900
zippo[0]: 0x7fff1c31a900
&zippo[0][0]: 0x7fff1c31a900
*zippo: 0x7fff1c31a900
&*zippo: 0x7fff1c31a900
===========最后验证第三条结论===========
*zippo: 0x7fff1c31a900
zippo[0]: 0x7fff1c31a900
*(zippo+1): 0x7fff1c31a908
zippo[1]: 0x7fff1c31a908
**zippo: 2
zippo[0][0]: 2
*(*(zippo+2)+1) 3
zippo[2][1]: 3
// 指针的兼容性
#include <stdio.h>
int main(void)
{
/*
指针之间的赋值规则比数值类型的赋值更严格
举例说明:
*/
int n = 5;
double x;
int * pi = &n;
double * pd = &x;
x = n; // 不需要进行类型转换就直接把一个int数值赋给一个double类型的变量(隐藏的类型转换)
pd = pi // 编译时错误,原因:pd指向一个double类型的数值,pi指向一个int类型的数值
int * pt;
int (* pa) [3];
int ar1[2][3];
int ar2[3][2];
int **p2; // (指向int指针)的指针
pt = &ar1[0][0]; // pt为指向一个int数值的指针,ar1[0][0]是一个int数值的变量
pt = ar1[0]; // pt为指向一个int数值的指针,ar1[0]也为指向一个int数值的指针
pt = ar1; // pt为指向一个int数值的指针,ar1指向由3个int值构成的指针(非法)
pa = ar1; // pa指向由3个int值构成的数组,ar1也指向由3个int值构成的数组
pa = ar2; // pa指向由3个int值构成的数组,ar2指向由2个int值构成的数组(非法)
p2 = &pt; // p2是(指向int指针)的指针,&pt(头一次见,得记下来)也是(指向int指针)的指针
*p2 = ar2[0]; // *p2为指向int的指针,ar2[0]也是指向int的指针
p2 = ar2; // p2是(指向int指针)的指针,ar2是指向由2个int值构成的数组(非法)
return 0;
}
复习题.
int ref[] = { 8, 4, 0, 2 };
3.
ref的地址是什么?ref + 1 是什么意思?++ref指向什么?
答:ref的数组名是指向首元素的地址。ref + 1 是指向该数组的第二个元素。 ++ref是错误的,因为ref是常量而不是变量。 (数组元素也是一种变量,其标识方法为数组名后跟一个下标。)有关变量和常量:http://c.biancheng.net/cpp/html/19.html
6.
假设有下面的声明:int grid[30][100];
a.用1种写法表示grid[22][56]
b.用2种写法表示grid[22][0]
c.用3种写法表示grid[0][0]
答:a:&grid[22][56] b:grid[22], &grid[22][0] c:grid[0], &grid[0][0], (int *) grid
(grid 是内含100个元素的grid[0]数组的地址。这两个地址数值相同,但是类型不同,可以用强制类型转换把他们转换成相同的类型。)
7.
d.psa是一个内含20个元素的数组,每个元素都是指向int的指针
e.pstr是一个指向数组的指针,该数组内含20个char类型的值
答:d. int * psa[20]; //[]比*先生效,所以每个元素都是指向int的指针.
e. char (*pstr)[20]; //这样就*先生效,所以pstr指向的数组含有20个char类型的值.
编程练习
1.
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
int main(void) {
const float rain[YEARS][MONTHS] =
{
{4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6},
{8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3},
{9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4},
{7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2},
{7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2}
};
const float (*pt)[MONTHS] = rain; //const数据不可赋给普通指针,否则通过指针就能改变const中的数据.
float subtot, total;
int year, month;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; year++) {
for (month = 0, subtot = 0; month < MONTHS; month++)
subtot += *(*(pt + year) + month);
printf("%5d %15.1f\n", 2010 + year, subtot);
total = total + subtot;
}
printf("\nThe yearly average is %.1f inches.\n\n",
total / YEARS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
printf(" Nov Dec\n");
for (month = 0; month < MONTHS; month++) {
for (year = 0, subtot = 0; year < YEARS; year++)
subtot += *(*(pt + year) + month);
printf("%4.1f ", subtot / YEARS);
}
printf("\n");
return 0;
}
2.
#include <stdio.h>
void copy_arr(double *ar, double *pt, int n);
void copy_arr2(double *ar, double *pt, int n);
void copy_arr3(double *ar, double *pt, double *pr);
int main(void) {
double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
double targe1[5], targe2[5], targe3[5];
printf("targe1:\n");
copy_arr(targe1, source, 5);
putchar('\n');
printf("targe2:\n");
copy_arr2(targe2, source, 5);
putchar('\n');
printf("targe3:\n");
copy_arr3(targe3, source, source + 5);
return 0;
}
void copy_arr(double *ar, double *pt, int n) {
int i;
for (i = 0; i < n; i++) {
ar[i] = pt[i];
printf("[%d]: %.1lf\n", i, ar[i]);
}
}
void copy_arr2(double *ar, double *pt, int n) {
int i;
for (i = 0; i < n; i++) {
*(ar + i) = *(pt + i);
printf("[%d]: %.1lf\n", i, *(ar + i));
}
}
void copy_arr3(double *ar, double *start, double *end) {
int i = 0;
while (start < end) {
*ar = *start;
printf("[%d]: %.1lf\n", i++, *ar);
start++;
ar++;
}
}
3.
#include <stdio.h>
int max(int *ar, int n);
int main(void) {
int source[5] = {1, 10, 3, 4, 5};
printf("MAX: %d", max(source, 5));
return 0;
}
int max(int *ar, int n){
int max = ar[0];
for (int i = 0; i < n; ++i) {
if (max < ar[i])
max = ar[i];
}
return max;
}
4.
#include <stdio.h>
int max(double *ar, int n);
int main(void) {
double source[5] = {1, 10, 11, 4, 5};
printf("MAX_: %d", max(source, 5));
return 0;
}
int max(double *ar, int n){
int max = ar[0];
int x = 0;
for (int i = 0; i < n; ++i) {
if (max < ar[i]){
max = ar[i];
x = i;
}
}
return x;
}
5.
#include <stdio.h>
int max(int *ar, int n);
int main(void) {
int source[5] = {1, 10, 3, 4, 5};
printf("Difference: %d", max(source, 5));
return 0;
}
int max(int *ar, int n){
int max = ar[0];
int min = ar[0];
for (int i = 0; i < n; ++i) {
if (max < ar[i])
max = ar[i];
}
for (int i = 0; i < n; ++i) {
if (min > ar[i])
min = ar[i];
}
return max - min;
}
6.
#include <stdio.h>
void copy(double *pr, double *ar, int n);
int main(void) {
double source[5] = {1, 10, 3, 4, 5}, targe[5];
copy(targe, source, 5);
for (int i = 0; i < 5; ++i) {
printf("%5.1lf",targe[i]);
}
return 0;
}
void copy(double *pr, double *ar, int n){
int x = n - 1;
for (int i = 0; i < n; ++i,x--) {
pr[x] = ar[i];
}
}
7.
//运行完成后会出现*** stack smashing detected ***这个,我也不知道啥情况记一下先吧.
#include <stdio.h>
void copy(double ar[][3], double pt[][3], int n);
int main(void)
{
double soure[2][3] = {{1,2,3},{4,5,6}};
double target[2][3];
copy(target,soure,2);
for (int i = 0; i < 2; ++i) {
for (int m = 0; m < 3; ++m) {
printf("target[%d][%d]:%.1lf\n", i, m, target[i][m]);
}
}
return 0;
}
void copy(double ar[][3], double pt[][3], int n){
for (int i = 0; i < n; ++i) {
for (int m = 0; m < 5; ++m) {
ar[i][m] = pt[i][m];
}
}
}
8.
#include <stdio.h>
void copy(double ar[], double pt[], int n);
int main(void) {
double soure[7] = {1, 2, 3, 4, 5, 6, 7};
double target[3];
copy(target, soure + 2, 3);
for (int m = 0; m < 3; ++m) {
printf("target[%d]:%.1lf\n", m, target[m]);
}
return 0;
}
void copy(double ar[], double pt[], int n) {
for (int m = 0; m < n; ++m) {
ar[m] = pt[m];
}
}
9.
#include <stdio.h>
void copy(int n, int m, double ar[n][m], double pt[n][m]);
void print(int n, int m, double ar[n][m]);
int main(void){
double soure[3][5] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
double target[3][5];
copy(3, 5, target, soure);
printf("soure:\n");
print(3, 5, soure);
printf("target:\n");
print(3, 5, target);
return 0;
}
void copy(int n, int m, double ar[n][m], double pt[n][m]){
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
ar[i][a] = pt[i][a];
}
}
}
void print(int n, int m, double ar[n][m]){
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
printf("[%d][%d]:%.1lf\n", i, a, ar[i][a]);
}
}
}
10.
#include <stdio.h>
void copy(double pt[],double zr[], double ar[],int n);
void print(double ar[], int n);
int main(void){
double soure[5] = {1,2,3,4,5};
double soure2[5] = {1,2,3,4,5};
double target[5];
copy(target, soure, soure2, 5);
print(target, 5);
return 0;
}
void copy(double pt[],double zr[], double ar[],int n){
for (int i = 0; i < n; ++i) {
pt[i] = zr[i] + ar[i];
}
}
void print(double ar[], int n){
for (int i = 0; i < n; ++i) {
printf("[%d]:%.1lf\n", i, ar[i]);
}
}
11.
#include <stdio.h>
void doub(int n, int m, double ar[n][m]);
void print(int n, int m, double ar[n][m]);
int main(void) {
double soure[3][5] = {{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}};
doub(3, 5, soure);
printf("soure:\n");
print(3, 5, soure);
return 0;
}
void doub(int n, int m, double ar[n][m]) {
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
ar[i][a] = ar[i][a] * 2;
}
}
}
void print(int n, int m, double ar[n][m]) {
for (int i = 0; i < n; ++i) {
for (int a = 0; a < m; ++a) {
printf("[%d][%d]:%.1lf\n", i, a, ar[i][a]);
}
}
}
12.
#include <stdio.h>
#define MONTHS 12
#define YEARS 5
void eachmonths(const float [][MONTHS], int n);
float sum(const float [][MONTHS], int n);
int main(void) {
const float rain[YEARS][MONTHS] =
{
{4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6},
{8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3},
{9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4},
{7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2},
{7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2}
};
float total;
printf(" YEAR RAINFALL (inches)\n");
total = sum(rain, YEARS);
printf("\nThe yearly average is %.1f inches.\n\n",
total / YEARS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
printf(" Nov Dec\n");
eachmonths(rain, YEARS);
return 0;
}
float sum(const float ar[][MONTHS], int n) {
float subtot, total;
int i, m;
for (i = 0, total = 0; i < n; i++) {
for (m = 0, subtot = 0; m < MONTHS; m++)
subtot += ar[i][m];
printf("%5d %15.1f\n", 2010 + i, subtot);
total += subtot;
}
return total;
}
void eachmonths(const float ar[][MONTHS], int n) {
float subtot;
int m;
for (int i = 0; i < MONTHS; ++i) {
for (m = 0, subtot = 0; m < n; ++m) {
subtot += ar[m][i];
}
printf("%4.1f ", subtot / YEARS);
}
printf("\n");
}
//做完这题之后就感觉自己是个弱智!
/*爆炸级别弱智错误还找了半天.
float sum(const float ar[][MONTHS], int n) {
float subtot, total;
for (int i = 0, total = 0; i < n; i++) {
for (int m = 0, subtot = 0; m < MONTHS; m++)
subtot += ar[i][m];
printf("%5d %15.1f\n", 2010 + i, subtot);
total += subtot;
}
return total;
}
这样子之后就在for循环中把total和subtot声明成了int格式了,
然后我不就是个傻逼了吗!!哇 真的是被自己蠢哭了.*/
13 and 14
#include <stdio.h>
void enter_number(int n, int m, double ar[n][m]);
double average_group(double ar[], int n);
double average_all(int n, int m, double ar[n][m]);
double MAX(int n, int m, double ar[n][m]);
void show(int n, int m, double ar[n][m]);
int main(void) {
int row, col;
printf("请输入你需要的数组(例如3×5):");
scanf("%d %d", &row, &col);
double target1[row][col];
printf("请输入数据:\n");
enter_number(row, col, target1);
for (int i = 0; i < row; ++i) {
printf("第 %d 组 (%d个) 的平均值是: %.1lf\n", i + 1, col, average_group(target1[i], col));
}
printf("所有数据的平均值是: %.1lf\n", average_all(row, col, target1));
printf("所有数据的最大值是: %.1lf\n\n\n", MAX(row, col, target1));
printf("你输入的数组是:\n");
show(row, col, target1);
return 0;
}
void enter_number(int n, int m,double ar[n][m]) {
double number;
for (int i = 0; i < n; ++i) {
for (int x = 0; x < m; ++x) {
scanf("%lf", &number);
ar[i][x] = number;
}
}
}
double average_group(double ar[], int n){
double total = 0;
for (int i = 0; i < n; ++i) {
total += ar[i];
}
return total / n;
}
double average_all(int n, int m, double ar[n][m]){
double total = 0;
for (int i = 0; i < n; ++i) {
for (int x = 0; x < m; ++x) {
total += ar[i][x];
}
}
return total / (n * m);
}
double MAX(int n, int m, double ar[n][m]) {
double max = ar[0][0];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (max < ar[i][j])
max = ar[i][j];
}
}
return max;
}
void show(int n, int m, double ar[n][m]){
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
printf("%8.1lf", ar[i][j]);
}
putchar('\n');
}
}
C Primer Plus 第10章 数组和指针 编程练习的更多相关文章
- 【C语言学习】《C Primer Plus》第10章 数组和指针
学习总结 1.数组初始化方式: int a[]={1,2,3} int a[SIZE]={1,2,3} //SIZE是宏定义,数组初始化个数不能大于SIZE,否则报错:当个数小 //SIZE,自动补0 ...
- C Primer Plus_第6章_循环_编程练习
1.题略 #include int main(void) { int i; char ch[26]; for (i = 97; i <= (97+25); i++) { ch[i-97] = i ...
- Java程序设计基础笔记 • 【第10章 数组】
全部章节 >>>> 本章目录 10.1 数组概述 10.1.1 数组优势 10.1.2 Java中的数组 10.1.3 数组的分类 10.2 一维数组 10.2.1 数组的 ...
- C++ Primer高速入门之六:数组和指针
更新:勘误,delete [] 猪 我们知道,C语言以及早期的面向结构的语言差点儿都支持数组定义.比方整形数组int 女神[2].表示有俩数: 女神[0], 女神[1].她们都是整数. C++ 语言为 ...
- C Primer Plus_第10章_数组和指针_编程练习
1. /*rain.c 针对若干年的降水量数据,计算年降水总量.年降水平均量,以及月降水平均量*/ #include <stdio.h> #define MONTHS 12 #define ...
- 《C++ primer》--第10章
习题10.21 解释map和set容器的差别,以及他们各自适用的情况. 解答: map容器和set容器的差别在于: map容器是键-值对的集合,而set容器只是键的集合: map类型适用于需要了解键与 ...
- C++ Primer 5th 第10章 泛型算法
练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受一对迭代器和一个值作为参数.count返回给定值在序列中出现的次数.编写程序,读取int序列存入vector ...
- [C++ Primer Plus] 第10章、对象和类(二)课后习题
1. bank.h #include <string> using namespace std; class BankAccount { private: std::string m_na ...
- [C++ Primer Plus] 第10章、对象和类(一)程序清单——辨析三个const
程序清单10.1+10.2+10.3 头文件stock.h #ifndef STOCK00_H_ //先测试x是否被宏定义过 #define STOCK00_H_ //如果没有宏定义,就宏定义x并编译 ...
随机推荐
- [FreeRadius2]遇到问题记录
在学习FreeRadius2中遇到的问题,和解决. 使用的是2.2 版本,测试的系统是Centos6.7 radtest 没有响应 radiusd 启动正常,测试如下命令不好使 [root@orang ...
- RHEL6.4上升级python从2.6.6到2.7.3
RHEL6.4上升级python从2.6.6到2.7.3 原始安装好的redhat6.4上的python版本是2.6.6,不能满足实际需要.升级的方法很多,从源码升级或者从rpm包升级.其中从rpm包 ...
- 排序算法(二)Sort with Swap(0,*)
对于一个由0到N-1的序列,如果只能交换0和另一个数的位置,求多少次能够将序列变为递增序列. 输入为<N> <序列>(N和序列之间有一个空格,序列元素之间均有一个空格). 设序 ...
- AngularJS进阶(三)HTML:让表单、文本框只读,不可编辑的方法
HTML:让表单.文本框只读,不可编辑的方法 有时候,我们希望表单中的文本框是只读的,让用户不能修改其中的信息,如使<input type="text" name=" ...
- Leetcode_48_Rotate Image
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/44216867 You are given an n x n ...
- libRTMP使用说明
名称 librtmp − RTMPDump Real-Time Messaging Protocol API 库 RTMPDump RTMP(librtmp, -lrtmp) 简介 #include& ...
- 校招:Vobile阜博通2015校园招聘
关于Vobile阜博通校招(10-11月份),耗时将近一个月,现整理分享给大家. 1 浙大笔试无选择填空,问答题为主,偏语言的个人理解,不在意具体语言方向(C/C++/Java).(1)描述C.C++ ...
- 根据Facebook内存的管理使用,浅谈在iOS上自动检测内存泄漏问题
分装库下载:https://github.com/facebook/FBMemoryProfiler FBMemoryProfiler类库使用教程:http://ifujun.com/fbmemory ...
- C++语言之构造函数
#include <iostream> using namespace std ; class Cat { public: char name[20]; void Say_Name(voi ...
- Xcode使用心得03:打开僵尸(Zombie)模式
如果打开了ARC或垃圾回收模式,在程序中发消息给以及重新分配的对象,将会引起程序崩溃.这时定位崩溃原因将非常困难,因为出问题的对象已经重新分配了.一个解决的方法就是要求Xcode将对象设置为" ...