简化我的程序,将数字从一个基转换为另一个基 我正在攻读初级C++课程。我接到一个任务,要求我编写一个程序,将任意数从二进制和十六进制之间的任意基数转换为二进制和十六进制之间的另一个基数。我被要求使用不同的函数来转换base 10和base 10。这是为了帮助我们习惯使用数组。(我们以前在课堂上已经讨论过通过引用传递。)我已经上交了,但我很确定这不是我应该做的: #include <iostream> #include <conio.h> #include <cstring> #include <cmath> using std::cout; using std::cin; using std::endl; int to_dec(char value[], int starting_base); char* from_dec(int value, int ending_base); int main() { char value[30]; int starting_base; int ending_base; cout << "This program converts from one base to another, so long as the bases are" << endl << "between 2 and 16." << endl << endl; input_numbers: cout << "Enter the number, then starting base, then ending base:" << endl; cin >> value >> starting_base >> ending_base; if (starting_base < 2 || starting_base > 16 || ending_base < 2 || ending_base > 16) { cout << "Invalid base(s). "; goto input_numbers; } for (int i=0; value[i]; i++) value[i] = toupper(value[i]); cout << "Base " << ending_base << ": " << from_dec(to_dec(value, starting_base), ending_base) << endl << "Press any key to exit."; getch(); return 0; } int to_dec(char value[], int starting_base) { char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; long int return_value = 0; unsigned short int digit = 0; for (short int pos = strlen(value)-1; pos > -1; pos--) { for (int i=0; i<starting_base; i++) { if (hex[i] == value[pos]) { return_value+=i*pow((float)starting_base, digit++); break; } } } return return_value; } char* from_dec(int value, int ending_base) { char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; char *return_value = (char *)malloc(30); unsigned short int digit = (int)ceil(log10((double)(value+1))/log10((double)ending_base)); return_value[digit] = 0; for (; value != 0; value/=ending_base) return_value[--digit] = hex[value%ending_base]; return return_value; } #包括 #包括 #包括 #包括 使用std::cout; 使用std::cin; 使用std::endl; int到_dec(字符值[],int起始_基); 字符*from_dec(int值,int结尾_基); int main(){ 字符值[30]; int-U基地; int END_基地; cout 16 | | end|u base16){ cout
我认为你不需要内环:简化我的程序,将数字从一个基转换为另一个基 我正在攻读初级C++课程。我接到一个任务,要求我编写一个程序,将任意数从二进制和十六进制之间的任意基数转换为二进制和十六进制之间的另一个基数。我被要求使用不同的函数来转换base 10和base 10。这是为了帮助我们习惯使用数组。(我们以前在课堂上已经讨论过通过引用传递。)我已经上交了,但我很确定这不是我应该做的: #include <iostream> #include <conio.h> #include <cstring> #include <cmath> using std::cout; using std::cin; using std::endl; int to_dec(char value[], int starting_base); char* from_dec(int value, int ending_base); int main() { char value[30]; int starting_base; int ending_base; cout << "This program converts from one base to another, so long as the bases are" << endl << "between 2 and 16." << endl << endl; input_numbers: cout << "Enter the number, then starting base, then ending base:" << endl; cin >> value >> starting_base >> ending_base; if (starting_base < 2 || starting_base > 16 || ending_base < 2 || ending_base > 16) { cout << "Invalid base(s). "; goto input_numbers; } for (int i=0; value[i]; i++) value[i] = toupper(value[i]); cout << "Base " << ending_base << ": " << from_dec(to_dec(value, starting_base), ending_base) << endl << "Press any key to exit."; getch(); return 0; } int to_dec(char value[], int starting_base) { char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; long int return_value = 0; unsigned short int digit = 0; for (short int pos = strlen(value)-1; pos > -1; pos--) { for (int i=0; i<starting_base; i++) { if (hex[i] == value[pos]) { return_value+=i*pow((float)starting_base, digit++); break; } } } return return_value; } char* from_dec(int value, int ending_base) { char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; char *return_value = (char *)malloc(30); unsigned short int digit = (int)ceil(log10((double)(value+1))/log10((double)ending_base)); return_value[digit] = 0; for (; value != 0; value/=ending_base) return_value[--digit] = hex[value%ending_base]; return return_value; } #包括 #包括 #包括 #包括 使用std::cout; 使用std::cin; 使用std::endl; int到_dec(字符值[],int起始_基); 字符*from_dec(int值,int结尾_基); int main(){ 字符值[30]; int-U基地; int END_基地; cout 16 | | end|u base16){ cout,c++,C++,我认为你不需要内环: for (int i=0; i<starting_base; i++) { 数学: 回路的预期工作状态: x = 0 x = 4x + 3 = 3 x = 4x + 0 = 12 x = 4x + 1 = 49 x = 4x + 2 = 198 return x; 编辑2: 很公平!那么,这里还有一些:-) 这是一个代码草图。虽然没有编译或测试。这是我之前提供的示例的直接翻译 unsigned to_dec( char * inputS
for (int i=0; i<starting_base; i++) {
数学:
回路的预期工作状态:
x = 0
x = 4x + 3 = 3
x = 4x + 0 = 12
x = 4x + 1 = 49
x = 4x + 2 = 198
return x;
编辑2: 很公平!那么,这里还有一些:-) 这是一个代码草图。虽然没有编译或测试。这是我之前提供的示例的直接翻译
unsigned
to_dec( char * inputString, unsigned base )
{
unsigned rv = 0; // return value
unsigned c; // character converted to integer
for( char * p = inputString; *p; ++p ) // p iterates through the string
{
c = *p - hex[0];
rv = base * rv + c;
}
return rv;
}
您可以通过字符串文本初始化数组(请注意,由于数组的大小不允许,因此不包括终止\0): 或者只需使用指向字符串文字的指针即可获得相同的效果:
char const* hex = "0123456789ABCDEF";
我会远离GOTO语句,除非它们是绝对必要的。GOTO语句很容易使用,但会导致“意大利面代码” 尝试使用一个循环。大致如下:
bool base_is_invalid = true;
while ( base_is_invalid ) {
cout << "Enter the number, then starting base, then ending base:" << endl;
cin >> value >> starting_base >> ending_base;
if (starting_base < 2 || starting_base > 16 || ending_base < 2 || ending_base > 16)
cout << "Invalid number. ";
else
base_is_invalid = false;
}
bool base\u为无效=真;
while(base_无效){
cout value>>起始基数>>结束基数;
如果(起始|基数<2 | |起始|基数>16 | |结束|基数<2 | |结束|基数>16)
coutto_dec()看起来很复杂,下面是我的拍摄:
int to_dec(char* value, int starting_base)
{
int return_value = 0;
for (char* cur = value + strlen(value) - 1; cur >= value; cur--) {
// assuming chars are ascii/utf: 0-9=48-57, A-F=65-70
// faster than loop
int inval = *cur - 48;
if (inval > 9) {
inval = *cur - 55;
if (inval > 15) {
// throw input error
}
}
if (inval < 0) {
// throw input error
}
if (inval >= starting_base) {
// throw input error
}
// now the simple calc
return_value *= starting_base;
return_value += inval;
}
return return_value;
}
int to_dec(字符*值,int起始值)
{
int返回_值=0;
对于(char*cur=value+strlen(value)-1;cur>=value;cur--){
//假设字符是ascii/utf:0-9=48-57,A-F=65-70
//比循环快
int inval=*cur-48;
如果(无效>9){
无效=*当前-55;
如果(无效>15){
//抛出输入错误
}
}
如果(无效<0){
//抛出输入错误
}
如果(无效>=起始\u基){
//抛出输入错误
}
//现在简单的计算
返回值*=起始基数;
返回值+=无效;
}
返回_值;
}
除了前面提到的内容之外,我建议使用new操作符而不是free。new的优点是它也会调用构造函数——这在这里是不相关的,因为您使用的是POD类型,但在涉及诸如std::string或您自己的自定义类之类的对象时很重要——并且您可以重载新的构造函数运算符来满足您的特定需求(这在这里也无关紧要:p)。但是不要继续使用malloc作为pod,而使用new作为类,因为混合使用它们被认为是不好的风格
但是,好吧,您从_dec获得了一些堆内存…但是它在哪里被再次释放?基本规则:必须在某个点传递malloc(或calloc等)以释放内存。相同的规则适用于新操作符,只是释放操作符称为delete。请注意,对于数组,您需要new[]和delete[]。永远不要使用new进行分配,使用delete[]或其他方法进行释放,因为内存无法正确释放
当你的玩具程序不释放内存时,没有什么坏事会发生……我猜你的电脑有足够的内存来处理它,当你关闭你的程序时,操作系统会释放内存……但不是所有的程序都(a)那么小,(b)经常关闭
此外,我还避免使用conio.h,因为这是不可移植的。您没有使用最复杂的IO,所以应该使用标准头(iostream等)
同样,我认为大多数使用现代语言的程序员都遵循这样的规则:“只有在其他解决方案真的有缺陷或工作量过大的情况下才使用goto”。这是一种可以通过使用循环很容易解决的情况,如主持人所示。在您的程序中,goto很容易处理,但您不会永远编写这样的小程序,是吗?;)
一、 例如,最近出现了一些遗留代码..2000行goto杂乱无章的代码,耶!试图遵循代码的逻辑流几乎是不可能的(“哦,跳200行,太好了…反正谁需要上下文”),更难的是重写这该死的东西
好吧,你的goto在这里没有什么坏处,但是它的好处在哪里?缩短2-3行?总体来说并不重要(如果你是按代码行付费的,这也可能是一个主要的缺点;)。我个人觉得循环版本更可读、更干净
正如您所看到的,这里的大多数要点对于您的程序来说很容易被忽略,因为它是一个玩具程序。但是当您想到更大的程序时,它们更有意义(希望);对于从ascii到整数的初始转换,您也可以使用查找表(就像您使用可查找表来进行相反的转换一样),这比在数组中搜索每个数字要快得多
int to_dec(char value[], int starting_base)
{
char asc2BaseTab = {0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15, //0-9 and A-F (big caps)
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //unused ascii chars
10,11,12,13,14,15}; //a-f (small caps)
srcIdx = strlen(value);
int number=0;
while((--srcIdx) >= 0)
{
number *= starting_base;
char asciiDigit = value[srcIdx];
if(asciiDigit<'0' || asciiDigit>'f')
{
//display input error
}
char digit = asc2BaseTab[asciiDigit - '0'];
if(digit == -1)
{
//display input error
}
number += digit;
}
return number;
}
int-to_-dec(字符值[],int-start_-base)
{
char asc2BaseTab={0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,10,11,12,13,14,15,//0-9和A-F(大写)
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,//未使用的ascii字符
10,11,12,13,14,15};//a-f(小型大写)
srcIdx=strlen(值);
整数=0;
而((-srcIdx)>=0)
{
数字*=起始基数;
char asciiDigit=值[srcIdx];
if(asciiDigit'f')
{
//显示输入错误
}
字符位数=asc2BaseTab[asciiDigit-'0'];
bool base_is_invalid = true;
while ( base_is_invalid ) {
cout << "Enter the number, then starting base, then ending base:" << endl;
cin >> value >> starting_base >> ending_base;
if (starting_base < 2 || starting_base > 16 || ending_base < 2 || ending_base > 16)
cout << "Invalid number. ";
else
base_is_invalid = false;
}
int to_dec(char* value, int starting_base)
{
int return_value = 0;
for (char* cur = value + strlen(value) - 1; cur >= value; cur--) {
// assuming chars are ascii/utf: 0-9=48-57, A-F=65-70
// faster than loop
int inval = *cur - 48;
if (inval > 9) {
inval = *cur - 55;
if (inval > 15) {
// throw input error
}
}
if (inval < 0) {
// throw input error
}
if (inval >= starting_base) {
// throw input error
}
// now the simple calc
return_value *= starting_base;
return_value += inval;
}
return return_value;
}
int to_dec(char value[], int starting_base)
{
char asc2BaseTab = {0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15, //0-9 and A-F (big caps)
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //unused ascii chars
10,11,12,13,14,15}; //a-f (small caps)
srcIdx = strlen(value);
int number=0;
while((--srcIdx) >= 0)
{
number *= starting_base;
char asciiDigit = value[srcIdx];
if(asciiDigit<'0' || asciiDigit>'f')
{
//display input error
}
char digit = asc2BaseTab[asciiDigit - '0'];
if(digit == -1)
{
//display input error
}
number += digit;
}
return number;
}
int to_dec(char value[], int starting_base)
int to_dec(string value, int starting_base);
string from_dec(int value, int ending_base);
string hex = "0123456789ABCDEF";//The index of the letter is its decimal value. A is 10, F is 15.
//usage
char c = 'B';
int value = hex.find( c );//works only with uppercase;
int to_dec(string value, int starting_base) {
string hex = "0123456789ABCDEF";
int result = 0;
for (int power = 0; power < value.size(); ++power) {
result += hex.find( value.at(value.size()-power-1) ) * pow((float)starting_base, power);
}
return result;
}
std::string from_dec(int n, int base)
{
std::string result;
bool is_negative = n < 0;
if (is_negative)
{
n = - n;
}
while (n != 0)
{
result = DIGITS[n % base] + result;
n /= base;
}
if (is_negative)
{
result = '-' + result;
}
return result;
}
// Write a function ConvertBase(Number, Base1, Base2) which takes a
// string or array representing an integer in Base1 and converts it
// into base Base2, returning the new string.
CString ConvertBase(const CString& strNumber, int base1, int base2)
{
return ValueToBaseString(BaseStringToValue(strNumber, base1), base2);
}
UINT64 BaseStringToValue(const CString& strNumber, int base)
{
if (strNumber.IsEmpty())
{
return 0;
}
CString outDigit = strNumber.Right(1);
UINT64 output = DigitToInt(outDigit[0]);
CString strRemaining = strNumber.Left(strNumber.GetLength() - 1);
UINT64 val = BaseStringToValue(strRemaining, base);
output += val * base;
return output;
}
int DigitToInt(wchar_t cDigit)
{
cDigit = toupper(cDigit);
if (cDigit >= '0' && cDigit <= '9')
{
return cDigit - '0';
}
return cDigit - 'A' + 10;
}
typedef struct
{
CString number;
int base1;
int base2;
CString answer;
} Input;
Input input[] =
{
{ "345678", 10, 16, "5464E"},
{ "FAE211", 16, 8, "76561021" },
{ "FAE211", 16, 2, "111110101110001000010001"},
{ "110110111", 2, 10, "439" }
};
(snip)
for (int i = 0 ; i < sizeof(input) / sizeof(input[0]) ; i++)
{
CString result = ConvertBase(input[i].number, input[i].base1, input[i].base2);
printf("%S in base %d is %S in base %d (%S expected - %s)\n", (const WCHAR*)input[i].number,
input[i].base1,
(const WCHAR*) result,
input[i].base2,
(const WCHAR*) input[i].answer,
result == input[i].answer ? "CORRECT" : "WRONG");
}
345678 in base 10 is 5464E in base 16 (5464E expected - CORRECT)
FAE211 in base 16 is 76561021 in base 8 (76561021 expected - CORRECT)
FAE211 in base 16 is 111110101110001000010001 in base 2 (111110101110001000010001 expected - CORRECT)
110110111 in base 2 is 439 in base 10 (439 expected - CORRECT)