C++练习题《基本练习》

NO1、选出妃子、宫女和嬷嬷

在这里插入图片描述
其他要求:

  • 超女用结构体表示
  • 不要嵌套if
  • 输入所有数据后再判断
#include <iostream>
#include <string>

using namespace std;
struct CGirl {
    int age;
    int high;
    string sc;
    //c风格字符串 char sc[31];  字符串比较就要用 strcmp
    bool yz;
};

int main() {
    CGirl g;
    cout << "请依次输入年龄、身高(cm)、身材(火辣/普通)、颜值(漂亮/一般):";
    string stringYz{0};
    cin >> g.age >> g.high >> g.sc >> stringYz;
    g.yz = (stringYz == "漂亮") ? true : false;
    if ((g.age >= 18 && g.age <= 25) && (g.high >= 165 && g.high <= 178) && (g.sc == "火辣") && g.yz)
        cout << "妃子" << endl;
    else if ((g.age >= 18 && g.age <= 30) && (g.high >= 160 && g.high < 165) && (g.sc == "火辣" || g.sc == "普通") &&
             g.yz)
        cout << "宫女" << endl;
    else if ((g.age >= 35 && g.age <= 40) && (g.high >= 155 && g.high < 165) && (g.sc == "飞机场" || g.sc == "普通") &&
             (!g.yz))
        cout << "嬷嬷" << endl;
/*    else
        cout<<"落选"<<endl;*/
    return 0;
}

No2、根据数字判断月份

在这里插入图片描述
其他要求:

  • ifelse或者switchcase实现
  • 字符串数组实现(C/C++)
#include <iostream>

int main() {
    int mouth = -1;
    std::cout << "请输入月份(1-12):";
    std::cin >> mouth;
    /*switch (mouth) {
        case 1:
            std::cout<<"January"<<std::endl;
            break;
        case 2:
            std::cout<<"February"<<std::endl;
            break;
        case 3:
            std::cout<<"March"<<std::endl;
            break;
        case 4:
            std::cout<<"April"<<std::endl;
            break;
        case 5:
            std::cout<<"May"<<std::endl;
            break;
        case 6:
            std::cout<<"June"<<std::endl;
            break;
        case 7:
            std::cout<<"July"<<std::endl;
            break;
        case 8:
            std::cout<<"August"<<std::endl;
            break;
        case 9:
            std::cout<<"September"<<std::endl;
            break;
        case 10:
            std::cout<<"October"<<std::endl;
            break;
        case 11:
            std::cout<<"November"<<std::endl;
            break;
        case 12:
            std::cout<<"December"<<std::endl;
            break;
        default:
            std::cout<<"输入错误"<<std::endl;
    }*/

    //效率高于ifelse 和 switch case
    char months[12][10] = {"January","February","March","April","May","June","July"
    ,"August","September","October","November","December"};

    if (mouth>=1&&mouth<=12)
        std::cout<<months[mouth-1]<<std::endl;
    else
        std::cout<<"输出错误"<<std::endl;
}

No3、循环计数

在这里插入图片描述

#include <iostream>

int main() {
    int sum = 0;
    int i = 0;
    while (i <= 100) {
        sum += i++;
    }
    std::cout << "1-100之间的和为" << sum << "\n";

    int num{0};
    int sumF{0};;
    for (;sumF <= 5000;) {
        std::cin>>num;
        sumF+=num;
    }
    std::cout << "输入的和为" << sumF << "\n";
    

    return 0;
}

No4、循环选数

在这里插入图片描述

/**
  ******************************************************************************
  * @file           : demo4.cpp
  * @author         : DELL
  * @brief          : None
  * @attention      : None
  * @date           : 2024-01-25
  ******************************************************************************
  */
#include <iostream>

int main() {
    int num{0}, count{0}, sum{0};
    while (std::cin >> num) {
        if (!num)break;
        if (num < 1 || num > 100)
            continue;
        count++;
        sum += num;
    }
    std::cout << "符合条件个数:" << count << "--" << "它们的和:" << sum << "\n";


    int n{1};
    //取余数
    while (n <= 100) {
        if (n % 5 == 0)
            std::cout << n << " ";
        ++n;
    }
    std::cout << "\n";
    //另外一种写法
    n = 5;
    while (n <= 100) {
        std::cout << n << " ";
        n += 5;
    }
    return 0;
}

No5、玩转字符

在这里插入图片描述

