【实验环境】
IDE: Microsoft Visual Studio Code October 2022 (version 1.71.3)
编译器:GNU gdb (Debian 8.2.1-2+b3) 8.2.1
操作系统:Debian 10 GNU/Linux arm64 5.4.0-aidlite
【实验题目】
1.改写字符串
试编写一个函数 void replaceAll(char str[],char c1,char c2) 将 str 字符串中出现的每一个字符 c2 替换为字符 c1。 其中第一个参数 str 是需要替换的字符串,c1, c2 是有具体值的字符变量或是字符常量。 如果 str 中不存在 c2 中的字符,则不作替换。
使用for循环遍历字符串进行替换即可
#include<iostream>
#include<cstring>
using namespace std;
void replaceAll(char str[],char c1,char c2);
/**
* @brief 将 str 字符串中出现的每一个字符 c2 替换为字符 c1
*
* @param str 需要替换的字符串
* @param c1 替换后的字符符变量或是字符常量
* @param c2 待替换的字符符变量或是字符常量
*/
void replaceAll(char str[],char c1,char c2){
for(int i=0;i<strlen(str);i++){
if(str[i]==c2)
str[i]=c1;
}
}
int main(){
char s1[81]="nannies";
char c1,c2;
replaceAll(s1,'d','n');
cout<<s1<<endl;
cout<<"请输入字符串:";
cin.getline(s1,80,'\n');
cout<<"请输入待替换的字符:";
cin>>c2;
cout<<"请输入替换后的字符:";
cin>>c1;
replaceAll(s1,c1,c2);
cout<<s1<<endl;
return 0;
}
2.改写单词
试编写如下函数void RegularPluralForm(char word[]);其中参数 word(在调用该函数时,在主调函数中对应的实参是字符串数组), 该函数将遵循标准英语规则将 word 修改为复数形式。规则如下: (1)如果单词以 s, x, z, ch 或 sh 结尾,单词后加 es; (2)如果单词后以 y 结尾,并且前面是一个辅音,将 y 改为 ies; (3)如果单词以 f 或 fe 结尾,则把 f 或 fe 变成 v, 再加 es; (4)对于其他单词,后面加 s
通过switch语句判断对应单词的情况,并且对应到相应的规则将其修改为复数形式
quiz,swiz,whiz这3个单词被单独算作了一种情况;
用到了一个重载函数char lastLetter(char word[],int n);返回单词的倒数第n个字母,n不填写时默认为1;
用到了函数bool isVowel(char ch);判断字母是否为元音字母;末尾添加字符串的操作用循环和strcat函数共同完成
#include<iostream>
#include<cstring>
using namespace std;
void RegularPluralForm(char word[]);
bool isVowel(char ch);
char lastLetter(char word[]);
char lastLetter(char word[],int n);
/**
* @brief 把一个单词转换为复数形式
*
* @param word 待转换单词
*/
void RegularPluralForm(char word[]){
int action_type; //需要对字符串执行的操作
//Step1 判断情况
switch(lastLetter(word)){
case 's': action_type=1; break; //-s
case 'x': action_type=1; break; //-x
case 'z': //-z
if(lastLetter(word,2)=='i'){
switch(lastLetter(word,3)){
case 'u': if(lastLetter(word,4)=='q') action_type=5; break; //quiz
case 'w': if(lastLetter(word,4)=='s') action_type=5; break; //swiz
case 'h': if(lastLetter(word,4)=='w') action_type=5; break; //whiz
default : action_type=1;
}
}
else{
action_type=1;
}
break;
case 'h':
switch(lastLetter(word,2)){
case 'c': action_type=1; break; //-ch
case 's': action_type=1; break; //-sh
default : action_type=0;
}
break;
case 'y':
if(!isVowel(lastLetter(word,2))){
action_type=2; //-y
}
else{
action_type=0;
}
break;
case 'f': action_type=3; break; //-f
case 'e':
if(lastLetter(word,2)=='f'){
action_type=4; //-fe
}
else{
action_type=0;
}
break;
default : action_type=0;
}
//Step2 执行操作
switch(action_type){
case 0: strcat(word,"s"); break; //+s
case 1: strcat(word,"es"); break; //+es
case 2:
word[strlen(word)-1]='i'; //-y+ies
strcat(word,"es");
break;
case 3:
word[strlen(word)-1]='v'; //-f+ves
strcat(word,"es");
break;
case 4:
word[strlen(word)-1]='e'; //-fe+ves
word[strlen(word)-2]='v';
strcat(word,"s");
break;
case 5: strcat(word,"zes"); //+zes
}
}
/**
* @brief 判断一个字母是否为元音字母
*
* @param ch 一个字母
* @return true
* @return false
*/
bool isVowel(char ch){
if(ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u'){
return 1;
}
else{
return 0;
}
}
/**
* @brief 返回单词的最后一个字母
*
* @param word 一个单词
* @return 最后一个字母
*/
char lastLetter(char word[]){
return word[strlen(word)-1];
}
/**
* @brief 返回单词的倒数第n个字母
*
* @param word 一个单词
* @param n
* @return char
*/
char lastLetter(char word[],int n){
return word[strlen(word)-n];
}
int main(){
char word1[81]="bus";
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "box");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "peach");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "dish");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "class");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "quiz");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "dictionary");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "family");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "monkey");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "boy");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "knife");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "leaf");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "apple");
RegularPluralForm(word1);
cout << word1 << endl;
strcpy(word1, "tool");
RegularPluralForm(word1);
cout << word1 << endl;
return 0;
}
3.多个名词改写
编写函数void MultiplePluralForm(target[], source[]); 将 source[]字符串(长度不超过 200 个字符)中的单词依次转换为复数,放入字符串数组target[]中, 要求调用第 7 题中的 void RegularPluralForm(char word[]);
通过空格断词,截断的单词存入临时字符串调用上一题的函数处理,再将处理完的单词strcat到target中
在函数结尾还需要再调用一次函数处理,因为最后一个单词结尾没空格触发不了条件
#include<iostream>
#include<cstring>
using namespace std;
void MultiplePluralForm(char target[],char source[]);
void RegularPluralForm(char word[]);
bool isVowel(char ch);
char lastLetter(char word[]);
char lastLetter(char word[],int n);
void MultiplePluralForm(char target[],char source[]){
char temp[81]; //临时单词
memset(temp,0,sizeof(temp)); //初始化
for(int i=0;i<strlen(source);i++){
if(source[i]==' '){ //空格断词
RegularPluralForm(temp);
strcat(temp," ");
strcat(target,temp);
memset(temp,0,sizeof(temp)); //重置临时单词
}
else{
for(int j=0;j<81;j++){
if(temp[j]=='\0'){
temp[j]=source[i]; //字母存入临时单词
break;
}
}
}
}
RegularPluralForm(temp);
strcat(temp," ");
strcat(target,temp);
memset(temp,0,sizeof(temp));
}
/**
* @brief 把一个单词转换为复数形式
*
* @param word 待转换单词
*/
void RegularPluralForm(char word[]){
int action_type; //需要对字符串执行的操作
//Step1 判断情况
switch(lastLetter(word)){
case 's': action_type=1; break; //-s
case 'x': action_type=1; break; //-x
case 'z': //-z
if(lastLetter(word,2)=='i'){
switch(lastLetter(word,3)){
case 'u': if(lastLetter(word,4)=='q') action_type=5; break; //quiz
case 'w': if(lastLetter(word,4)=='s') action_type=5; break; //swiz
case 'h': if(lastLetter(word,4)=='w') action_type=5; break; //whiz
default : action_type=1;
}
}
else{
action_type=1;
}
break;
case 'h':
switch(lastLetter(word,2)){
case 'c': action_type=1; break; //-ch
case 's': action_type=1; break; //-sh
default : action_type=0;
}
break;
case 'y':
if(!isVowel(lastLetter(word,2))){
action_type=2; //-y
}
else{
action_type=0;
}
break;
case 'f': action_type=3; break; //-f
case 'e':
if(lastLetter(word,2)=='f'){
action_type=4; //-fe
}
else{
action_type=0;
}
break;
default : action_type=0;
}
//Step2 执行操作
switch(action_type){
case 0: strcat(word,"s"); break; //+s
case 1: strcat(word,"es"); break; //+es
case 2:
word[strlen(word)-1]='i'; //-y+ies
strcat(word,"es");
break;
case 3:
word[strlen(word)-1]='v'; //-f+ves
strcat(word,"es");
break;
case 4:
word[strlen(word)-1]='e'; //-fe+ves
word[strlen(word)-2]='v';
strcat(word,"s");
break;
case 5: strcat(word,"zes"); //+zes
}
}
/**
* @brief 判断一个字母是否为元音字母
*
* @param ch 一个字母
* @return true
* @return false
*/
bool isVowel(char ch){
if(ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u'){
return 1;
}
else{
return 0;
}
}
/**
* @brief 返回单词的最后一个字母
*
* @param word 一个单词
* @return 最后一个字母
*/
char lastLetter(char word[]){
return word[strlen(word)-1];
}
/**
* @brief 返回单词的倒数第n个字母
*
* @param word 一个单词
* @param n
* @return char
*/
char lastLetter(char word[],int n){
return word[strlen(word)-n];
}
int main(){
char str1[201];
char str2[400];
cin.getline(str1, 201,'\n');
memset(str2,0,sizeof(str2));
MultiplePluralForm(str2, str1);
cout << str2 <<endl;
return 0;
}
4.计算单词次数
编写一个程序,读入几行文本,并打印一个表格。 此表格按照单词在文本中出现的顺序,显示每个不同单词(不区分大小写)在文本中的出现次数。 约定每个单词的长度不超过 20 个字符,每行文本字符数不超过 80,输入文本中的单词个数不超过 1000 个。
(1)定义一个二维字符数组 char words[1001][21],用于按照输入文本中单词出现的顺序依次存储每个单词。
(2)编写一个函数 readWords()从读入的几行文本中抽取每个单词,将其存储在二维数组words 中。(3)编写一个函数 countAndPrintWords(),依次计算 words 数组中每个单词出现的次数,并按照每行显示五个单词的格式,依次打印出每个单词出现的次数。
输入行断词标准:空格或\0;
单词录入标准:字母或单引号录入,其它字符跳过,大写字母转换成小写字母录入;
计数和输出使用vector容器实现
#include<iostream>
#include<cstring>
#include<vector>
#include<string>
using namespace std;
void readWords(char row[],char words[][21],int *numberOfWords);
void countAndPrintWords(char words[][21]);
/**
* @brief 从读入的几行文本中抽取每个单词,将其存储在二维数组words
*
* @param row 输入行
* @param words 单词库
* @param numberOfWords 已存储单词数
*/
void readWords(char row[],char words[][21],int *numberOfWords){
int number_of_words=*numberOfWords; //已存储单词数
for(int j=0;j<strlen(row);j++){
if(row[j]>='A'&&row[j]<='Z'){
row[j]=row[j]-'A'+'a'; //大写转小写
}
}
for(int j=0;j<strlen(row);j++){
if((row[j]==' '&&words[number_of_words][0]!='\0')||(row[j]==' '&&number_of_words==0)){
number_of_words++; //完成单词录入
}
else{
if((row[j]>='a'&&row[j]<='z')||row[j]=='\''){
for(int k=0;k<21;k++){
if(words[number_of_words][k]=='\0'){
words[number_of_words][k]=row[j];
break; //字母录入
}
}
}
}
}
*numberOfWords=number_of_words;
}
/**
* @brief 依次计算 words 数组中每个单词出现的次数,并按照每行显示五个单词的格式,依次打印出每个单词出现的次数
*
* @param words 单词库
*/
void countAndPrintWords(char words[][21]){
vector<string> word_name;
vector<int> word_times;
//确定库一共存储了多少个单词
int number_of_words=0; //库已存储单词数
for(int i=1;i<1001;i++){
if(words[i][0]!=0)
number_of_words++;
else
break;
}
//依次处理库中每一个单词
for(int i=1;i<=number_of_words;i++){
string temp_word; //临时存储单词
for(int j=0;j<strlen(words[i]);j++){
//将单词存入临时存储
temp_word.push_back(words[i][j]);
}
if(word_name.size()==0){ //首位空占格
word_name.push_back("0");
word_times.push_back(0);
}
bool new_word=true; //判断是否为新单词
for(int j=0;j<word_name.size();j++){
if(word_name[j].compare(temp_word)==0){
word_times[j]++; //计数增加
new_word=false;
break;
}
}
if(new_word){
word_name.push_back(temp_word); //录入新单词
word_times.push_back(1);
}
}
int flag=0;
for(int i=1;i<word_name.size();i++){
cout<<word_name[i]<<'\t'<<word_times[i]<<'\t';
flag++;
if(flag==5){
flag=0;
cout<<'\n';
}
}
cout<<'\n';
}
int main(){
//变量定义&声明
char row[81]; //行存储
char words[1001][21]; //单词库
int number_of_rows=0; //目标输入行数
int number_of_words=0; //库已存储单词数
//字符串初始化
memset(row,0,sizeof(row));
memset(words,0,sizeof(words));
//输入
cout<<"请输入你想要的行数:"<<endl;
cin>>number_of_rows;
cout<<"请输入:"<<endl;
for(int i=0;i<=number_of_rows;i++){
memset(row,0,sizeof(row)); //重置行
cin.getline(row,81,'\n'); //输入行
readWords(row,words,&number_of_words);
number_of_words++; //完成行录入
}
countAndPrintWords(words);
return 0;
}
5.计算数字根
小明想吃糖果。小明的爸爸要求小明必须在规定时间内计算出任意整数的数字根,才能吃到糖果。 一个整数的数字根(digital root)是指不断重复地将各位数字相加,直到结果只有一位数字为止。 请你编写一个程序帮助小明计算任意正整数的数字根。
用到两个递归函数int digitalSum(int n);-返回n的各位数之和,以及int digitalRoot(int n);-返回n的数字根
#include<iostream>
using namespace std;
int digitalSum(int n);
int digitalRoot(int n);
/**
* @brief 求n的各数位之和
*
* @param n
* @return int
*/
int digitalSum(int n){
if(n/10==0){
return(n);
}
else{
return(digitalSum(n/10)+digitalSum(n%10));
}
}
/**
* @brief 计算n的数字根
*
* @param n
* @return int
*/
int digitalRoot(int n){
if(n/10==0){
return(n);
}
else{
return(digitalRoot(digitalSum(n)));
}
}
int main(){
int n;
cin>>n;
cout<<digitalRoot(n)<<endl;
return 0;
}
6.任意进制转换问题
编程输入任意十进制数 N(N:-32767~32767),请输出它对应的二进制、八进 制、十六进制; (注意,当数值超过十之后,就用字母 A、B、C……来代替) 比如十六进制数:A1F,代表它最低位是 F,也就是 15,第二位是 1,最高位是 A,也就是10, 转换成 10 进制就是 10*16*16+1*16+15=2581。
首先编写一个函数 void printInt(int n, int base), 功能是输出 n 的 base 进制表示。然后在以下主程序中调用。
进制转换逆向进行,输出时再逆向输出,得到正向的数字结果
#include<iostream>
#include<vector>
using namespace std;
void printInt(int n,int base);
void printInt(int n,int base){
vector<int> result;
do{
result.push_back(n%base);
n/=base;
}while(n!=0); //倒序进制转换,再逆向输出
for(int j=1;j<=result.size();j++){
switch(result[result.size()-j]){
case 10: cout<<"A"; break;
case 11: cout<<"B"; break;
case 12: cout<<"C"; break;
case 13: cout<<"D"; break;
case 14: cout<<"E"; break;
case 15: cout<<"F"; break;
default: cout<<result[result.size()-j];
}
}
cout<<"\n";
}
int main(){
int x;
cin>>x;
printInt(x,2);
printInt(x,8);
printInt(x,16);
return 0;
}
7.函数模板
分别设计一个支持整型、实型、字符型的选择排序的函数模板 selectSort, 以及一个打印整型、实型、字符型数组的函数模板 printArray,在主程序调用。
两个函数并不能使用一个模板,必须要用两个异名模板
#include<iostream>
using namespace std;
template<class T1> void selectSort(T1 arr[],int len);
template<class T2> void printArray(T2 arr[],int len);
/**
* @brief 支持整型、实型、字符型的选择排序的函数模板
*
* @param arr 数组
* @param len 数组长度
*/
template<class T1> void selectSort(T1 arr[],int len){
int lh,rh,k,tmp;
for(lh=0;lh<len;lh++){
rh=lh;
for(k=lh;k<len;k++){
if(arr[k]<arr[rh])
rh=k;
}
tmp=arr[lh];
arr[lh]=arr[rh];
arr[rh]=tmp;
}
}
/**
* @brief 打印整型、实型、字符型数组的函数模板
*
* @param arr 数组
* @param len 数组长度
*/
template<class T2> void printArray(T2 arr[],int len){
cout<<"\n";
for(int i=0;i<len;i++){
cout<<arr[i]<<" ";
}
cout<<"\n";
}
int main()
{
int intarr[10]={20,18,7,19,9,8,2,12,10,1};
float floatarr[12]={9.1,1.9,8.2,7.3,6.4,3.7,5.5,4.6,2.8,5.8,4.6,2.9};
char chararr[8]= {'C','d','e','x','B','D','A','a'};
selectSort(intarr,10);
cout << "the sorted float array:";
printArray(intarr,10);
selectSort(floatarr,12);
cout << "the sorted float array:";
printArray(floatarr,12);
selectSort(chararr,8);
cout << "the sorted float array:";
printArray(chararr,8);
return 0;
}
8.递归
请用递归编写一个函数 bool isPalindrome(char str[]),判断一个字符串是否是回文(palindrome), 所谓回文,就是从左边读与从右边读完全一样的字符串,本题忽略大小写的不同, 例如:Level 是一个回文,abGhgbA 也是一个回文。 主程序首先要求用户输入任意字符串,然后调用你编写的函数,判断用户的输入是否是回文。
用到了三个函数:isPalindrome-递归判断回文;cutHeadAndTail-字符串掐头去尾;disCaps-大写转小写
#include<iostream>
#include<cstring>
using namespace std;
bool isPalindrome(char str[]);
void cutHeadAndTail(char str[]);
void disCaps(char str[]);
/**
* @brief 把一个字符串掐头去尾
*
* @param str 字符串
*/
void cutHeadAndTail(char str[]){
for(int i=0;i<=strlen(str)-1;i++){
str[i]=str[i+1];
}
str[strlen(str)-1]='\0';
}
/**
* @brief 把字符串中的大写字母换成小写
*
* @param str 字符串
*/
void disCaps(char str[]){
for(int i=0;i<strlen(str);i++){
if(str[i]>='A'&&str[i]<='Z')
str[i]=str[i]-'A'+'a';
}
}
/**
* @brief 判断字符串是否回文
*
* @param str 字符串
* @return true
* @return false
*/
bool isPalindrome(char str[]){
if(strlen(str)<=1){
return true;
}
else{
if(str[0]==str[strlen(str)-1]){
cutHeadAndTail(str);
isPalindrome(str);
}
else{
return false;
}
}
}
int main()
{
char str[81];
cout<<"Please input a string:\n";
cin.getline(str,80,'\n');
cout<<str;
disCaps(str);
if(isPalindrome(str))
cout<<" is a palinedrome.\n";
else
cout<<" is not a palinedrome.\n";
return 0;
}