#include<stdio.h>
#include<math.h>	// Compilar con "-lm"

#define MIDA	80
#define BASEMAX	16
#define BASEMIN	2

double log_b(double base, double num) {
	// El log de num en base base es:
	return log(num)/log(base);
}

void canvi_base(char vi[MIDA], int bi, char vo[MIDA], int bo) {
	int i, n;

	// Calculo que numero es vi que viene dado en base bi -> n
	for(i=0,n=0;vi[i]!='\0';i++) {
		n = n*bi;
		if ((vi[i]>='0')&&(vi[i]<='9')) n = n+vi[i]-'0';
		else if ((vi[i]>='A')&&(vi[i]<='F')) n = n+vi[i]-'A'+10;
		else if ((vi[i]>='a')&&(vi[i]<='f')) n = n+vi[i]-'a'+10;
	}
	printf("\t(en base 10 es %d)\n", n);
	// Version2: relleno vo empezando por el final porque se que:
	// El numero de digitos de n en base bo es igual a
	// el logaritmo en base bo de n truncado a entero + 1
	i = (int) log_b(bo,n) + 1;
	vo[i]='\0';
	i--;
	for(;i>=0;i--) {
		vo[i] = n % bo;
		if (vo[i]>9) vo[i]=vo[i]-10+'A';
		else  vo[i]=vo[i]+'0';
		n = n / bo;
	}
}

int main() {
	char vi[MIDA], vo[MIDA];
	int bi, bo, i;
	char c;

	printf("Conversio de nums de qualsevol base a qualsevol base (de base %d a base %d)\n",
			BASEMIN, BASEMAX);
	printf("Intro num en qualsevol base: ");
	for(i=0;c!='\n';i++) {
		scanf("%c", &c);
		vi[i] = c;
	}
	vi[i-1] = '\0';
	do {
		printf("En quina base esta? ");
		scanf("%d", &bi);
	} while (bi < BASEMIN || bi > BASEMAX);
	do {
		printf("A quina base el vols convertir? ");
		scanf("%d", &bo);
	} while (bo < BASEMIN || bo > BASEMAX);
	canvi_base(vi, bi, vo, bo);
	printf("%s en base %d\n", vi, bi);
	printf("es %s en base %d\n", vo, bo);
}

/*
 * Se podria compilar con
 * gcc t4_canvi_base.c -O2 -Wall -Wno-unused-result
 * Para ver todos los warnings menos los del tipo:
 * t4_canvi_base.c:44:3: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
 *    scanf("%c", &c);
 *    ^~~~~~~~~~~~~~~
 */