//ASCII A->65 Z->90   a->97  z->122
void printLastChar(char &&c) {
    if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
        std::cout << "输入不合规" << "\n";
        return;
    }
    if (c == 'Z' || c == 'z') {
        std::cout << c << "的后面没有字符" << "\n";
        return;
    }
    std::cout << c << "后面的字符是:" << char(c + 1) << std::endl;

}

在这里插入图片描述

int ctoi(const char ch) {
    if (ch < '0' || ch > '9') {
        std::cout << "参数不合规" << std::endl;
        return -1;
    }
    return int(ch - 48);
}

No6、计算字符串长度

在这里插入图片描述
其他要求

  • 封装成一个函数
  • for循环+数组表示法+临时变量
  • while+指针表示+临时变量
  • 不用临时变量->递归
int len(char *c) {
    //1、for循环+临时变量+数组表示法
    /*int len{0};
    for (; c[len] != '\0'; ++len);
    return len;*/

    //2、while循环+临时变量+指针表示法
    /*char *p = c;
    int len{0};
    while (*p++)
        ++len;
    return len;*/

    //3、递归思路+不采用临时变量
    //递归开销大于循环)(
    if (*c == '\0')return 0;//中止条件
    c++;//指针后移
    return len(c) + 1;//后移之后的长度+1=本来的长度
    //递归中我们可以把下一层当作已知参数,比如
}

No7、显示字符串中的字符

在这里插入图片描述

void printStr(const char *c, bool isSequence = true) {
    int len = strlen(c);
    if (isSequence) {
        for (int i = 0; i < len; ++i) {
            std::cout << c[i] << " ";
        }
    } else {
        for (int i = len - 1; i >= 0; --i) {
            std::cout << c[i] << " ";
        }
    }
    std::cout << std::endl;
}

No8、字符串反转

在这里插入图片描述

//使用另外一个字符串
char *reverse(const char *str){
    char *newStr = new char[30];
    int len = ::strlen(str);
    ::memset(newStr,0, sizeof(newStr));
    for (int i = 0,j=len-1; i < len;)
        newStr[i++] = str[j--];
    return newStr;
}

//原地反转
void reserveS(char *str){
    //abc   d
    int len = ::strlen(str);
    int n = len/2;
    for (int i = 0; i < n; ++i) {
        char tmp = str[i];
        str[i] = str[len-i-1];
        str[len-i-1] = tmp;
    }
}

No9、二维数组的应用

在这里插入图片描述
任务一

    double weights[3][4];
    ::memset(weights,0, sizeof(weights));
    double total{0};
    for (int i = 0; i < 3; ++i) {
        double sum{0};
        for (int j = 0; j < 4; ++j) {
            double weight{0};
            cout<<"请输入第"<<i+1<<"组第"<<j+1<<"个超女的体重:";
            cin>>weight;
            weights[i][j] = weight;
            sum+=weight;
        }
        total+= sum;
        cout<<"第"<<i+1<<"小组超女的平均体重:"<<sum/4<<"\n";
    }
    cout<<"所有小组超女的平均体重:"<<total/12<<endl;

任务二

    char names[3][11];
    ::memset(names,0, sizeof(names));
    for (int i = 0; i < 3; ++i) {
        cout<<"请输入超女姓名:";
        cin>>names[i];
    }
    for (int i = 0; i < 3; ++i) {
        cout<<"表白:"<<names[i]<<"\n";
    }

No10、整数转化字符串课后

在这里插入图片描述

/**
  ******************************************************************************
  * @file           : demo10.cpp
  * @author         : DELL
  * @brief          : None
  * @attention      : None
  * @date           : 2024-01-25
  ******************************************************************************
  */
#include <iostream>

using namespace std;

//可以将字符串反转 这样才是真正的
int main() {
    cout << "请输入一个整数:";
    int num{0};
    char cNum[21];
    cin >> num;
    int index = 0;
    int cnum{num};
    //转化十进制
    while (cnum) {
        int tmp = cnum % 10;
        cNum[index++] = static_cast<char>(tmp + 48);
        cnum /= 10;
    }
    for (int i = index - 1; i >= 0; --i) {
        cout << cNum[i];
    }
    cout << "\n";

    //转化为二进制
    index = 0;
    cnum = num;
    while (cnum) {
        int tmp = cnum % 2;
        cNum[index++] = static_cast<char>(tmp + 48);
        cnum /= 2;
    }
    for (int i = index - 1; i >= 0; --i) {
        cout << cNum[i];
    }
    return 0;
}

No11、把字符串转化为整数

在这里插入图片描述
补充:
可以选择二进制或者十进制 默认为十进制

