Respecto al primer código, sinceramente, veo cosas muy raras.
Voy a analizarlo.
1º. Parámetros. ¿Por que pasarle a la función CountA un "diccionario" si solo estás buscando la letra 'a' o la 'A'?
Creo que es lógico que la función solo pida la cadena (frase) en cuestión:
void CountA(char frase[])
2º El valor de retorno. Según el ejercicio, la función debe retornar un entero, en concreto, la cantidad de 'a'
o 'A':
int CountA(/*Parámetros*/)
3º El ciclo for no itera por todos los elementos de la frase.
for (j = 0; j < num-1; j++)
debería ser...
for (j = 0; j < num; j++)
4º Sin tener en cuenta las anotaciones de antes, veamos el código de la función en sí
¿Por qué guardas la letra que deseas comprobar en cada iteración del bucle for?
for ... {
...
letra = diccionario[i];
}
La variable 'i' no cambia en toda la función, así que la letra tampoco.
Respecto al segundo código, si bien puedes representar un vector y una matriz con esas estructuras, es mejor que dentro de estas guardes arreglos:
typedef struct{
double elems[2];
} Vec;
typedef struct {
double elems[2][2];
} Mat;
Eso ya es opinión mía.
Respecto al último ejercicio, has de recordar cómo se multiplican las matrices.
En el caso de una matriz 2x2 por una matriz columna de 2x1 se hace así:
Ejemplo:
(ma mb) (va)
(mc md) (vb) =
(ma*va + mb*vb)
(mc*va + md*vb)