我正在用C编写程序,将数字从任何基数转换为任何基数。它从十进制到任何基础工作但是当我从任何基础实现转换时,我得到分段错误:我必须指定我不使用IDE,只是gcc命令将我的程序链接到静态库。奇怪的是,我尝试在Windows上编译,但它确实有效。有人可以帮助我吗?
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> //library for isdigit
#include <string.h>
#include "ylantron.h" //<-- my library
#define MAX_SYMBOLS 36
void pause();
char* convert(char* value, int startingBase, int endingBase);
char* swapArray(char *oldArray);
// MAIN
int main(int argc, char *argv[]){
/* CHECK ARGUMENTS NUMBER */
if (argc != 4 ){
printf("\n\e[91m[X]\e[39m Invalid number argument\n");
pause();
return 1;
}
/* CHECK ARGUMENTS */
if ( (isdigit(argv[1][0])==0) || (isdigit(argv[2][0])==0) || (isdigit(argv[3][0])==0) ){
printf("\n\e[91m[X]\e[39m One of the arguments is not a number\n");
pause();
return 1;
}
/* CHECKING BASES */
int check=0;
char *baseType=(char*)calloc(9,sizeof(char));
char *infSup=(char*)calloc(10,sizeof(char));
int numMinMax;
if (atoi(argv[1])<2) { strcpy(baseType,"starting"); strcpy(infSup,"inferior"); numMinMax=2; check=1; }
else if (atoi(argv[1])>MAX_SYMBOLS) { strcpy(baseType,"starting"); strcpy(infSup,"superior"); numMinMax=MAX_SYMBOLS; check=1; }
else if (atoi(argv[3])<2) { strcpy(baseType,"ending"); strcpy(infSup,"inferior"); numMinMax=2; check=1; }
else if (atoi(argv[3])>MAX_SYMBOLS) { strcpy(baseType,"ending"); strcpy(infSup,"superior"); numMinMax=MAX_SYMBOLS; check=1; }
if (check==1){
printf("\n\e[91m[X]\e[39m The %s base can't be %s to %d\n", baseType, infSup, numMinMax);
free(baseType);
free(infSup);
pause();
return 1; }
int base_from, base_to;
char* val;
base_from=atoi(argv[1]);
val=argv[2];
base_to=atoi(argv[3]);
if (base_from==base_to) { printf("\n\e[93m[?]\e[39m Why you want me to convert a number with equal bases?"); pause(); return 1; }
printf("\nThe result is %s\n\n",converti(val,base_from,base_to));
return 0;
}
// FUNCTIONS
void pause() {
printf("\nPress any key...");
getch();
printf("\n");
}
char* convert(char* value, int startingBase, int endingBase){
char symbols[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
char *valueArray=NULL;
int val=0;
if (startingBase != 10 ){
for (int i=0;i<(strlen(value)/sizeof(char));i++){
for (int j=0;j<MAX_SYMBOLS;j++){
if (value[i]==symbols[j]){
val+=j;
break;
}
}
}
}
printf("val: %d",val);
for (int i=1;val!=0;){
valueArray=(char *)realloc(valueArray,(++i)*sizeof(char));
valueArray[i-2]=symbols[(val%endingBase)];
valueArray[i-1]='\0';
val/=endingBase;
}
swapArray(valueArray);
return valueArray;
}
char* swapArray(char *oldArray){
char old;
int i,j;
for (i=0,j=strlen(oldArray)-1;i<(strlen(oldArray)/2);i++,j--){
old=oldArray[i];
oldArray[i]=oldArray[j];
oldArray[j]=old;
}
return oldArray;
}
答案 0 :(得分:2)
你有一些真正的错误。有些会产生崩溃。其他人会产生错误的结果。首先,我将解释这些错误。
此外,我在下面制作了两个版本的程序。一个注释注释显示错误[有修复]。并且,第二个清理版本。
对于崩溃,倒退:
swapArray
是segfaulting,因为它被赋予NULL
指针convert
会swapArray(valueArray)
而valueArray
可以/ NULL
convert
中,如果valueArray
为零,则NULL
为val
(即)realloc
的循环将为零迭代val
如果startingBase
为10,则可能为零(即)前两个循环不会被执行if (startingBase != 10)
测试是多余的/错误的val
仍然可以[合法地]为零(即)原始值 为零。因此,realloc
循环必须重新架构,至少执行一次,保证 valueArray
不 NULL
。 好的,这可以处理崩溃,但程序仍然会产生不正确的结果,因为在行上方:
val += j;
我们需要乘以起始基数,如下所示:
val *= startingBase;
val += j;
以下是带注释的版本。
风格是:#if 0 /*original code*/ #else /*fixed code*/ #endif
并且有评论解释事情[请原谅无偿风格的清理]:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // library for isdigit
#include <string.h>
#include <curses.h>
//#include "ylantron.h" // <-- my library
#define MAX_SYMBOLS 36
void pause();
char *convert(char *value, int startingBase, int endingBase);
char *swapArray(char *oldArray);
// MAIN
int
main(int argc, char *argv[])
{
/* CHECK ARGUMENTS NUMBER */
if (argc != 4) {
printf("\n\e[91m[X]\e[39m Invalid number argument\n");
pause();
return 1;
}
/* CHECK ARGUMENTS */
if ((isdigit(argv[1][0]) == 0) || (isdigit(argv[2][0]) == 0) || (isdigit(argv[3][0]) == 0)) {
printf("\n\e[91m[X]\e[39m One of the arguments is not a number\n");
pause();
return 1;
}
/* CHECKING BASES */
int check = 0;
char *baseType = (char *) calloc(9, sizeof(char));
char *infSup = (char *) calloc(10, sizeof(char));
int numMinMax;
int base_from;
int base_to;
char *val;
base_from = atoi(argv[1]);
val = argv[2];
base_to = atoi(argv[3]);
if (base_from < 2) {
strcpy(baseType, "starting");
strcpy(infSup, "inferior");
numMinMax = 2;
check = 1;
}
else if (base_from > MAX_SYMBOLS) {
strcpy(baseType, "starting");
strcpy(infSup, "superior");
numMinMax = MAX_SYMBOLS;
check = 1;
}
else if (base_to < 2) {
strcpy(baseType, "ending");
strcpy(infSup, "inferior");
numMinMax = 2;
check = 1;
}
else if (base_to > MAX_SYMBOLS) {
strcpy(baseType, "ending");
strcpy(infSup, "superior");
numMinMax = MAX_SYMBOLS;
check = 1;
}
if (check == 1) {
printf("\n\e[91m[X]\e[39m The %s base can't be %s to %d\n",
baseType, infSup, numMinMax);
free(baseType);
free(infSup);
pause();
return 1;
}
if (base_from == base_to) {
printf("\n\e[93m[?]\e[39m Why you want me to convert a number with equal bases?");
pause();
return 1;
}
printf("\nThe result is %s\n\n", convert(val, base_from, base_to));
return 0;
}
// FUNCTIONS
void
pause()
{
printf("\nPress any key...");
getch();
printf("\n");
}
char *
convert(char *value, int startingBase, int endingBase)
{
char symbols[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
char *valueArray = NULL;
int val = 0;
// NOTE/BUG: this should _always_ be executed regardless of base
#if 0
if (startingBase != 10) {
#endif
for (int i = 0; i < (strlen(value) / sizeof(char)); i++) {
for (int j = 0; j < MAX_SYMBOLS; j++) {
if (value[i] == symbols[j]) {
// NOTE/BUG: when assembling the number we must multiply by
// the base
#if 1
val *= startingBase;
#endif
val += j;
break;
}
}
}
#if 0
}
#endif
// NOTE: for debug?
printf("val: %d", val);
// NOTE/BUGS:
// (1) if val is zero, this loop will never be executed and
// valueArray will remain NULL
// (2) if startingBase _is_ 10, then val could _never_ be non-zero
#if 0
for (int i = 1; val != 0;) {
valueArray = (char *) realloc(valueArray, (++i) * sizeof(char));
valueArray[i - 2] = symbols[(val % endingBase)];
valueArray[i - 1] = '\0';
val /= endingBase;
}
#else
int i = 1;
while (1) {
valueArray = (char *) realloc(valueArray, (++i) * sizeof(char));
valueArray[i - 2] = symbols[(val % endingBase)];
valueArray[i - 1] = '\0';
val /= endingBase;
if (val == 0)
break;
}
#endif
// NOTE/BUG: this produces a segfault if valueArray is NULL
swapArray(valueArray);
return valueArray;
}
char *
swapArray(char *oldArray)
{
char old;
int i;
int j;
// NOTE/BUG: strlen gives segfault if oldArray is NULL
for (i = 0, j = strlen(oldArray) - 1; i < (strlen(oldArray) / 2); i++, j--) {
old = oldArray[i];
oldArray[i] = oldArray[j];
oldArray[j] = old;
}
return oldArray;
}
这是清理过的版本。
除了删除&#34;丑陋&#34;旧代码和&#34;注意/ BUG&#34;评论,主要是,它改变了处理字符串的循环,从循环内部重复调用strlen
来代替寻找EOS字符。我已经在几个循环中对此进行了更改,并生成了swapArray
的一些变体以显示可以执行的操作。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // library for isdigit
#include <string.h>
#include <curses.h>
//#include "ylantron.h" // <-- my library
#define MAX_SYMBOLS 36
void pause();
char *convert(char *value, int startingBase, int endingBase);
char *swapArray(char *oldArray);
// MAIN
int
main(int argc, char *argv[])
{
/* CHECK ARGUMENTS NUMBER */
if (argc != 4) {
printf("\n\e[91m[X]\e[39m Invalid number argument\n");
pause();
return 1;
}
/* CHECK ARGUMENTS */
if ((isdigit(argv[1][0]) == 0) || (isdigit(argv[2][0]) == 0) || (isdigit(argv[3][0]) == 0)) {
printf("\n\e[91m[X]\e[39m One of the arguments is not a number\n");
pause();
return 1;
}
/* CHECKING BASES */
int check = 0;
char *baseType = (char *) calloc(9, sizeof(char));
char *infSup = (char *) calloc(10, sizeof(char));
int numMinMax;
int base_from;
int base_to;
char *val;
base_from = atoi(argv[1]);
val = argv[2];
base_to = atoi(argv[3]);
if (base_from < 2) {
strcpy(baseType, "starting");
strcpy(infSup, "inferior");
numMinMax = 2;
check = 1;
}
else if (base_from > MAX_SYMBOLS) {
strcpy(baseType, "starting");
strcpy(infSup, "superior");
numMinMax = MAX_SYMBOLS;
check = 1;
}
else if (base_to < 2) {
strcpy(baseType, "ending");
strcpy(infSup, "inferior");
numMinMax = 2;
check = 1;
}
else if (base_to > MAX_SYMBOLS) {
strcpy(baseType, "ending");
strcpy(infSup, "superior");
numMinMax = MAX_SYMBOLS;
check = 1;
}
if (check == 1) {
printf("\n\e[91m[X]\e[39m The %s base can't be %s to %d\n",
baseType, infSup, numMinMax);
free(baseType);
free(infSup);
pause();
return 1;
}
if (base_from == base_to) {
printf("\n\e[93m[?]\e[39m Why you want me to convert a number with equal bases?");
pause();
return 1;
}
printf("\nThe result is %s\n\n", convert(val, base_from, base_to));
return 0;
}
// FUNCTIONS
void
pause()
{
printf("\nPress any key...");
getch();
printf("\n");
}
char *
convert(char *value, int startingBase, int endingBase)
{
char symbols[] = { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
char *valueArray = NULL;
int val = 0;
for (int chr = *value++; chr != 0; chr = *value++) {
for (int j = 0; j < MAX_SYMBOLS; j++) {
if (chr == symbols[j]) {
val *= startingBase;
val += j;
break;
}
}
}
int i = 1;
while (1) {
valueArray = (char *) realloc(valueArray, (++i) * sizeof(char));
valueArray[i - 2] = symbols[(val % endingBase)];
valueArray[i - 1] = '\0';
val /= endingBase;
if (val == 0)
break;
}
swapArray(valueArray);
return valueArray;
}
char *
swapArray(char *oldArray)
{
char old;
int i;
int j;
for (i = 0, j = strlen(oldArray) - 1; i < (strlen(oldArray) / 2); i++, j--) {
old = oldArray[i];
oldArray[i] = oldArray[j];
oldArray[j] = old;
}
return oldArray;
}
char *
swapArray_2(char *oldArray)
{
char old;
int len;
int i;
int j;
len = strlen(oldArray);
for (i = 0, j = len - 1; i < (len / 2); i++, j--) {
old = oldArray[i];
oldArray[i] = oldArray[j];
oldArray[j] = old;
}
return oldArray;
}
char *
swapArray_3(char *oldArray)
{
char *lhs;
char *rhs;
char old;
lhs = oldArray;
rhs = &lhs[strlen(lhs) - 1];
for (; lhs < rhs; ++lhs, --rhs) {
old = *lhs;
*lhs = *rhs;
*rhs = old;
}
return oldArray;
}