int myAtoi(const char*s,int radix = 10){
    int sum{0},len = ::strlen(s);
    for (int i = 0; i < len; ++i) {
        if (radix==10&&(*(s+i)>'9'||*(s+i)<'0'))return sum;
        if (radix==2&&(*(s+i)>'1'||*(s+i)<'0'))return sum;
        sum = sum*radix + *(s+i) - '0';
    }
    return sum;
}

No12、实现strcpy和strncpy函数

字符串赋值

#include <iostream>

using namespace std;

//数组表示法||还可以指针表示法
char *strcpy1(char *dest, const char *src) {
    int i{0};
    while (src[i]) {
        dest[i] = src[i];
        ++i;
    }
    dest[i] = 0;//循环结束在目标字符串的结尾加上0
    return dest;
}

//一次复制一整块内存
char *strcpy2(char *dest, const char *src) {
    memcpy(dest, src, sizeof(src) + 1);//char是1B,+1是结尾标志0也要复制进去
    return dest;
}
//时间消耗:复制一整块内存<指针<数组


char *strncpy(char *dest, const char *src,size_t n) {
    memcpy(dest, src, n);
    *(dest+n) = 0;//实际的strncpy是没有这一行的 所以会有bug
    return dest;
}
#include <chrono>

int main() {
   chrono::steady_clock::time_point start,end;
    char dest[11], src[11]{"aasdcas"};

    start = chrono::steady_clock::now();
    for (int i = 0; i < 100000; ++i)
        strcpy1(dest, src);
    end=chrono::steady_clock::now();
    cout<<"数组表示法时间:"<<static_cast<double>((end-start).count())/(1000*1000)<<"毫秒"<<endl;

    start = chrono::steady_clock::now();
    for (int i = 0; i < 100000; ++i)
        strcpy2(dest, src);
    end=chrono::steady_clock::now();
    cout<<"复制整个内存时间:"<<static_cast<double>((end-start).count())/(1000*1000)<<"毫秒"<<endl;

    return 0;
}

在这里插入图片描述

No13、实现strcat和strncat函数

拼接字符串

#include <iostream>
#include<cstring>

using namespace std;

char *m_strcat(char *dest, const char *src) {
    size_t dLen = strlen(dest), sLen = ::strlen(src);
    ::memcpy(dest + dLen, src, sLen + 1);
    return dest;
}

char *m_strncat(char *dest, const char *src, const size_t n) {
    size_t len = strlen(dest);
    ::memcpy(dest + len, src, n);
    *(dest + len + n) = 0;
    return dest;
}

int main() {
    char d[21] = "dududuying";
    cout << m_strcat(d, "seu")<<"\n";
    cout << m_strncat(d, "seuduseu",5)<<"\n";
    return 0;
}

No14、实现strchr和strrchr函数

查找字符位置,返回的是地址

#include<iostream>

using namespace std;

const char *strchr(const char *s, char c) {
    char *p = const_cast<char *>(s);
    while (*p) {
        if (c == *p)return p;
        ++p;
    }
    return nullptr;
}
const char *strrchr(const char*s,int c){
    char *p=const_cast<char*>(s);
    char*p1= nullptr;
    while (*p){
        if (*p == c)p1=p;
        ++p;
    }
    return p1;
}
int main() {
    char s[21]{"abcdefgacaaacccadac"};
    cout<<strchr(s,'a')<<endl;
    cout<<strrchr(s,'a')<<endl;
    return 0;
}

No15、实现strcmp和strncmp函数

比较str的大小

#include<iostream>
using namespace std;

int strcmp(const char*str1,const char*str2){
    int i{0};
    while (true){
        if (str1[i]>str2[i])return 1;
        if (str1[i]<str2[i])return -1;
        if (str1[i]==0&&str2[i]==0)return 0;
        ++i;
    }
}
int strncmp(const char*str1,const char*str2,size_t n){
    for (int i = 0; i < n; ++i) {
        if (str1[i]>str2[i])return 1;
        if(str1[i]<str2[i])return -1;
//        if (str1[i]==0&&str2[i]==0)return 0;
    }
    return 0;
}


int main(){
    char s1[11]="abcde";
    char s2[11]="abcde";
    cout<<strcmp(s1,s2)<<endl;
    cout<<strncmp(s1,s2,6)<<endl;
    return 0;
}

No16、实现strstr函数 复刷

返回子串在目标串中第一次出现的位置

/*!
 * 查找子串
 * 两种方法:
 * 1.BP 暴力算法 本次实现的是BP
 * 2.KMP算法
 */
