あなたは、いくつかの本当のバグを持っていました。いくつかはクラッシュを引き起こすでしょう。他のものは間違った結果をもたらすでしょう。まず、バグについて説明します。
また、以下では、2つのバージョンのプログラムを作成しました。 1つは、[修正あり]のバグを示すコメント付きの注釈です。そして、もう1つはクリーンアップされたバージョンです。後方作業クラッシュのために
convert
を与えられたので、
swapArray
はセグメンテーションフォルトして、 val
が0である場合(つまり、01のループを有する場合)valueArray
はNULL
となりますゼロ反復 を有するであろう
val
/(IE)これら二つのループは常にを実行すべき
- 最初の二つのループが実行されない(IE)
if (startingBase != 10)
試験は不要10であったゼロstartingBase
場合であろう可能性/間違った
- また、#5を修正しても、
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;
}
はクリーンアップバージョンです。
さておき、古いコードと「NOTE/BUG」のコメントの「醜さ」を取り除くから、主に、それがループ内で繰り返し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[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
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;
}