(C++练习)细节知识记录
最近捡起很久没有复习过的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++中数组的最大长度)
- C/C++知识细节整理
- c/c++ 细节点记录
- 【基础知识】c++字符串中需要注意的一些细节
- c++碰到的一些细节知识
- 数组实现栈功能(2)——类模板(C++练习记录)
- C++ 练习记录1--vector<T> 中T的初始化
- 讨论记录之C++细节
- 紫书c++语言基础细节知识
- 初学C++基本知识记录
- 数组实现队列功能(C++练习记录)
- c/c++细节知识整理
- C++练习题目记录
- 讨论记录之C++细节
- C++ Primer Plus 第六版 第四章编程练习记录
- C++细节系列(零):零散记录
- 1008_C/C++笔试题_17:c细节知识几点
- C++细节点记录
- c++细节知识总结
- C/C++ 新学知识记录
- C++ 细节知识整理!