(C++练习)细节知识记录

本文详细介绍了C++中十进制与十六进制、十六进制与十进制、十六进制与八进制之间的转换方法,包括代码实现及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


  最近捡起很久没有复习过的C++,在编程的过程中发现了很多细节问题,也可以说是稍微深入一点的知识吧,决定在此文中一一记录下来,并且在以后的编程学习中无限期更新。


十进制转十六进制

问题描述

  十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。
  给出一个非负整数,将它表示成十六进制的形式。

输入格式

  输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647

输出格式

  输出这个整数的16进制表示

样例输入

  30

样例输出

  1E

代码

#include <iostream>
using namespace std;

int main(int argc, char *argv[]) {
    long int a;
    char c[32] = {'0'};
    int tag = 0;
    cin >> a;
    if (a < 0 || a > 2147483647){
        cout << "error" << endl;
        return 0;
    } 
    int result = a, mod;
    while(result != 0){
        mod = result % 16;
        switch(mod){
            case 10: c[tag++] = 'A'; break;
            case 11: c[tag++] = 'B'; break;
            case 12: c[tag++] = 'C'; break;
            case 13: c[tag++] = 'D'; break;
            case 14: c[tag++] = 'E'; break;
            case 15: c[tag++] = 'F'; break;
            default:
                c[tag++] = '0' + mod;
                break;
        }
        result = result / 16;
    }
	
    for(int i = tag ; i >= 0; i--){
        cout << c[i];
    }
    return 0;
}

知识点总结

  2147483647(二十一亿四千七百四十八万三千六百四十七)是2147483646与2147483648之间的自然数,也是欧拉在1772年所发现的一个梅森素数,它等于2^31-1,是32位操作系统中最大的符号型整型常量,也就是4个字节的int类型能表示的最大值,这就是为什么经常在游戏中碰到经验值或者金钱的上限是21E。


十六进制转十进制

问题描述

  从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。
  注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。

样例输入

  FFFF

样例输出

  65535

代码

#include <iostream>
#include <string.h>
using namespace std;

int main(int argc, char *argv[]) {
    string s;
    cin >> s;
    char c[9];
    strncpy(c,s.c_str(),s.length()+1);
    
    int tag = 0;
    for(int i = 0; i < 9; i++){
        if(c[i] == '\0'){
        tag = i - 1;
        break;
        }
    } 
    
    int a[8] = {0};
    for(int i = 0; i <= tag; i++){
        switch(c[i]){
            case 'A': a[i] = 10; break;
            case 'B': a[i] = 11; break;
            case 'C': a[i] = 12; break;
            case 'D': a[i] = 13; break;
            case 'E': a[i] = 14; break;
            case 'F': a[i] = 15; break;
            default:
                a[i] = c[i] - '0';
                break;
        }
    } 
    long long result = 0;
    for(int i = 0; i < tag + 1; i++){
        long long temp = 1;
        for (int j = 0; j < tag - i; j++){
            temp *= 16;
        }
        result += a[i] * temp;
    } 
    cout << result << endl;
    return 0;
}

知识点总结

1)字符数组转换成字符串

char ch [] = "ABCDEFG";
string str(ch);//也可string str = ch;
char ch [] = "ABCDEFG";
string str;
str = ch;//在原有基础上添加可以用str += ch;

2)字符串转换成字符数组

string str = "ABCDEFG";
char ch[8];
for(int i = 0; i < str.len(); i++){
    ch[i] = str[i];
}
ch[str.len()] = '\0';
string str;
cin >> str;
char ch[100];
strncpy(ch,str.c_str(),str.length()+1);//str.length()+1表示要把'\0'也复制到数组

  c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同.,这是为了与C语言兼容,在C语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成C中的字符串样式。


十六进制转八进制

问题描述

  给定n个十六进制正整数,输出它们对应的八进制数。

输入格式

  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式

  输出n行,每行为输入对应的八进制正整数。

  【注意】

  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。

样例输入

  2
  39
  23ABC

样例输出

  71
  435274

错误代码示例

#include <iostream>
#include <string.h>
using namespace std;

int main(int argc, char *argv[]) {
    int h[10][100000];
    int b[400000];
    int o[10][140000];
    char temp[100000];
    int n;
    cin >> n;
    if ( n < 1 || n > 10){
        cout << "error" << endl;
        return 0; 
    }    
    int len[10] = { 0 };
    
    //赋值十六进制数组 
    string s;
    for(int i = 0; i < n; i++){
        memset(temp,'\0',sizeof(temp));
        cin >> s;
        strncpy(temp,s.c_str(),s.length()+1);
        len[i] = s.length();
        for(int j = 0; j < len[i]; j++){
            switch(temp[j]){
                case 'A': h[i][j] = 10; break;
                case 'B': h[i][j] = 11; break;
                case 'C': h[i][j] = 12; break;
                case 'D': h[i][j] = 13; break;
                case 'E': h[i][j] = 14; break;
                case 'F': h[i][j] = 15; break;
                default:
                    h[i][j] = temp[j] - '0';
                    break;
            }
        }
    }

    int tag;//记录二进制数组有多少位
    int tag2[10] = { 0 };//记录每个八进制数组有多少位 
    //赋值二进制数组和八进制数组 
    for(int i = 0; i < n; i++){
        //二进制数组赋值
        tag = 0;
        memset(b,0,sizeof(b));
        for(int j = 0; j < len[i]; j++){
            int x = h[i][j];
            for(int k = 0; k < 4; k++){
                tag++;
                b[j * 4 + 3 - k] = x % 2;
                x /= 2;
            }
        }
        //八进制数组赋值
        int mod = tag % 3;
        if(mod == 1){
            o[i][0] = b[0];
            for(int j = 1; j < tag; j += 3){
                o[i][(j + 2) / 3] = 4 * b[j] + 2 * b[j + 1] + b[j + 2];
            }
            tag2[i] = (tag + 2) / 3;
        }
        else if(mod == 2){
            o[i][0] = 2 * b[0] + b[1];
            for(int j = 2; j < tag; j += 3){
                o[i][(j + 1) / 3] = 4 * b[j] + 2 * b[j + 1] + b[j + 2];
            }
            tag2[i] = (tag + 1) / 3;
        }
        else{
            for(int j = 0; j < tag; j += 3){
            o[i][j / 3] = 4 * b[j] + 2 * b[j + 1] + b[j + 2];
            }
            tag2[i] = tag / 3;
        }
    }
    
    for(int i = 0; i < n; i++){
        int flag = 0;
        //找到第一个不为0的八进制开始输出
        for(int j = 0; j < tag2[i]; j++){
            if (o[i][j] != 0){
                flag = j;
                break;
            } 
        }
        for(; flag < tag2[i]; flag++){
            cout << o[i][flag];
        }
        cout << endl;
    }
    return 0;
}

