2016-09-10 5 views
-2

数値を任意の基数から任意の基数に変換するC言語のプログラムを実行しています。 10進数から任意のベースで動作しましたが、どのベースからの変換を実装してもセグメント化エラーが発生します。私はIDEを使用しないことを指定する必要があります。奇妙なことは、私が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; 
} 

答えて

2

あなたは、いくつかの本当のバグを持っていました。いくつかはクラッシュを引き起こすでしょう。他のものは間違った結果をもたらすでしょう。まず、バグについて説明します。

また、以下では、2つのバージョンのプログラムを作成しました。 1つは、[修正あり]のバグを示すコメント付きの注釈です。そして、もう1つはクリーンアップされたバージョンです。後方作業クラッシュのために


、:それは swapArray(valueArray)valueArrayは/ convertNULL
  • だろう可能性がどうなるNULLポインタ
  • convertを与えられたので、

    1. swapArrayはセグメンテーションフォルトして、 valが0である場合(つまり、01のループを有する場合)valueArrayNULLとなりますゼロ反復
    2. を有するであろう
    3. val /(IE)これら二つのループは常にを実行すべき
    4. 最初の二つのループが実行されない(IE)if (startingBase != 10)試験は不要10であったゼロstartingBase場合であろう可能性/間違った
    5. また、#5を修正しても、valはゼロ[正当]である(つまり)元の値である可能性があります。だから、reallocループがvalueArrayNULLではないことを保証に、少なくとも一度に実行するために再設計する必要があります。

      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; 
    } 
    
  • 関連する問題