廣島です.
> ちなみに,多項式計算のアルゴリズム
>
> 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@...)