Validar entrada de scanf

Necesito leer horas: minutos en este formato exacto. Yo suelo:

int hours, minutes; if (scanf("%d:%d", &hours, &minutes)!= 2) { printf("Wrong input.\n"); return 1; } else if (minutes>60 || minutes<0 || hours60 || minutes<0 || hours<0) { printf("Wrong input 2.\n"); return 1; } ... 

funciona bien, pero necesito obtener “entrada incorrecta” también en situaciones en las que alguien ingresa, por ejemplo, 5: 38abc

Agregue un operador a la cadena de formato para que coincida con la nueva línea:

 int hours, minutes; char str[2]; if (scanf("%d:%d%1[\n]", &hours, &minutes, str)!= 3) 

%[\n] coincide con los caracteres de nueva línea, y el ancho del campo 1 hace que deje de coincidir después de exactamente 1 carácter.

La forma tradicional es leer una línea completa usando getline (3) o fgets (3) (para que la línea esté en un búfer), luego analizar esa línea. Podría usar sscanf (3) , quizás con su especificador %n , o podría analizar esa línea más manualmente con, por ejemplo, strtol (3) (que establece el puntero final).

Así que algo como:

 int endpos= -1; char linbuf[32]; memset(linbuf, 0, sizeof(linbuf)); if (!fgets(linbuf, sizeof(linbuf)) exit(EXIT_FAILURE); if (sscanf(linbuf, "%O2d:%02d%n", &hour, &minute, &endpos)<2) exit(EXIT_FAILURE); if (endpos!=6) exit(EXIT_FAILURE); if (hour<0 || minute<0 || hour>=24 || minute>=60) exit(EXIT_FAILURE); 

Por supuesto que reemplazaría la exit(EXIT_FAILURE); Con un rechazo más fácil de usar.

Por cierto, debe especificar si 1:2 es una entrada aceptable o si necesita 01:02 . ¿Y aceptarías una línea vacía como representación del mediodía?