正确代码

#include <iostream>
#include <string.h>
using namespace std;

int h[10][100000];
    int b[400000];
    int o[10][140000];
    char temp[100000];

int main(int argc, char *argv[]) {
    int n;
    cin >> n;
    if ( n < 1 || n > 10){
        cout << "error" << endl;
        return 0; 
    }
    int len[10] = { 0 };
  
    //赋值十六进制数组 
    string s;
    for(int i = 0; i < n; i++){
        memset(temp,'\0',sizeof(temp));
        cin >> s;
        strncpy(temp,s.c_str(),s.length()+1);
        len[i] = s.length();
        for(int j = 0; j < len[i]; j++){
            switch(temp[j]){
                case 'A': h[i][j] = 10; break;
                case 'B': h[i][j] = 11; break;
                case 'C': h[i][j] = 12; break;
                case 'D': h[i][j] = 13; break;
                case 'E': h[i][j] = 14; break;
                case 'F': h[i][j] = 15; break;
                default:
                    h[i][j] = temp[j] - '0';
                    break;
            }
        }
    }

    int tag;//记录二进制数组有多少位
    int tag2[10] = { 0 };//记录每个八进制数组有多少位 
    //赋值二进制数组和八进制数组 
    for(int i = 0; i < n; i++){
        //二进制数组赋值
        tag = 0;
        memset(b,0,sizeof(b));
        for(int j = 0; j < len[i]; j++){
            int x = h[i][j];
            for(int k = 0; k < 4; k++){
                tag++;
                b[j * 4 + 3 - k] = x % 2;
                x /= 2;
            }
        }

        //八进制数组赋值
        int mod = tag % 3;
        if(mod == 1){
            o[i][0] = b[0];
            for(int j = 1; j < tag; j += 3){
                o[i][(j + 2) / 3] = 4 * b[j] + 2 * b[j + 1] + b[j + 2];
            }
            tag2[i] = (tag + 2) / 3;
        }
        else if(mod == 2){
            o[i][0] = 2 * b[0] + b[1];
            for(int j = 2; j < tag; j += 3){
                o[i][(j + 1) / 3] = 4 * b[j] + 2 * b[j + 1] + b[j + 2];
            }
            tag2[i] = (tag + 1) / 3;
        }
        else{
            for(int j = 0; j < tag; j += 3){
                o[i][j / 3] = 4 * b[j] + 2 * b[j + 1] + b[j + 2];
            }
            tag2[i] = tag / 3;
        }
    }

    for(int i = 0; i < n; i++){
        int flag = 0;
        //找到第一个不为0的八进制 
        for(int j = 0; j < tag2[i]; j++){
            if (o[i][j] != 0){
                flag = j;
                break;
            } 
        }
        for(; flag < tag2[i]; flag++){
            cout << o[i][flag];
        }
        cout << endl;
    }
  
    return 0;
 }

知识点总结

  正确代码与错误代码不同之处只有一个地方,那就是将数组的声明放在了函数外,声明成了全局变量,那为什么放在函数内部声明成为局部变量就不行呢?为此我查阅了一番资料,弄清了其中的缘由。
  首先,数组的size是有限制的,在32位操作系统中,size数据类型是unsigned int,而在64位系统中,它的类型是unsigned long。前者能表示的最大值为232-1,后者能表示的最大值为264-1,这也就表示数组最大能有多大。
  其次,就是数据存放在不同的地方,也限制了这个数据类型最大能有多大。数据的分配方式有静态分配和动态分配两种,使用静态分配方法分配的局部数组是在栈中划分空间的,也就是说这一类型的数组所占空间最大不能超过栈的空间(栈有多少空间…能力有限…望大佬指点)。使用动态分配方法(new)分配的数组是在堆中划分空间的,堆的大小是与本机有效的虚存大小有关的,因此堆的空间大小一般比较大。
  一个C++程序的内存是怎样分配的呢?通常来说会分为5个区(见下表):

存放内容
全局数据区全局变量、静态变量、全局常变量
代码区程序运行的函数
栈区局部变量、函数参数、程序返回地址
堆区new产生的对象
字符串常量区字符串常量

除字符串常量外的一般常量是一个“立即数”,在程序代码中。除字符串常量外的局部常变量与局部变量同等看待。也有将全局常变量与字符串常量划分到常量区的分法,实际上,全局变量、静态变量与常量的存储很难细分,也没必要区分,可统称为全局数据区。
  因此,想要解决数组过大的问题,有两种方法。一是将数组存放在堆上,二则是将数组声明为全局变量,也就是本例正确代码中采取的方法。(参考文章:C++如何定义一个长度超过一百万的数组C++中数组的最大长度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值