2

tengo que hacer un programa en el cual he alojado 10 grupos de Heavy Metal, y despues pedir al usuario que introduzca 10 grupos, y en funcion de los aciertos que tenga el programa sacara una cosa u otra, no consigo dar con el problema, a ver si me pueden echar una mano, saludos!

#include <iostream>
#include <string>

using namespace std;

void main() {

    string gruposPredeterminados[10] = { "Slayer", "Slipknot", "Iron Maiden", "Metallica", "Judas Priest", "AC/DC", "Black Sabbath", "Kiss", "Megadeth", "Pantera" };
    string gruposUsuario[10];
    int aciertos = 0;

    cout << "Ingresa 10 grupos de Heavy Metal: \n";

    for (int i = 0; i < 10; i++)
    {
        getline(cin, gruposUsuario[i]);

        if (gruposUsuario[i] == gruposPredeterminados[i])
        {
            aciertos++;
        }
    }


    switch (aciertos)
    {
    case 10: cout << "Amo del metal!";
        break;
    case 9: cout << "True metal";
        break;
    case 8: cout << "True metal";
        break;
    case 7: cout << "True metal";
        break;
    case 6: cout << "Metalero";
        break;
    case 5: cout << "Metalero";
        break;
    case 4: cout << "Metalero noob";
        break;
    case 3: cout << "Metalero noob";
        break;
    case 2: cout << "Meta que?";
        break;
    case 1: cout << "Meta que?";
    default: cout << "Tu ets mes de Pacha, oi?";
        break;
    }

    system("pause");

}
Trauma
  • 25,297
  • 4
  • 37
  • 60
  • ¿ Podrías explicar/detallar el problema exacto ? ¿ De compilación, de funcionamiento ? Esperar que alguien, para poder ayudarte, tenga que compilar y ejecutar tu programa ... ¡ Ayudanos a ayudarte ! – Trauma Jan 28 '19 at 17:08
  • Muchas gracias a todos! En mi cabeza sabia que estaba mal el tema de comparar el valor X[i] con Y[i], ya que como bien habeis dicho solo estaria bien si el usuario lo escribe en el mismo orden, de todas formas, he visto que habeis utilizado dos formas, con compare y utilizando dos for, cual seria la mas eficaz? – Dan Cezanne Galavan Jan 28 '19 at 17:59
  • @DanCezanneGalavan La que usa el `compare` no soluciona tu problema, a no ser que uses el `compare` Y dos `for`. – PaperBirdMaster Jan 29 '19 at 06:48

2 Answers2

4

Estás sumando aciertos sólo si el valor de la posición i de gruposUsuario coincide el valor en la misma posición en gruposPredeterminados. Esto significa que aunque el usuario acierte todos los grupos, no se le dará por bueno a no ser que los acierte en el mismo orden.

Tienes que comprobar si un valor está en cualquiera de las posiciones, no en una sola:

for (int entrada = 0; entrada < 10; ++entrada)
{
    getline(cin, gruposUsuario[i]);

    for (int verificacion = 0; verificacion < 10; ++verificacion)
    {
        if (gruposUsuario[entrada] == gruposPredeterminados[verificacion])
        {
            ++aciertos;
        }
    }
}

Pero este código es horrible, además exige que el usuario acierte incluso las mayúsculas/minúsculas (No sería lo mismo "AC/DC" que "Ac/Dc").

Propuesta.

Separa la obtención de datos...

cout << "Ingresa 10 grupos de Heavy Metal: \n";

for (auto &grupo : gruposUsuario)
{
    getline(cin, grupo);
}

... de la verificación:

for (const auto &grupo : gruposUsuario)
{
    aciertos += count(begin(gruposPredeterminados), end(gruposPredeterminados), grupo) ? 1 : 0;
}

También puedes simplificar tu switch:

switch (aciertos)
{
case 10:
    cout << "Amo del metal!";
    break;
case 9:
case 8:
case 7:
    cout << "True metal";
    break;
case 6:
case 5:
    cout << "Metalero";
    break;
case 4:
case 3:
    cout << "Metalero noob";
    break;
case 2:
    cout << "Meta que?";
    break;
case 1:
    cout << "Meta que?";
default:
    cout << "Tu ets mes de Pacha, oi?";
    break;
}

