问题 计算用户输入的一个正整数各位之和。
分析 为完成问题所提出的任务,首先必须将该整数的各位分离出来。分离各位数有两种方案:一种是从高向低逐位分离;
另一种则反之。然而,前者必须知道用户所输入之数据的位数,并用不同的数来逐级除该数。利用后者则可以采用一种简单的算法:反复地分离出个位数、将数据降低一个数量级,
直到无数据可分离。每分离出一个个位数,就将它加到一个累加器中。
开始
Sum? 0
分离个位数降低数量级
d = 0
Sum? Sum + 分离出的数输出 Sum
d? 用户输入的数据结束
Y
n? d % 10
d? d / 10
#include <iostream.h>
void main()
{
unsigned long ulData;
int nSum = 0;
cout << "请输入一个正整数,";
cin >> ulData;
cout << ulData << "->";
while(ulData != 0) {
nSum += ulData % 10;
ulData /= 10;
}
cout << nSum << endl;
}
问题 输出所有“水仙花数”。
分析 所谓水仙供花数是指与其各位之平方和相等的三位数。
于是可知解题空间为 100~1000;其关键问题是分离被测数据的各位。
由于位数较少,于是可以考虑用 3 个变量来记录分离出的每一位数(若位数较多,则应考虑使用数组),同时还应当设置一个用来标识当前分离的是哪一位的变量。
#include <iostream.h>
void main()
{
int nMult,n,nStep,nOne,nTen,nHundred;
for(int i = 100; i < 1000; i ++) { // 确定测试范围
n = i; // 保存当前测试数
nStep = 0; // 标记初始化
while(n) {
nMult = n % 10;
nMult = nMult * nMult * nMult;
switch(nStep) { // 当前分离哪一位
case 0:
nOne = nMult;
break;
case 1:
nTen = nMult;
break;
case 2:
nHundred = nMult;
}
n /= 10;
nStep ++; // 准备分离下一位
}
if(i == nOne + nTen + nHundred) // 是水仙花数吗
cout << i << endl;
}
}
在上述程序中,注意到所处理的数据均为 3 位数,并注意到作为记录当前处理位数的变量 nStep 的取值分别为 0,1,2。
于是可以考虑将一个 3 位数所分离出来的各位数用一个大小为 3 的数组来存放,从而可以简化程序。
#include <iostream.h>
void main()
{
int nMult,n,nStep,nNum[3];
for(int i = 100; i < 1000; i ++) {
n = i;
nStep = 0;
while(n) {
nMult = n % 10;
nMult = nMult * nMult * nMult;
nNum[nStep] = nMult;
n /= 10;
nStep ++;
}
if(i == nNum[0] + nNum[1] + nNum[2])
cout << i << endl;
}
}
问题 编写函数输出指定数以内的“完数”。
分析 所谓完数是指与其因子(包括 1)之和相等的正整数。
由问题可知解决方案可以分为两步:
1,分解并保存数 i 的各因数;
2,检测 i 是否是一个完数,若是则按指定格式输出。
#include <iostream.h>
void Perfect(int n)
{
void Factor(int,int[]);
int nFact[20],nSum,j;
for(int i = 2; i <= n; i ++) {
Factor(i,nFact); // 分解并保存 i 的各因数
j = 0;
nSum = 1; // 初始化累加器
while(nFact[j])
nSum += nFact[j ++];
if(i == nSum) { // i 是完数
cout << i << " --> 1,";
j = 0;
while(nFact[j + 1])
cout << nFact[j ++] << ",";
cout << nFact[j] << endl;
} // End(if(i == nSum))
} // End(for(int i = 2; i <= n; i ++))
}
void Factor(int n,int nFactors[]) // 分解因数
{
int nStep = 0;
for(int i = 2; i < n / 2 + 1; i ++)
if(n % i == 0)
nFactors[nStep ++] = i;
nFactors[nStep] = 0; // 添加一个结束标志
}
问题 分别编写计算 Hermite 多项式第 n 项值的非递归和递归函数。
分析 所谓 Hermite 多项式是指如下定义的函数:
可以看出,由于数学模型是递归定义的,所以能够很方便地编写出解决该问题的递归函数。

