书籍信息
名称: Visual C++开发实例大全(基础卷)
版次: 2016年1月第1版
印次: 2019年第4次印刷
Wild Chicken Programing TANXL
简介
在角落沉寂了半年之后,我终于翻开了这把砖头一样厚的书。按照读书计划应该迅速的完成本书的阅读,然而在基础部分的快速阅读中发现了很多令人困扰的代码,经验证后确定了是书上代码的问题。官网勘误的最近一条信息已是多年以前,所以在此记录一下我发现的一些问题。(书还没看完 持续更新)
正文
代码全部来源于随书附带CD!
PAGE 079 实例064 新同学的年龄
// SchoolfellowAge.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int main()
{
long a[10]={0},s[10]={0},i,n3,n4,x=18; //因为有六位数出现,所以定义为长整形
do
{
n3 = x*x*x; //求出x的三次方
for (i=3;i>=0;i--)
{
a[i] = n3%10; //取这个三位数的各位数字
n3 /= 10;
}
n4 = x * x * x * x; //求x的四次方
for (i=9;i>=4;i--)
{
a[i] = n4%10; //取这个四位数的各位数字
n4 /= 10;
}
for (i=0;i<=9;i++)
{
s[a[i]]++; //统计数字出现次数
}
for (i=0;i<=9;i++)
{
if (s[i] == 1) //判断有无重复数字
{
if(i == 9)
{
printf("╔═════════════════╗\n");
printf("║ ║\n");
printf("║ 新同学的年龄是%d岁 ║\n",x);
printf("║ ║\n");
printf("╚═════════════════╝\n");
}
}
else
{
break; //跳出for循环
}
}
x++;
}while(x<22); //x的最大值取到21
return 0;
}
代码在循环时不会清理数组中的原有数据,如果第一次的值不能满足所有条件并输出新同学的年龄,那么即使后面的值是正确的也不会输出,这一个实例的作者运气很好!18到21中第一个值18正好满足条件,不需要进行第二次while循环。
PAGE 082 实例067 集邮册中的邮票数量
// Philately.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int main()
{
int a, b, c, x, sum;
for (x = 1; x <= 5; x++) //x的取值范围从1到5
{
if (10605 % (28-5 * x) == 0) //满足条件的x值即为所求
{
sum = 10605 / (28-5 * x); //计算出邮票总数
a = 2 * sum / 10; //计算a集邮册中的邮票数
b = 5 * sum / 7; //计算b集邮册中的邮票数
c = 303; //c集邮册中的有票数
printf("邮票的总数为: %d张\n", sum); //输出邮票的总数
printf("A集邮册中邮票数量为:%d张\n", a); //输出A集邮册中的邮票数
printf("B集邮册中邮票数量为:%d张\n", b); //输出B集邮册中的邮票数
printf("C集邮册中邮票数量为:%d张\n", c); //输出C集邮册中的邮票数
}
}
return 0;
}
问题出在代码的第十四行。前面辛辛苦苦化简了公式用for循环来寻找满足条件的值,然后一看下面,好家伙14行直接给出了x的值(b = 5 * sum / 7;)这一个实例求的就是七分之几的sum值加十分之二的sum再加303等于sum。经验证把“5”改成“x”没有任何问题,代码仍然可以得到相同结果。
PAGE 086 实例069 用“*”打印图形
秘籍心法
心法领悟069:字符数组元素赋值注意事项。
在本实例中定义了一个字符数组a,在初始化时进行赋值"'*','*','*','*','*'",读者会发现复制时的字
符“*”是用单引号“"”包起来的。这里之所以不使用双引号,是因为双引号包含的是字符串,字符串不能给单
个字符的数组元素赋值。
这个实例的最后的秘籍心法部分,把赋值打成了复制(第三行最后一段话)。
PAGE 113 实例093 数组地址的表示方法
还有一种数组的表示方法是在一个数组地址后面跟上加号和一个整型表达式,相当于以该整型表达式作为下标的数组元素的地址。例如:
int array[10];
int *p = &[2]; //第3个元素的地址
int *p1= array + 2; //第3个元素的地址
第三行的“int *p = &[2];”缺少了变量名,应该改为“int *p = &array[2];”。
PAGE 122 实例101 使用指针实现整数排序
代码与注释和实例100相比,唯一的区别是主函数"return 0;“上面的"getch();”,实例100中有getch而实例101中没有,而实例101的代码也不能满足实例说明、关键技术以及图3.23的截图。(实例100是用指针实现两个数字的交换,而实例101的排序错误的使用了实例100的代码)
PAGE 125 实例104 输出二维数组的有关值
a是数组名。a数组包含3行,即a[0]、a[1]和a[2] 3个元素,而每个元素又是一个包含4个元素的一维数组。
同一维数组一样,a的值为数组首元素地址值,而这里的首元素为4个元素组成的一维数组。因此,从二维数组角度
看,a代表的是首行的首地址,a+1代表的是第一行的首地址。a[0]+0可表示为&a[0][0],即首行首元素地址:a[0]
+1可表示为&a[0][1],即首行第二个元素的地址。
以上内容截取自关键技术的第二段。其中第三行写道“a代表的是首行的首地址,a+1代表的是第一行的首地址。”根据开头的“a是数组名。a数组包含3行”可以确认,首行代表的就是第一行(而不是第零行),而后面的a+1则代表首行之后的第二行。有意思的是在百度搜索“a代表的是首行的首地址,a+1代表的是第一行的首地址。”这一句话可以查到很多csdn投原创的文章。
PAGE 153 实例128 将二维数组转换为一维数组
通过对数组下标的控制可以实现对二维数组元素的逐一提取,提取过程需要两个循环。外层循环控制数组的
行序号,内层循环控制数组的列序号,将二维数组元素逐一提取出来赋值给一维数组,一维数组的下标变化与
行序号和列序号有关,关系如下:
一维数组序号=二维数组列序号+二维数组行序号×4
最后的关系式的“×4”可能跟实例说明的截图有关,但是前面没有任何内容介绍二维数组的大小。在上面截取的一段话完整的来自关键技术,所以这个“×4”的出现毫无道理,应该改为二维数组每行包含的列数,原式应该为“一维数组序号=二维数组列序号+二维数组行序号×二维数组每行包含的列数”。
PAGE 157 实例132 反向输出字符串
#include <stdio.h>
int main()
{
int i;
char String[7] = {"mrsoft"};
char Reverse[7] = {0};
int size;
size = sizeof(String); /*计算源字符串长度*/
/*循环读取字符*/
for(i=0;i<6;i++)
{
Reverse[size-i-2] = String[i]; /*向目标字符串中插入字符*/
}
/*输出源字符串*/
printf("输出源字符串:%s\n",String);
/*输出目标字符串*/
printf("输出目标字符串:%s\n",Reverse);
return 0; /*程序结束*/
}
首先size就很多余,求的是数组的长度,而不是注释中的求字符串长度。其次for循环中的“Reverse[size-i-2] = String[i];”中size-i-2的情况仅限于数组长度为7且只包含六个字符的情况,否则就会把“/0”赋值到Reverse的首位或导致溢出。以下是我给出的改进方案。
#include <stdio.h>
#include <string.h>
int main()
{
int i, j;
char String[] = { "mrsoft" };
char Reverse[7] = { 0 };
int size;
size = strlen(String); /*计算源字符串长度*/
/*循环读取字符*/
for (i = 0, j = size - 1; j >= 0; i++, j--)
{
Reverse[i] = String[j]; /*向目标字符串中插入字符*/
}
/*输出源字符串*/
printf("输出源字符串:%s\n", String);
/*输出目标字符串*/
printf("输出目标字符串:%s\n", Reverse);
return 0; /*程序结束*/
}
PAGE 164 实例 139 删除数组中重复的连续元素
实例名称应该改为删除数组中的元素,代码与标题毫无关联,只是做出了相同的效果而已。
PAGE 168 实例 143 数组中整数的判断
#include "stdio.h"
void main()
{
int data[5], i;
printf("please input 5 number:\n");
for (i = 0; i < 5; i++)
scanf("%d", &data[i]); //向数组data中输入数据
for (i = 0; i < 5; i++)
if (data[i] == 25) //判断数组中的元素是否为3
{
printf("25 is input the postion %d \n", i + 1);
break; //跳出循环
}
if (i >= 5) //判断i是否大于等于10
printf("3 is not in data \n");
}
实例说明中的解释为,“输入5个整型值”、“判断用户输入的5个整型值中是否有整数25”,然而代码中注释和最后的的输出却是对3的判断,另外在判断是否已经遍历完整数组且未跳出的“if (i >= 5)”后面的注释写的是“//判断i是否大于等于10”。另外,在附带光盘中查看代码时,我发现光盘里面实例143的代码就是复制的实例142的代码,没有做任何修改(除了文件名),如下图。
PAGE 258 实例 221 const函数的使用
代码、截图、标题三者牛头不对马嘴,实在是怀疑这本书作者的水平。书中存在巨量类似的错误,初学者极不推荐购买这本书,避免被带偏。其他的错误懒得再发了,太多了…