c++程序设计课后习题
第6章 数组与字符串
(1) 编写一个函数:bool isSorted(const int a[], int n),判断数组a中元素是否按升序排列。
以下第一篇都是参考答案
#include<iostream>
using namespace std;
bool isSorted(const int a[], int n)
{
for(int i=0; i<n-1; i++)
{
if (a[i]>a[i+1]) return false;
if (i==n-2) return true;
}
}
int main()
{
int a[] = {1,2,3,7,10};
int b[] = {1,2,3,1,0,8};
int c[] = {1,2,2,2,3};
cout<<isSorted(a, sizeof(a)/sizeof(int))<<endl;
cout<<isSorted(b, sizeof(b)/sizeof(int))<<endl;
cout<<isSorted(c, sizeof(c)/sizeof(int))<<endl;
return 0;
}
算法实现很简单。
(2)编写一个函数:int getAbsMax(con st int a[], int n),在数组a中找出绝对值最大值并返回下标。
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
void getRandom(int a[], int n) {
srand(time(NULL));
for(int i = 0; i < n; i++)
a[i] = rand() % 100;
}
int getMax(const int a[], int n) {
int max = a[0];
int index = 0;
for(int i = 1; i < n; i++)
if(a[i] > max) {
max = a[i];
index = i;
}
return index;
}
int main() {
int a[10];
getRandom(a, 10);
for(int i = 0; i < 10; i++) {
cout << a[i] << " ";
}
cout << endl;
cout << getMax(a, 10) << endl;
return 0;
}
- 第一个
getRandom
很值得我们学习,为以后调试很方便,需要理解记忆,注意要同时包含
cstdlib
,ctime
两个头文件 - 算法实现上即假设第一个数组元素为最大,后多次进行比较,返回最大的数组下标
运用for
循环语句if
判断语句进行联合操作
(3)编写一个函数:void trim(char a[]),将字符串a的前后所有空格过滤掉,但中间空格要保留。例如:字符串" ab c “的过滤结果是"ab c”。
#include<iostream>
#include<string.h>
using namespace std;
void trim(char a[])
{
int n = strlen(a);
n--;
int i=0;
while(a[i] == ' ')
i++;
while(a[n] == ' ')
n--;
int index=0;
for(; i<=n; i++)
a[index++] = a[i];
a[index] = '\0';
}
int main()
{
char a[] = " a de s ";
cout<<a<<endl;
trim(a);
cout<<a<<endl;
return 0;
}
- 关于
sizeof
与strlen
两者的区别,前者是算某一变量或是数组中所有元素的所占字节大小
或是某一类型所占字节大小,而后者则是常用来求字符串除零前有多少个元素长度 - 算法实现,即从两头分别遍历“ ‘ 然后从零开始重新录入中间的元素
- 特别注意处理完字符串有添加
/0
(4)任意输入一个浮点数,作为一笔金额,显示为中文金额格式(银行里经常要用这种格式)。例如:输人1234.56,输出“壹仟贰佰叁拾肆元伍角陆分”。0为零,1为壹,2为贰,3 为叁,4为肆,5为伍,6为陆,7为柒,8为捌,9为玖,10为拾,还有万、亿。若四舍五入精确到分,尝试你能准确处理的最大金额是多少。
接下来的这段代码,涉及到了数据结构
*图*
这一数据结构,笔者在此从零开始为大家
拓展一些关于数据结构的及基本操作与知识
#include<iostream>
#include<string>
#include<map>
using namespace std;
map<char, string> C{{'0',"零"},{'1',"壹"},{'2',"贰"},{'3',"叁"},{'4',"肆"},{'5',"伍"},{'6',"陆"},
{'7',"柒"}, {'8',"捌"},{'9',"玖"}};
void print(string n)
{
int length = n.size();
int i=0;
while(length >0)
{
switch (length)
{
case 4:
cout<<C[n[i]]<<"千";
length--;i++;
break;
case 3:
if(n[i] != '0')
cout<<C[n[i]]<<"佰";
else if(n[i+1]!='0')
cout<<C[n[i]];
length--;i++;
break;
case 2:
if(n[i] != '0')
cout<<C[n[i]]<<"十";
else if(n[i+1]!='0')
cout<<C[n[i]];
length--;i++;
break;
case 1:
if(n[i] != '0')
cout<<C[n[i]];
length--;
break;
}
}
}
int main()
{
double a;
cout<<"Please input the value of money:";
cin>>a;
bool flag = false;
if(int(a*1000)%10>=5 && int(a*100)%100==99)
{
a = a + 0.01;flag=true;
}
unsigned long a1 = (unsigned long) a;
double a2 = a - a1;
string s1 = to_string(a1);
int length = s1.size();
if(length >8)
{
string num0(s1,0,length-8);
print(num0);
cout<<"亿";
num0.assign(s1,length-8,4);
print(num0);
cout<<"万";
num0.assign(s1,length-4,4);
print(num0);
}else if(length >4)
{
string num0(s1,0,length-4);
print(num0);
cout<<"万";
num0.assign(s1,length-4,4);
print(num0);
}else
{
string num0(s1,0,length);
print(num0);
}
if(a1!=0)
cout<<"元";
if(int(a2*1000)%10>=5)
{
int a3 = int(a2*100);
if(!flag)
a3 = a3 + 1;
string s3 = to_string(a3);
if(a3<10)
cout<<C[s3[0]]<<"分";
else
cout<<C[s3[0]]<<"角"<<C[s3[1]]<<"分";
}else
{
int a3 = int(a2*100);
string s3 = to_string(a3);
if(a3<10)
cout<<C[s3[0]]<<"分";
else
cout<<C[s3[0]]<<"角"<<C[s3[1]]<<"分";
}
return 0;
}
(5)编写一个函数:bool isSmith(int n),判断一个正整数n是否为 Smith 数, 并尝试计算大于等于4937774 的下一个 Smith 数。 Smith数的概念:一个非素数,其各位数之和等于其所有质因数的各位数之和。例如:
4=2*2,4=2+2,所以4 就是一个 Smith 数;
22=2*11,2+2=2+1+1,22 也是一个 Smith数;
27=333,2+7=3+3+3,27 也是一个 Smith数。
#include <iostream>
#include <cmath>
using namespace std;
// 计算一个数的各位数字之和
int sumOfDigits(int num) {
int sum = 0;
while (num > 0) {
sum += num % 10;
num /= 10;
}
return sum;
}
// 计算一个数的所有素数因子的各位数字之和
int sumOfPrimeFactors(int num) {
int sum = 0;
for (int i = 2; i <= sqrt(num); ++i) {
while (num % i == 0) {
sum += sumOfDigits(i);
num /= i;
}
}
if (num > 1) {
sum += sumOfDigits(num);
}
return sum;
}
// 判断是否为史密斯数
bool isSmithNumber(int num) {
int digitSum = sumOfDigits(num);
int primeFactorSum = sumOfPrimeFactors(num);
return digitSum == primeFactorSum;
}
int main() {
int number;
cout << "请输入一个整数:";
cin >> number;
if (isSmithNumber(number)) {
cout << number << " 是史密斯数。" << endl;
} else {
cout << number << " 不是史密斯数。" << endl;
}
return 0;
}
- 整段代码有几个函数组成,体现了分步计算的思想。
(6)先编写一个函数:int getRev(char a[]),计算并返回字符串a的逆序数; 再任意输入 MAX个字符串(MAX是一个宏,值为大于2的正整数),每个串不多于20个字符,计算各串的逆序数,并按逆序数升序输出各串及其逆序数。
逆序的概念:在一个字符串中,如果存在i<j,并且a[i]>a[j],则称a[i]和a[j]构成1个逆序。例如:"DAABEC"的逆序数是5,其中D与A,A,B,C构成4个逆序,E与C构成1个逆序。
#include<iostream>
#include<string.h>
using namespace std;
#define MAX 4
int getRev(char a[])
{
int length = strlen(a);
int count = 0;
for(int i=0; i<length; i++)
{
for(int j=i+1; j<length; j++)
{
if(a[i]>a[j])
count++;
}
}
return count;
}
int main()
{
cout<<"请输入"+ to_string(MAX) + "个长度不大于20的字符串:"<<endl;
char a[MAX][20];
cin>>a[0]>>a[1]>>a[2]>>a[3];
int num[MAX];
for(int i=0; i<MAX; i++)
{
if(strlen(a[i])>20)
{
cout<<"字符串长度过长"<<endl;
return 0;
}
}
for(int i=0; i<MAX; i++)
num[i] = getRev(a[i]);
for(int i=0; i<MAX-1; i++)
{
int temp;
char temp_a[20];
for(int j=i+1; j<MAX; j++)
{
if(num[i]>num[j])
{
temp = num[i];
strcpy(temp_a,a[i]);
num[i] = num[j];
strcpy(a[i],a[j]);
num[j] = temp;
strcpy(a[j],temp_a);
}
}
}
cout<<"结果为:"<<endl;
for(int i=0; i<MAX; i++)
cout<<a[i]<<" "<<num[i]<<endl;
return 0;
}
getrev
函数得到一个字符串中逆序数的个数,之后创建了一个二位数组,来储存max个字符串
for
循环来判断字符串是否过长- 使用选择排序来对逆序字符串的逆序个数大小进行排序,巧妙地是创建了一个中间
数组,像处理数字那样处理数组。
一些突然的补充,在机考模拟之后
每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如’ “x-xxx-xxxxx-xʸ,, 其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语; 第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号; 最后一位为识别码。
识别码的计算方法如下:
首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码( O-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1, 2, , 9, 再求和, 即( 0×1+6×2+⋯⋯+2×9=158, 然后取158 mod 11的结果4作为识别码。
编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出是正确的ISBN号码。
我们由这道题引出我们对字符串的处理
#include <iostream>
#include <string>
using namespace std;
bool isValidISBN(const string &isbn) {
int sum = 0;
int multiplier = 1;
for (int i = 0; i < isbn.length(); ++i) {
char c = isbn[i];
if (isdigit(c)) {
sum += (c - '0') * multiplier;
multiplier++;
} else if (c == 'X' && multiplier == 10) {
sum += 10 * multiplier;
multiplier++;
}
}
return (sum % 11 == 0);
}
string correctISBN(string &isbn) {
int sum = 0;
int multiplier = 1;
for (int i = 0; i < isbn.length(); ++i) {
char c = isbn[i];
if (isdigit(c)) {
sum += (c - '0') * multiplier;
multiplier++;
} else if (c == 'X' && multiplier == 10) {
sum += 10 * multiplier;
multiplier++;
}
}
int checkDigit = sum % 11;
char correctCheckDigit;
if (checkDigit == 10) {
correctCheckDigit = 'X';
} else {
correctCheckDigit = checkDigit + '0';
}
isbn[isbn.length() - 1] = correctCheckDigit;
return isbn;
}
int main() {
string isbn;
cout << "请输入ISBN号码: ";
cin >> isbn;
// 去除输入中的短横线
isbn.erase(remove(isbn.begin(), isbn.end(), '-'), isbn.end());
if (isValidISBN(isbn)) {
cout << "Right" << endl;
} else {
cout << "错误的ISBN号码" << endl;
cout << "正确的ISBN号码为: " << correctISBN(isbn) << endl;
}
return 0;
}
下面我们来分析这段代码
- isValidISBN函数接受一个字符串类型的ISBN号码作为参数。
它创建了一个变量sum来保存计算得到的加权和。 - 遍历ISBN号码的每个字符,如果是数字,则按照ISBN识别码的计算方法进行加权求和。
- 如果字符是’X’,且位于第10个位置(即识别码位置),则将其视为10,并按照规则进行加权求和。
- 最后,检查加权和除以11的余数是否为0。如果余数为0,则识别码正确,函数返回true,否则返回false。
这个函数有一些技巧,用
isbn.length()
得到i的限制数,新建一个字符c
来保存当前字符串所操作的数,并且当前这个数是一个字符,我们用通过他与字符0
相减来得到数字本身
下一个检查函数则是在搞一次,并且又新建了两个变量,一个
下面是一些关于字符串的常规处理操作
- 获取字符串长度:size() 或 length() 函数可用于获取字符串的长度。
string str = "Hello";
int len = str.size(); // 或者 int len = str.length();
- 访问字符串中的字符:可以通过索引来访问字符串中的单个字符。
string str = "Hello";
char first_char = str[0]; // 获取第一个字符'H'
- 连接字符串:使用 + 运算符可以连接两个字符串。
string str1 = "Hello";
string str2 = " World!";
string combined_str = str1 + str2; // 结果是"Hello World!"
- 截取子字符串:使用 substr() 函数来截取子字符串。
string str = "Hello World!";
string sub_str = str.substr(6, 5); // 从索引6开始截取长度为5的子字符串:"World"
- 查找子字符串:find() 函数用于查找子字符串在主字符串中的位置。
string str = "Hello World!";
size_t found = str.find("World"); // found 的值将是子字符串 "World" 的起始位置
- 比较字符串:使用 compare() 函数来比较两个字符串的大小关系。
string str1 = "apple";
string str2 = "banana";
int result = str1.compare(str2); // 返回负值、0、正值,表示 str1 小于、等于、大于 str2
- 插入字符串:使用 insert() 函数在指定位置插入字符串或字符。
string str = "Hello!";
str.insert(5, " World"); // 在索引5处插入字符串 " World",结果为"Hello World!"
- 替换字符串:使用 replace() 函数替换指定位置的字符串或字符。
string str = "Hello World!";
str.replace(6, 5, "Universe"); // 从索引6开始,替换长度为5的字符串为"Universe",结果为"Hello Universe!"
- 转换大小写:tolower() 和 toupper() 函数用于将字符串中的字符转换为小写或大写。
string str = "HeLLo WoRld!";
for (char &c : str) {
c = tolower(c); // 将字符串中的字符全部转换为小写
}
- 分割字符串:可以使用字符串流(stringstream)、find()、substr() 等方法来分割字符串。
#include <sstream>
#include <vector>
string str = "apple orange banana";
stringstream ss(str);
string token;
vector<string> tokens;
while (getline(ss, token, ' ')) {
tokens.push_back(token); // 分割字符串并存储在 tokens 容器中
}
在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
下图给出了一个画了两个矩形的例子。第一个矩形是(1,1)到(4,4),用绿色和紫色表示。第二个矩形是(2,3)到(6,5),用蓝色和紫色表示。 图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。
#include <iostream>
using namespace std;
int a[101][101] = {0};
int main() {
int n;
cin >> n;
// 读取每个矩形的坐标并在数组中涂色
for (int i = 0; i < n; ++i) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
for (int x = x1; x < x2; ++x) {
for (int y = y1; y < y2; ++y) {
a[x][y] = 1; // 将未涂色的区域涂色,注意这里x和y的位置交换了
}
}
}
// for(int i=0;i<10;i++)
//
// {
// for(int j=0;j<10;j++)
// {
//
// cout<<a[i][j]<<" ";
//
// } cout<<endl;
//
// }
// 计算涂色的面积
int coloredArea = 0;
for (int i = 0; i < 101; ++i) {
for (int j = 0; j < 101; ++j) {
if (a[i][j]) {
coloredArea++;
}
}
}
cout << coloredArea << endl;
return 0;
}
-
这道提将抽象的体目具化为我们所需要解决的问题,运用遍历算法和数组数据结构来完成我们所需要解决的问题,这在我们以后解决的问题提供了一般性思考
我们顺着这道题继续拓展一下关于数组处理的一般性方法
1. 遍历数组
数组初始化
#include <iostream> using namespace std; int main() { // 初始化数组 int arr1[] = {1, 2, 3, 4, 5}; // 自动推断数组大小 int arr2[5] = {0}; // 初始化为全零 int arr3[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; // 二维数组初始化 return 0; }
数组遍历
#include <iostream> using namespace std; int main() { int arr[] = {1, 2, 3, 4, 5}; // 使用 for 循环遍历数组 for (int i = 0; i < 5; ++i) { cout << arr[i] << " "; } cout << endl; // 使用范围-based for 循环(C++11及以上) for (auto element : arr) { cout << element << " "; } cout << endl; return 0; }
如何对数组进行操作
交换数组元素
#include <iostream> using namespace std; int main() { int arr[] = {1, 2, 3, 4, 5}; // 交换数组的第一个和最后一个元素 int temp = arr[0]; arr[0] = arr[4]; arr[4] = temp; // 输出交换后的数组 for (int i = 0; i < 5; ++i) { cout << arr[i] << " "; } cout << endl; return 0; }
逆转数组元素
#include <iostream> #include <algorithm> // 包含标准库中的逆转函数 using namespace std; int main() { int arr[] = {1, 2, 3, 4, 5}; // 使用标准库中的函数逆转数组 reverse(arr, arr + 5); // 输出逆转后的数组 for (int i = 0; i < 5; ++i) { cout << arr[i] << " "; } cout << endl; return 0; }
数组的排序与搜索
数组的排序
#include <iostream>
#include <algorithm> // 包含标准库中的排序函数
using namespace std;
int main() {
int arr[] = {4, 2, 7, 1, 5};
// 对数组进行排序
sort(arr, arr + 5); // 这里假设数组大小为5
// 输出排序后的数组
for (int i = 0; i < 5; ++i) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
下面介绍关于sort函数的用法
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {5, 2, 9, 1, 7};
// 使用 Lambda 表达式进行升序排序
sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; });
// 输出排序后的向量
for (int num : vec) {
cout << num << " ";
}
cout << endl;
return 0;
}
数组的搜索
- 线性搜索
#include <iostream>
#include <vector>
using namespace std;
// 线性搜索函数
bool linearSearch(const vector<int>& vec, int target) {
for (int i = 0; i < vec.size(); ++i) {
if (vec[i] == target) {
return true; // 找到目标值
}
}
return false; // 未找到目标值
}
int main() {
vector<int> vec = {5, 2, 9, 1, 7};
int target = 9;
if (linearSearch(vec, target)) {
cout << "目标值 " << target << " 存在于数组中。" << endl;
} else {
cout << "目标值 " << target << " 不存在于数组中。" << endl;
}
return 0;
}
- 二分搜索
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 二分搜索函数
bool binarySearch(const vector<int>& vec, int target) {
int left = 0;
int right = vec.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (vec[mid] == target) {
return true; // 找到目标值
} else if (vec[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false; // 未找到目标值
}
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int target = 6;
if (binarySearch(vec, target)) {
cout << "目标值 " << target << " 存在于数组中。" << endl;
} else {
cout << "目标值 " << target << " 不存在于数组中。" << endl;
}
return 0;
}
swap函数可以直接交互值
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int a = 5, b = 10;
cout << "Before swapping: a = " << a << ", b = " << b << endl;
// 使用 std::swap() 函数交换变量值
swap(a, b);
cout << "After swapping: a = " << a << ", b = " << b << endl;
return 0;
}
7.(7)交警要从违章记录中统计有哪些车辆违章及每辆车的违章次数,并根据违章次数从大到小降序排序。 违章记录设计成一个数组 int a[n],其中记录了所有的违章车辆。 例如:a={1,3,2, 1},表示车辆1,3,2,1违章,其中车辆1违章两次。先编写一个函数,从数组 int a[n]中取出相互不等的元素,形成一个集合set。 例如:a={1,3,2,1, 3,5,2,3},集合 set =(1,2,3,5},表示车辆1,2,3,5 违章。
接着设计一个函数,不仅能得到集合数组,还可以得到集合中各元素出现的次数。例如上面例子中集合set = {1,2,3,5},其中各元素出现次数分别为{2,2,3,1},表示车辆1 违章两次,车辆2违章两次,车辆3违章三次,车辆5违章一次。
再设计一个函数,将集合中的各元素按出现次数降序排序,最后输出各元素及其出现次数。例如上面例子输出结果如下(显示格式为“元素值:出现次数”):
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <iomanip>
using namespace std;
const int n = 30;
int getSet(int rs[],const int a[],int n);
void getSet_improved(int rs[],const int a[],int n);
void create(int a[],int n);
void show(int a[],int n);
int main()
{
int rs[n],a[n];
create(a,n);
show(a,n);
cout<<endl;
cout<<"rs[]'s size: "<<getSet(rs,a,n)<<endl;
for(int i = 0;i < getSet(rs,a,n);i++)
cout<<rs[i]<<" ";
cout<<endl;
cout<<"The descending order is:"<<endl;
getSet_improved(rs,a,n);
return 0;
}
int getSet(int rs[],const int a[],int n)
{
int counter = 0;
bool flag;
for(int i = 0;i < n;i++)
{
flag = true;
for(int j = 0;j < counter;j++)
{
if(a[i] == rs[j])
flag = false;
}
if(flag == true)
rs[counter++] = a[i];
}
return counter;
}
void getSet_improved(int rs[],const int a[],int n)
{
int counter = 0,total[30];
bool flag;
for(int i = 0;i < n;i++)
total[i] = 0;
for(int i = 0;i < n;i++)
{
flag = true;
for(int j = 0;j < counter;j++)
{
if(a[i] == rs[j])
{
flag = false;
total[j]++;
}
}
if(flag == true)
{
rs[counter] = a[i];
total[counter++]++;
}
}
int temp;
for(int i = 0; i < counter; i++)
{
for(int j = 0; j < counter-1-i; j++)
{
if(total[j] < total[j+1])
{
temp = total[j];
total[j] = total[j+1];
total[j+1] = temp;
temp = rs[j];
rs[j] = rs[j+1];
rs[j+1] = temp;
};
}
}
cout<<setiosflags(ios::left);
cout<<setw(10)<<"element"<<setw(10)<<"count "<<endl;
for(int i = 0;i< counter;i++)
cout<<setw(10)<<rs[i]<<setw(10)<<total[i]<<endl;
}
void show(int a[],int n)
{
cout<<"a[]'s size is:";
cout<<n<<endl;
for(int i = 0;i < n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
void create(int a[],int n)
{
srand((unsigned)time(NULL));
for(int i = 0;i < n;i++)
a[i] = rand() % 21;
}
- getset函数保存唯一的数字在数组rs中,并返回有几个唯一的数;getset-improved
函数将唯一的数字保存在数组rs中,并且统计每个数字出现的次数
(8)编写一个函数: int getWordCount(char a[]),统计字符串a中的单词个数,其中单词之间用一个或多个空格或tab符隔开。
#include <iostream>
using namespace std;
int getWordCount(char a[])
{
int num=0;
bool word=false;
for (int i=0;a[i]!='\0'; i++)
{
if (a[i]==' '||a[i]=='\t' )
word=false;
else
if (word==false)
{
word=true;
num++;
}
}
return num;
}
int main()
{
char str[100];
cin.getline(str,100);
int i=getWordCount(str);
cout<<"The number of words:"<<endl;
cout<<i<<endl;
return 0;
}
- cin.getline的优点 :
1.读取包含空格的字符串: 相比于 cin >> 操作符,cin.getline() 能够读取包含空格的整行输入。这意味着可以输入含有空格的句子或短语而不会被空格切割成多个单词。
2.指定最大字符数: 可以指定要读取的最大字符数目。这有助于防止缓冲区溢出或处理超出指定长度的输入,避免造成程序错误或安全漏洞。
3.将输入存储在字符数组中: cin.getline() 可以将读取的输入字符串存储到预先定义的字符数组中。这种方式允许在程序中以字符串形式处理输入数据。
4.处理换行符: cin.getline() 会读取输入直到遇到换行符 \n 或读取的字符数达到指定的最大值(根据参数设定)为止。
例如,使用 cin.getline() 可以这样读取输入,并将其存储在字符数组中:
char str[100];
cin.getline(str, 100); // 读取最多 99 个字符到 str 中,包括终止符 '\0'
总的来说,cin.getline() 函数在读取用户输入时提供了更灵活的方式,能够处理包含空格的字符串,并且可以限制读取的最大字符数目,从而提高程序的健壮性和安全性。
(9)将一副扑克牌(54 张牌中去掉大小王)随机发给4个人,每人13 张牌。编写一个程序,判断某人是否有“五连顺”,即判断是否有5张牌面值连续,如3,4,5,6,7,也包括10,J=11,Q=12, K=13,A=1。运气好的话,一个人可能有两个“五连顺”,编程判断所有的“五连顺”。
#include<iostream>
#include<string>
#include<map>
#include<time.h>
using namespace std;
map<string, int> p{{"3",3},{"4",4},{"5",5},{"6",6},{"7",7},{"8",8},{"9",9},
{"10",10},{"J",11},{"Q",12},{"K",13},{"A",14},{"2",0}};
int main()
{
string s[13];
srand(time(NULL));
for(int i=0; i<13;)
{
int n = rand() % 14;
if(n == 0)
continue;
if(n>1 && n<11)
s[i] = to_string(n);
else if(n==1)
s[i] = "A";
else if(n==11)
s[i] = "J";
else if(n==12)
s[i] = "Q";
else
s[i] = "K";
i++;
}
cout<<"手牌为:"<<endl;
for(auto e:s)
cout<<e<<" ";
cout<<endl;
bool a[15];
for(int i=0; i<15; i++)
a[i] = false;
for(int i=0; i<13; i++)
{
a[p[s[i]]] = true;
}
int count = 0;
cout<<endl;
for(int i=3; i<15; i++)
{
if(a[i])
count++;
else
count=0;
if(count == 5) break;
}
if(count==5)
cout<<"存在五连顺"<<endl;
else
cout<<"不存在五连顺"<<endl;
return 0 ;
}
1.五连顺中,不存在jqkA2,也不存在12345或23456,根据以上,得出映射。
2.通过srand得到手牌,
(10)(报数游戏——约瑟夫环的一个特例)21 个人围成一个圈,编号依次为1~21。现从第1 号开始递增报数,报到5的倍数的人离开,一直报到最后只剩下1人,试编程求出此人的编号。
#include<iostream>
using namespace std;
int main()
{
int num = 21;
bool flag[21];
for(int i=0;i<21;i++)
flag[i] = true;
int index=0;
int count =0;
while(num > 1)
{
if(flag[index])
{
count++;
if(count % 5 == 0)
{
num--;
flag[index] = false;
}
}
index++;
index = index % 21;
}
cout<<"The last one's number is:"<<endl;
for(int i=0; i<21; i++)
{
if(flag[i])
{
cout<<i+1;
break;
}
}
return 0;
}