Puedes ver mi propuesta funcionando en Wandbox. He hecho cambios adicionales a tu código:

  • Uso el for de rango por claridad.
  • Uso la función std::count para ver si el elemento existe1 en la formación2 de destino.
  • Las funciones libres de obtención de rango std::begin y std::end.

Otras cosas a tener en cuenta.

  • Este es StackOverflow en Español, debiste poner algún grupo que cante en nuestro idioma ò_ó.
  • El algoritmo, tal y como está, contará como 10 aciertos si pones 10 veces un valor que existe en la formación de referencia (pero puedes solucionando dando la vuelta a la comprobación: busca en la entrada de usuario los valores predeterminados).
  • No es necesaria la cláusula using namespace std; pues tan sólo es una ayuda a la escritura; no pasa nada por usarla pero si la usas procura que sea en el ámbito más pequeño posible; lee este hilo para saber más del tema.
  • Procura favorecer el pre-decremento (o incremento) frente al post-decremento (o incremento), lee este artículo para saber más del tema.
  • La función main debe devolver int (no void), lee este hilo para saber por qué.

  1. Es un poco más sencillo que usar std::find, pero menos eficiente.
  2. También conocidas como arreglo o en inglés array.
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
  • Gracias compi! La mayoria de ajustes que dices son malas practicas de clase...hemos empezado hace nada y desde el primer dia nos han dado estas pautas, y si te buscas la vida e intentas usar codigo que no este en el temario tristemente te lo echan hacia atras...de todas formas no dudes en que vaya a echarle un ojo a lo que me has dicho, muchas gracias! – Dan Cezanne Galavan Jan 28 '19 at 18:02
  • 1
    @DanCezanneGalavan eso que me explicas me entristece, me dan ganas de charlar con quien os da esas pautas para despotricar un rato. – PaperBirdMaster Jan 28 '19 at 19:35
0

Necesitas usar la función compare para comparar las strings de lo contrario puede darte problemas en muchos casos.

He modificado también los case del switch para evitar la repetición de código.

#include <iostream>
#include <string>

using namespace std;

int main() {

    string gruposPredeterminados[10] = { "Slayer", "Slipknot", "Iron Maiden", "Metallica", "Judas Priest", "AC/DC", "Black Sabbath", "Kiss", "Megadeth", "Pantera" };
    string gruposUsuario[10];
    int aciertos = 0;

    cout << "Ingresa 10 grupos de Heavy Metal: \n";

    for (int i = 0; i < 10; i++)
    {
        getline(cin, gruposUsuario[i]);

        if (gruposUsuario[i].compare(gruposPredeterminados[i]) == 0)
        {
            aciertos++;
        }
    }


    switch (aciertos)
    {
    case 10: cout << "Amo del metal!";
        break;
    case 9:
    case 8:
    case 7:
        cout << "True metal";
        break;
    case 6:
    case 5:
        cout << "Metalero";
        break;
    case 4: 
    case 3: 
        cout << "Metalero noob";
        break;
    case 2: cout << "Meta que?";
        break;
    case 1: cout << "Meta que?";
    default: cout << "Tu ets mes de Pacha, oi?";
        break;
    }

    system("pause");
    return 0;
}
solamente
  • 1,560
  • 7
  • 14
  • ¿ Que tiene de malo usar `==` para comparar `std::string( )` ? ¿ Seguro que el problema del usuario es ese ? – Trauma Jan 28 '19 at 17:23
  • No es ese el error pero creo que es una practica mucho mejor ya que ofrece muchas más posibilidades tanto para comprar strings cual es mayor y poder realizar posteriores ordenaciones. Igual que el caso de modificación de los case entendí por la vaga explicación que ofreció que necesitaba una optimización de código. @Trauma – solamente Jan 28 '19 at 17:33
  • @solamente está bien que menciones (aquello que crees que son) buenas prácticas, pero no respondes la pregunta. – PaperBirdMaster Jan 28 '19 at 17:52