#include<iostream>
#include<cstring>

using namespace std;
//BP
const char *strstr_BP(const char *str, const char *substr) {
    size_t i{0}, j{0}, len{::strlen(str)}, slen{::strlen(substr)};
    while (i<len && j<slen){//i==len代表目标串结束  j==slen代表查找成功
        if(str[i]==substr[j]){//如果比较相等,那么继续向后比较
            ++i;
            ++j;
        } else{//如果比较不相等
            i -=j;//目标串回退j位,回到本次起始的位置
            j=0;//子串数组下标归0
            ++i;//目标串向后移1个字符(下次起始位置) 准备重来
        }
    }
    //循环完 如果访问完毕了子串 说明成功
    //但是此时i在目标串的末尾 j在子串末尾 所以子串在目标串匹配的位置如下
    if(j==slen)return str+i-j;
    return nullptr;//找不到返回空
}

int main() {
    char str[21]="hxxhelloxadsad";
    char substr[6]="hello";
    cout<<strstr_BP(str,substr);
    return 0;
}

No17、删除字符串右边指定的字符 复刷

#include<iostream>
#include<cstring>

using namespace std;

/*实例 删除y
 * duyy -> du
 * duyingyyy->duying
 * */
void deleteChrR(char *str, const char c = ' ') {
    if (str == nullptr)return;
    char *p = str;//指向字符串首地址
    char *piscc{nullptr};//指向右边全是字符c的第一个位置
    while (*p) {
        if (*p == c && piscc == nullptr)piscc = p;//记下字符c的第一个位置
        if (*p!=c)piscc = nullptr;//只要当前字符不是c就清空piscc
        ++p;//最后在让p向后移动一个位置
    }
    if (piscc != nullptr)*piscc = 0;//遍历完成后,只要piscc不为空说明指向右边全是字符c的第一个位置存在
}

int main() {
    char s[11] = "ada  ss";
    deleteChrR(s, 's');
    cout << s << endl;
    return 0;
}

No18、删除字符串左边指定的字符 复刷

#include<iostream>
#include<cstring>

using namespace std;

/* 删除y
 * yydu -> du
 * yyyduying->duying
 * */
//传入的s是首地址 在函数改变str也改变不了传入s的首地址  str是s的复制
void deleteChrL(char *str, const char c = ' ') {
    if(str== nullptr)return;
    char*p{str};
    while (*p==c){
        ++p;
    }
    ::memmove(str,p, ::strlen(str)-(p-str)+1);
//    ::memcpy(str,p, ::strlen(str)-(p-str)+1); 不可以
//原因:
//memcpy没有考虑内存重叠的情况,如果有内存重叠,他的行为是不确定的
//memmove()函数在memcpy()函数的基础上加入了对内存重叠拷贝的处理,保证其正确性。
//如果能确定拷贝内存没有重叠,memcpy()比memmove()更高效,如果有重叠,只能memmove
}

int main() {
    char s[21] = "sssasda  ss";
    deleteChrL(s, 's');
    cout << s << endl;
    return 0;
}

No19、删除字符串中间指定的字符 复刷

实例:

目标字符:aaxxyzyzooo
删除字符:xyz
aaxxyzyzooo->aaxyzooo->aaooo

//可采用循环 或者 递归 
//不要写无用代码
#include<iostream>
#include <cstring>

using namespace std;
char*strstr_BP(char *str,const char *substr){
    int i{0},j{0};
    size_t len = strlen(str),slen=strlen(substr);
    while (i<len&&j<slen){
        if(str[i]==substr[j]){
            ++i;
            ++j;
        }else{
            i-=j;
            j=0;
            ++i;
        }
    }
    if(j==slen)return str+i-j;
    return nullptr;
}
void deleteStr(char*str,const char *substr){
    if(str== nullptr||substr== nullptr)return;
    while (true){
    	//里面的顺序是有讲究的
        int slen = ::strlen(substr);
        if(slen==0)return;
        char *p = strstr_BP(str,substr);
        if(p== nullptr)return;
        size_t len= ::strlen(str); 
        ::memmove(p,p+slen,len-(p-str)-slen+1);//+1是为了把结束符0移动过去
    }
}
int main(){
    char s[21]="aaxxyzyzooo";
    deleteStr(s,"xyz");
    cout<<s<<endl;
    return 0;
}

NO20、统计字符串的字数 复刷

在这里插入图片描述

