@sebach ya identificó la cuestión, que tenía que ver con el uso del método eof, y la forma de “leer hasta que se termine el archivo” que recomendó es la más práctica y la que recomendamos para todo.
Dicho esto, solo para ampliar, comento “por qué eof no andaba”. eof solo se prende cuando ya se llegó al fin de archivo. Ahora bien, si lo único que falta leer es por ejemplo “el enter del final” o cualquier cosa de ese estilo, no se llegó al eof todavía, y entonces va a dar false
. Pero para nosotros, “sí se llegó”, porque ya no hay nada útil que leer. Esto lo tenés resuelto en tu código de una manera “adhoc”, que no debería ser necesaria, que es poner ese valor especial -1, y de esta manera “procesar un caso extra fruta al final de todo”, con la esperanza de que todo salga bien y produzca el -1, y una vez afuera de calc()
, poner un if especial para saltear ese -1. Esto tiene dos desventajas: una es que “es feo” hacer todo este mecanismo artesanal: querríamos de una “saber si de verdad quedan cosas útiles por leer todavía, y ni procesar un caso más si no quedan”. Esto se hace de la forma que sugirió Seba. Pero el otro problema es que cuando calc()
se manda a calcular este caso extra, está usando los datos que surgen de usar cin pero sobre un archivo que ya se terminó. En ese caso, “no sabemos qué datos se leen”, y queda cualquier fruta. En otras palabras, el código como está es inválido porque se manda a procesar ese caso extra del final, y ahí se podría leer cualquier cosa. En particular, algo que haga al programa fallar, o quizás hasta producir un número que no sea -1 y se muestre, dando WA. En casos chiquitos parece andar bien en mi compu con mi compilador, pero no hay nada que garantice que esto siga siendo así en casos grandes, en otras compus, con otros compiladores.
Por otro lado, cuando compilo tu código me da todos estos warnings:
g++ -D_GLIBCXX_DEBUG -std=c++11 -DACMTUYO -O2 -g -Wconversion -Wshadow -Wall -Wextra -o "testingSotoLalala" "testingSotoLalala.cpp" -lgmp -pthread
(in directory: /home/santo/Documents/C++)
testingSotoLalala.cpp: In constructor ‘Pos::Pos(int, int)’:
testingSotoLalala.cpp:7:20: warning: declaration of ‘y’ shadows a member of ‘Pos’ [-Wshadow]
Pos(int x, int y): x(x), y(y) {}
^
testingSotoLalala.cpp:6:7: note: shadowed declaration is here
int y;
^
testingSotoLalala.cpp:7:20: warning: declaration of ‘x’ shadows a member of ‘Pos’ [-Wshadow]
Pos(int x, int y): x(x), y(y) {}
^
testingSotoLalala.cpp:5:7: note: shadowed declaration is here
int x;
^
testingSotoLalala.cpp: In function ‘int calc()’:
testingSotoLalala.cpp:46:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if(curr.second == s.size()) {
^
Compilation finished successfully.
Quizás a vos no te salen porque no los tenés activados. Como ayudan a detectar muchos errores de programación que es muy bueno que el compilador avise antes que sufrir una hora buscando errores, recomiendo súper fuertemente activar los warnings. Acá se comentan las opciones del compilador para activarlas. ¡¡Cualquier duda sobre cómo hacerlo, consultar!!
En este caso las cosas que te marca no son bugs, pero cosas muy parecidas podrían serlo. “Silenciar” estas falsas alarmas es muy simple:
curr.second == s.size()
se transforma en
curr.second == int(s.size())
Siempre es buena idea pasar a entero con signo los .size(), por ejemplo si usaras .size()-1
sobre algo vacío sin el casteo, tendrías el programa funcionaría probablemente mal. Activando los warnings, el compilador avisa todos los lugares donde puede faltar uno de estos casteos.
El otro warning es en Pos
, que indica que los parámetros x
e y
“esconden” o “tapan” a las variables x e y el Pos mismo. Lo mejor es ponerles un nombre diferente para evitar eso, como por ejemplo newX
y newY
:
struct Pos {
int x;
int y;
Pos(int newX, int newY): x(newX), y(newY) {}
};
Esto me parece además que es mejor, porque el otro patrón de ponerles el mismo nombre tiene cierto peligro: si por ejemplo hacemos:
struct Pos {
int x;
int y;
Pos(int x, int t): x(x), y(y) {}
};
Que tiene un sencillo error de tipeo de poner una t
en lugar de una y
(que están al lado en el teclado Qwerty), esto compilaría, pero estaría mal (porque la y
se está inicializando consigo misma, en lugar de con el t
) así que el programa fallaría, y encontrar este bug probablemente sería difícil de ver, porque la lógica está perfecta pero es un error sutil en un caracter mal escrito. Compilando con los warnings activados, por en este caso avisaría dos cosas que hacen que descubramos esto rápido: Que el parámetro t
no se usa, y que la la variable y
se está inicializando consigo misma.
Moraleja: ACTIVAR LOS WARNINGS. Salvan vidas.