strchr es la función que buscas. Devuelve la posición de memoria de la primera aparición de un carácter en una cadena.
Sea ABCDE... tu cadena base, la que te dará el índice según el carácter actual de tu cadena a codificar. Sea !26&$... tu cadena código que tiene los caracteres codificados. Debes pasarle a strchr dicha cadena base y el susodicho carácter, entonces strchr te devolverá una posición de memoria del mismo carácter dentro de la cadena base. Haciendo uso de la aritmética de punteros debes restar dicha posición de memoria con la dirección de la misma cadena base. Esto te dará un número natural. A este número natural, que deberás hacer un cast a size_t para que el compilador no se queje, se lo das como índice a la cadena código. En este momento ya tienes el carácter codificado.
lim_inferior + rand() % (lim_superior - lim_inferior) Si solo pones el límite superior después del módulo te podría dar ese límite y además le sumarías el límite inferior, con lo que saldrías de rango.
Por ejemplo, fíjate en el array com: es de 10 elementos, eso es para una cadena de 9 caracteres efectivos y, sin embargo, con strcpy le introduces una cadena muy larga.
Lo que ocurre es que de esa forma no se tratan las cadenas de caracteres. Las cadenas van entre comillas dobles y para compararlas se deben usar funciones de librería. A menos que uses objetos string, entonces la cosa cambia.
signo es un carácter y un carácter no se puede comparar con una cadena, en este caso raiz2.
Lo mismo para los case. El valor de los case sólo pueden ser constantes numéricas. Los caracteres como tales también son números, no así las cadenas que son arrays.