Bueno, echando un vistazo por encima, veo que ya está algo mejor.
De todas formas empiezo desde el principio:
CABECERAS: Sólo tienes que incluir las cabeceras necesarias, es decir, las que contengan las funciones que tú vas a utilizar. En este caso tienes:
- stdio.h -> Contiene las funciones de entrada/salida típicas de C (printf()/scanf() /Funciones sobre ficheros en C/...) -> No lo utilizas.
- iostream -> Contiene las "funciones" de entrada/salida típicas de C++ (cout <</cin >>/...) -> Sí la utilizas.
- string -> Contiene el tipo de dato std::string, entre otras cosas. -> Sí la utilizas.
- conio.h -> Contiene entre otras cosas la función getch(). Esta librería no pertenece al estándar y está desaconsejado su uso. Un buen sustituto de getch() en C++ es cin.get() (que pertenece a <iostream>) y en C es getchar() (que pertenece a <stdio.h>). -> No la utilizas y no creo que lo necesites.
- stdlib.h -> Contiene funciones como system()/srand()/rand() /conversores de tipos/... -> No la utilizas.
Todas las bibliotecas que no utilizas es mejor eliminarlas. Primero para ahorrar espacio ya que cada include lo que hace es copiar el contenido de cada uno de esos ficheros. Y segundo, para sabe cuándo necesitas una u otra biblioteca.
Además todas las que terminan en ".h" son propias de C. Estas también funcionan en C++ pero las propias de C++ se denominan igual pero quitando el ".h" del final y añadiendo una "c" al principio -> cstdio/cstdlib/...
VARIABLES/CONSTANTES GLOBALES/LOCALES
No es recomendable utilizar variables globales. Las variables es mejor crearlas locales a una función y utilizar los parámetros cuando sea necesario para enviarlas a otras funciones.
Sin embargo, es mejor creas constantes globales como si fueran valores de configuración antes que colocar números sueltos por ahí. Así es más fácil modificar el programa. Aunque si se va a inicializar un array al momento de la declaración, no es necesario determinar su longitud ya que esta será la que tenga una vez inicializado.
Además el método tradicional de crear arrays en C/C++ dice que si son estáticas, deben declararse con constantes y no se permiten variables. Para crear arrays con tamaños definidos en tiempo de ejecución hay que usar memoria dinámica.
Por convenio, los nombres de variables/funciones se definen en lowerCamelCase (primera palabra en minúsculas y a partir de ahí cada palabra con la primera letra en mayúsculas) y los nombres de constantes en SCREAMING_SNAKE_CASE (todas las letras en mayúsculas y las palabras separadas por guión bajo _).
const int NUM_ALUMNOS = 2; // Este valor deberia usarse tambien para el array de nombres para asegurar la misma longitud
const int NUM_MATERIAS = 4;
FILTRO DE DATOS
Cuando se quiere pedir un dato hasta que éste sea válido se suele utilizar un filtro do-while(). La estructura do-while() primero ejecuta lo que hay dentro y luego comprueba la condición. Se diferencia del while() en que el código que hay dentro del do{} al menos se ejecutará una vez.
int numero;
bool valido;
do { // Hacer esto...
cout << "Introduce un numero positivo: ";
cin >> numero;
// Si se quiere mostrar un mensaje es mejor crear una variable para guardar la comprobacion
// Sino tambien se puede poner la condicion directamente en los parentesis del while()
valido = (numero >= 0);
if(!valido)
cout << "El numero debe ser positivo" << endl;
} while(!valido); // ...mientras el numero introducido no sea valido
OTROS ERRORES
- Las variables i y j de la línea 14 nunca se utilizan. En los bucles de las líneas 20 y 32 estás declarando otras dos que solo existen hasta que acabe cada uno de los for().
- El bucle de la línea 32 está dentro del if() de la línea 24 por lo que solo se ejecutará bien si de primeras introduces un número de materias no válido. Cuando apliques el filtro do-while() tendrás que poner el for() de la línea 32 después del do-while() para que se ejecute siempre que se tenga ya un número válido.
- No estás utilizando la matriz notas[][]. Deberías utilizarla para guardar en cada fila las notas de un alumno y en cada columna la nota de una materia. Esto se haría así:
for(int i = 0; i < NUM_ALUMNOS; ++i){
for(int j = 0; j < NUM_MATERIAS; ++j){
cout << "Introduce la nota " << (j+1) << " del alumno " << (i+1) << ": ";
cin >> notas[i][j];
}
}
Ahora tienes que revisar todas estas cosas que no son pocas e introducirlas en tu programa correctamente.
Suerte.
PD: El bucle for() de la línea 32 debería estar identado al mismo nivel que el bucle while() de la línea 27. No se trata de identar cada fragmento de código más a la derecha sino de mantener una estructura de orden para saber qué cosas están dentro de qué otras cosas y cuáles están al mismo nivel.