Problem when scanning a character and saving it in a structure

0

When I scan the sex and save it in the structure the functions CancionMasVotada and Premio print me wrong results, however if I remove the scanf of sex everything works perfectly.

The code is as follows:

#include <stdio.h>
#include <stdlib.h>
struct canciones {
    int codigo;
    char genero;
    int puntos;
    char nombre[100];
};
typedef struct canciones CANCIONES;
struct oyente {
    int cedula;
    int edad;
    char sexo;
    int eleg[3];
    int puntos;
};
typedef struct oyente OYENTE;
int i, j, k = 0, aux = 0, x;
OYENTE oyentes[3];
CANCIONES canciones[10];
void Menu();
void TomarDatosOyente();
void CancionMasVotada();
void PtsOyente();
void Premio();
int main () {
    Menu();
    TomarDatosOyente();
    CancionMasVotada();
    PtsOyente();
    Premio();
    return 0;
}
void Menu(){
  printf("\n\tEMISORA DE RADIO\n\n");
  printf("Digite el listado de canciones:\n");
  for (i = 0; i < 10; i++) {
    fflush(stdin);
    printf("Cancion #%d: ", i+1);
    gets(canciones[i].nombre);
    printf(" Genero <P-pop / R-rap / K-rock / T-Romantica> : ");
    scanf("%s", &canciones[i].genero);
  }
}
void TomarDatosOyente(){
  for (i = 0; i < 3; i++) {
    printf(" Oyente #%d \n", i+1);
    printf(" Cedula: ");
    scanf("%d", &oyentes[i].cedula);
    printf(" Edad: ");
    scanf("%d", &oyentes[i].edad);
    printf(" sexo: "); 
    scanf("%s", &oyentes[i].sexo); // aqui esta el problema
    printf(" Digite los datos de sus canciones favoritas\n");
    aux = 3;
    for (j = 0; j < 3; j++) {
      printf(" Cancion #%d\n", j+1);
      printf(" Codigo <1-10> : ");
      scanf("%d", &oyentes[i].eleg[j]);
      k = oyentes[i].eleg[j];
      canciones[k-1].codigo = k;
      canciones[k-1].puntos += aux;
      aux--;
    }
    system("pause");
    system("cls");
  }
}
void CancionMasVotada(){
  for (i = 0; i < 10; i++) {
    for (j = 0; j < 10; j++) {
      if (canciones[j].puntos < canciones[j+1].puntos) {
        aux = canciones[j].puntos;
        canciones[j].puntos = canciones[j+1].puntos;
        canciones[j+1].puntos = aux;

        k = canciones[j].codigo;
        canciones[j].codigo = canciones[j+1].codigo;
        canciones[j+1].codigo = k;
      }
    }
  }
  printf("--------------------------------\n--------------------------------\n");
printf("La cancion mas votada es %s con %d votos\n",      canciones[canciones[0].codigo - 1].nombre, canciones[0].puntos);
printf("La segunda cancion mas votada es %s con %d votos\n", canciones[canciones[1].codigo - 1].nombre, canciones[1].puntos);
  printf("--------------------------------\n--------------------------------\n");
}
void PtsOyente(){
  for (i = 0; i < 3; i++) {
  aux = 0;
    for (j = 0; j < 3; j++) {
  if (oyentes[i].eleg[j] == canciones[0].codigo) {
      oyentes[i].puntos += 30;
      aux++;
  }else if (oyentes[i].eleg[j] == canciones[1].codigo) {
      oyentes[i].puntos += 20;
    if (aux == 1) {
        oyentes[i].puntos += 10;
    }
  }
}
  }
}
void Premio(){
  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      if (oyentes[j].puntos < oyentes[j+1].puntos) {
        aux = oyentes[j].puntos;
        oyentes[j].puntos = oyentes[j+1].puntos;
        oyentes[j+1].puntos = aux;

        k = oyentes[j].cedula;
        oyentes[j].cedula = oyentes[j+1].cedula;
        oyentes[j+1].cedula = k;
      }
    }
  }

  for (i = 0; i < 3; i++) {
    printf("Oyente de cedula: %d\nPuntos: %d\n", oyentes[i].cedula, oyentes[i].puntos);
  }
      printf("El oyente de cedula %d ha ganado el premio con un total de %d puntos\n", oyentes[0].cedula, oyentes[0].puntos);
}

choosing first the songs 1,2 and 3 then the 4,1 and 6 and finally 7,8 and 2 should give this result

When I scan the sex and choose the same songs, it prints me this incorrect data, since I made the change from %s to %c as they had said to me below

Thanks

    
asked by Leonard 24.02.2018 в 17:14
source

2 answers

1

You are scanning a single character, use %c , %s is for a string of characters:

scanf("%c", &oyentes[i].sexo); 

As it says here

  

The conversion '% c' is the simplest: it matches a fixed number of   characters, always. The maximum width of the field indicates how many   read characters; If you do not specify the maximum, the default value   is 1. This conversion does not add a null character at the end of the text   What read. Nor does it omit the initial blank characters. Read with   precision the next n characters, and fails if you can not get them.

    
answered by 24.02.2018 в 18:03
0

Variables must not be global

Except for very few exceptions, and none is applicable to your case, the variables should not be global and the explanation is very simple:

  • Global variables can be used, without any control, from any part of the code. You can not assume that a global variable is going to have a certain value and, surely, you have to treat the variable at all times as if it were not initialized.
  • In multi-threaded environments, the problem worsens.
  • They have no scope (that is, their scope is the whole application) and it is easy for the variable to end up overlapping with a local variable ... which complicates reading and understanding the code.

It is preferable to have this:

void func()
{
  for( int i=0; i<10; i++ )
    // ...
}

To this:

int i;

void func()
{
  for( i=0; i<10; i++ )
    // ...
}

Eye with the ranges

Function with the prize of the day:

for (i = 0; i < 3; i++) {
  for (j = 0; j < 3; j++) {
    if (oyentes[j].puntos < oyentes[j+1].puntos) {
      aux = oyentes[j].puntos;
      oyentes[j].puntos = oyentes[j+1].puntos;
      oyentes[j+1].puntos = aux;

      k = oyentes[j].cedula;
      oyentes[j].cedula = oyentes[j+1].cedula;
      oyentes[j+1].cedula = k;
    }
  }
}

The first thing that squeaks of this function is that you use two loops ( i and j ) and yet then you only use one of the two indexes ( j ). Then you look more closely and you find this oyentes[j+1].puntos and, of course, you realize that if j=2 , then j+1=3 that is, you would be accessing a position that does not belong to the array ... badly come on.

That sorting algorithm is not well implemented. You have to use the two indexes:

for (int i = 0; i < 3; i++) {
  for (int j = i+1; j < 3; j++) {
    if (oyentes[i].puntos < oyentes[j].puntos) {
      aux = oyentes[i].puntos;
      oyentes[i].puntos = oyentes[j].puntos;
      oyentes[j].puntos = aux;

      k = oyentes[i].cedula;
      oyentes[i].cedula = oyentes[j].cedula;
      oyentes[j].cedula = k;
    }
  }
}

Although, already put, and perhaps you do not know it, the structures can be copied with the assignment operator, with which the final code is still more readable:

for (int i = 0; i < 3; i++) {
  for (int j = i+1; j < 3; j++) {
    if (oyentes[i].puntos < oyentes[j].puntos) {
      OYENTE aux = oyentes[i];
      oyentes[i] = oyentes[j];
      oyentes[j] = aux;
    }
  }
}
    
answered by 28.02.2018 в 07:46