1)()1(2)(2
12
01
)(
21 nxHnxxH
nx
n
xH
nn
n
int Hermite(int n,int x)
{
if(n == 0)
return 1;
if(n == 1)
return 2 * x;
return 2 * (x * Hermite(n - 1,x) - (n - 1) * Hermite(n - 2,x));
}
int Hermite(int n,int x)
{
int nLow = 1,nMid = 2 * x,nHi;
if(n == 0)
return nLow;
if(n == 1)
return nMid;
for(int i = 2; i <= n; i ++) {
nHi = 2 * (x * nMid - (i - 1) * nLow);
nLow = nMid;
nMid = nHi;
}
return nHi;
}
问题 编写求字符串长度、字符串比较和字符串连接函数。
int StringLength(const char* s)
{
int i = 0; // 长度初始化为 0
while(*s != 0) { // 只要字符串尚未结束则反复
i ++; // 将长度加 1
s ++; // 下一个字符
}
return i;
}
int StringCompare(const char* s1,const char* s2)
{
while(*s1) {
if(*s1 != *s2) // 发现第一个不同的字符
return *s1 - *s2; // 就返回两者之差
s1 ++;
s2 ++;
}
return -(*s2); // 由于 s1 已经结束,所以 s2 中的字符大
}
char* StringConcatenate(char* s1,const char* s2)
{
char* temp = s1;
while(*s1) // 找出 s1 的结尾
s1 ++;
while((*s1 ++ = *s2 ++) != 0); // 将 s2 复制到 s1 尾部
return temp;
}
问题 创建一个可以存放指定个数字符串的数组,数组中每个串所占内存的大小根据用户所输入的字符串的实际长度动态地确定,并利用一个函数对该数组进行排序。
分析 由于字符串是一个字符型数组,所以字符串数组必定是一个二维数组;由于欲创建的数组和每个元素的大小事先均为未知的,所以应当使用一个二维指针来创建所要求的数组。
char** CreateArrays(int n) // 创建
{
char** p;
char temp[81];
p = new char*[n];
if(p)
for(int i = 0; i < n; i ++) {
cin >> temp; // 接收用户输入
p[i] = new char[strlen(temp) + 1]; // 根据输入串的
if(p[i]) // 实际长度为其分配内存
strcpy(p[i],temp); // 保存输入串
}
return p;
}
void SortArray(char** p,int n) // 排序
{
int i,j;
for(i = 1; i < n; i ++) // 进行 n-1 次比较
for(j = i; j < n; j ++)
if(strcmp(p[j],p[j - 1]) < 0) { // 若相邻两元素
char* temp = p[j]; // 位置不正确
// 则交换它们
p[j] = p[j - 1];
p[j - 1] = temp;
}
}
void DestroyArrays(char** p,int n)
{
for(; n > 0; n --)
delete []p[n - 1]; // 释放各字符串所占的内存
delete []p; // 释放指针数组所占的内存
}
问题 编写一个函数,统计一篇英文文章中的行数和单词数。
分析 下面是一篇英文短文:
Preprocessor,Invoking the preprocessor automatically
loads the output into the edit buffer.
Syntax highlighting,Scope delimiters and can be
customized; preprocessor directives highlighted only
instead of highlighting the whole line.
可以看出:每一行都由一个回车符结束;每个单词后边都有至少一个空格、制表符或回车符。另外,文章的开始处有时可能有一些空格或制表符。根据这些条件就可以确定在什么情况下为单词记数加一,什么情况下为行记数加一。在实际编写函数时还应当注意对连续出现多个空白字符的处理。
入口将字计数和行计数初始化为 0
跳过前导空白字符缓冲区中还有字符?
是空白字符(包括回车)?
字计数加 1
跳过可能存在的空白字符(不包括回车)
返回
B
A
No
No
A
是回车符?
行计数加 1
B No
void Counter(char* p,int& rW,int& rL)
{
rW = rL = 0;
while(*p == '\t' || *p == ' ') // 跳过前导空白字符
p ++;
while(*p) {
if(*p == '\t' || *p == ' ' || *p == '\n') { // 一个单词结束
rW ++;
while(*p == '\t' || *p == ' ') // 跳过其余空白字符
p ++;
}
if(*p == '\n') { // 一行结束
p ++;
rL ++;
}
p ++;
} // End while(*p)
rL ++;
rW ++;
}