作者: Tsutomu Hiroshima
日時: 2003/10/23(09:00)
廣島です.

> ちなみに,多項式計算のアルゴリズム
> 
> a*x^3 + b*x^2 + c*x + d = (((a*x + b)*x + c)*x + d
> 
> は Scheme か Common Lisp の入門書で読みました.

等と,
えらそうな事を言っていましたが,
C の数値表現文字列を数値に変換するための
至極,普通のテクニックですね.
C 文字列に対してならとても簡潔に書けます.


#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#define BASE ('A' - 1)

/* 課題の変換:ABCD => 19010 */
unsigned long labelToNum(char *label) {
  unsigned long num = toupper(*(label ++)) - BASE;
  char c;
  while ((c = *(label ++)) != 0) {
    /* 文字種チェック,1 文字目は main でチェック済 */
    if (! isalpha(c)) return 0;
    num = num * 26 - BASE + toupper(c);
  }
  return num;
}

/* 逆変換:1234 => AUL */ 
char *numToLabel(unsigned long num) {
  int lg;
  unsigned char r, *label;
  unsigned long q;

  /* 空の for :必要な文字数 + 1 を計算 */
  for (q = 27, lg = 2; num >= q; q = q * 26 + 1, lg ++);
  label = malloc(lg * sizeof(char));
  if (label == NULL) return label;
    
  label[-- lg] = 0;
  while (lg > 0) {
    q = num / 26;
    /* r = num % 26 より効率良い? */
    r = num - q * 26;
    if (r == 0) {
      /* 割り切れたら上の桁から 26 借りてくる */
      q --;
      r += 26; 
    }
    label[-- lg] = r + BASE;
    num = q;
  }
  return label;    
}

int main(int argc, char *argv[]) {
  char c;
  if (argc == 1) {
    fprintf(stderr, "%s: No Argument\n", argv[0]);
    return 1;
  } else if (argc > 2) {
    fprintf(stderr, "%s: Too Many Arguments\n", argv[0]);
    return 1;
  }
  c = argv[1][0];
  if (isdigit(c)) {
    char *label = 0;
    unsigned long num = strtoul(argv[1], &label, 10);
    if (*label != 0 || num <= 0) {
      fprintf(stderr, "%s: Not a Positive Number %s\n",
	      argv[0], argv[1]);
      return 1;
    }
    label = numToLabel(num);
    if (label == NULL) {
      fprintf(stderr, "%s: Memory Error\n", argv[0]);
      return 1;
    }
    printf("%s\n", label);
    free(label);
  } else if (isalpha(c)) {
    unsigned long num = labelToNum(argv[1]);
    if (num == 0) {
      fprintf(stderr, "%s: Not a Label %s\n", argv[0], argv[1]);
      return 1;
    }
    printf("%u\n", num);
  } else {
    fprintf(stderr, "%s: Illegal Argument %s\n", argv[0], argv[1]);
    return 1;
  }
  return 0;
}


コンパイルしてできたコマンドは引数を 1 つだけ取り,
正の整数値なら アルファベット列に,
アルファベット列なら 整数値に変換し出力します.
unsinged long の桁をオーバーフロウした場合のチェックはしていません.

## スクリプト言語でなくてすいません.
-----------------------------
	廣島 勉
	(tsutomu@...)