//clion的汉字占用三个字节
#include<iostream>
using namespace std;
int sumwords(const char *str){
    int sum{0};
    int flag{0};//记录是否为汉字 false:没有记录半个汉字 true:当前已经记录半个汉字
    char* p= (char*)str;
    while (*p){
        if((unsigned char)*p<128){//ASCII码的标准字符
            ++sum;
        } else{
            if(flag==2){
                ++sum;
                flag=0;
            }else {
                flag++;
            }
        }
        p++;
    }
    return sum;
}
int main(){
    char s[21]="你好的,?xxx";
    cout<<sumwords(s)<<endl;
    return 0;
}

NO21、拆分字符串 复刷

在这里插入图片描述

/**
  ******************************************************************************
  * @file           : 拆分字符串
  * @author         : DELL
  * @brief          : None
  * @attention      : None
  * @date           : 2024-01-30
  ******************************************************************************
  */
#include<iostream>
#include<cstring>
using namespace std;

/*!
 * @param str 待拆分的字符串
 * @param splitstr 数据项的分隔字符串
 * @param value 存放拆分之后的值的数组
 * @return 拆分后数据项的个数
 */
size_t splitstr(const char *str,const char *splitstr,char values[][51]){
    if(str== nullptr||splitstr== nullptr)return 0;
    size_t slen = ::strlen(splitstr);
    if(slen==0)return 0;
    char*p=const_cast<char *>(str);
    int index{0};
    while (true){
        char*p1 = ::strstr(p,splitstr);
        if(p1== nullptr){
            ::strcpy(values[index++],p);
            break;
        } else{
            ::strncpy(values[index++],p,p1-p);
            p = p1 + slen;
        }
    }
    return index;
}

int main(){
    char s[11] = {"aa,cc,bb"};
    char splits[5] = ",";
    char values[10][51]={0};
    size_t t = splitstr(s,splits,values);
    for (size_t i = 0; i < t; ++i) {
        cout<<values[i]<<endl;
    }
    cout<<t<<endl;
    return 0;
}

NO22、解析XML字符串


NO23、随机数

/**
  ******************************************************************************
  * @file           : 随机数
  * @author         : DELL
  * @brief          : None
  * @attention      : None
  * @date           : 2024-01-30
  ******************************************************************************
  */
#include<iostream>
using namespace std;
//随机数在[minValue,minValue+len)
void rrand(int arr[],const size_t len,const int minValue = 0){
    srand(time(nullptr));
    for (int i = 0; i < len; ++i) {
        while(true){
            int tmp = rand()%len+minValue;
            int j;
            for (j=0; j < i; ++j)
                if(tmp == arr[j])
                    break;
            if(i==j){
                arr[i]=tmp;
                break;
            }
        }
    }
}
int main(){
    int arr[10]={0};
    rrand(arr,5,10);
    for (int i = 0; i <5 ; ++i) {
        cout<< arr[i] <<endl;
    }
    return 0;
}

NO24、随机发牌

在这里插入图片描述

/**
  ******************************************************************************
  * @file           : 随机发牌
  * @author         : DELL
  * @brief          : None
  * @attention      : None
  * @date           : 2024-01-30
  ******************************************************************************
  */
  //重点是一个发牌数组 一个洗牌数组 按照对应来发牌即可
#include<iostream>

using namespace std;

void rrand(int arr[], const int min, const int len) {
    for (int i = 0; i < len; ++i) {
        ::srand(time(nullptr));
        while (true) {
            int j, tmp = rand() % len + min;
            for (j = 0; j < i; ++j)
                if (tmp == arr[j])break;
            if (i == j) {
                arr[i] = tmp;
                break;
            }
        }
    }
}

void dealCards(int arr[4][13]) {
    int cards[52] = {-1};//洗牌数组,存放牌的数组
    rrand(cards, 1, 52);

    int sendCardsArr[52] = {-1};//发牌数组,存放所发牌的下标
    rrand(sendCardsArr, 0, 52);

    int j = 0;
    for (int i = 0; i < 13; ++i) {
        arr[0][i] = cards[sendCardsArr[j++]];
        arr[1][i] = cards[sendCardsArr[j++]];
        arr[2][i] = cards[sendCardsArr[j++]];
        arr[3][i] = cards[sendCardsArr[j++]];
    }
}

int main() {
    int arr[4][13] = {0};
    dealCards(arr);
    for (int i = 0; i < 4; ++i) {
        cout<< "玩家" <<i+1<<":";
        for (int j = 0; j < 13; ++j) {
            cout<<arr[i][j]<<" ";
        }
        cout<<"\n";
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值