Issues with do/while loop ask question too many times - c

I have a problem with my code:
When I write any input different from 1,2,3,4 the output is
Inserire il numero dei giocatori
inserire un numero valido
Inserire il numero dei giocatori
inserire un numero valido
Inserire il numero dei giocatori
How can I fix it?
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
int controll_num(){
int controll=0;
int players;
char c;
do{
printf("Inserire il numero dei giocatori \n");
c=getc(stdin);
switch (c){
case 49:
players=1;
controll=1;
break;
case 50:
players=2;
controll=1;
break;
case 51:
players = 3;
controll=1;
break;
case 52:
players = 4;
controll=1;
break;
default:
printf("inserire un numero valido\n");
}
}while(controll==0);
return players;
}
int main(){
controll_num();
return 0;
}

Instead of getc use scanf as for example
scanf( " %c", &c );
Pay attention to the leading space in the format string. It allows to skip white space characters as for example the new line character '\n' that is placed in the input buffer by pressing the Enter key.
As for getc then it can read white space characters.
Also instead of using magic numbers like 49 as case labels
case 49:
use characters like
case '1':
This will make your code more readable.

You need to check if the value is digit and your switch case is not needed at all.
int controll_num(void){
int players;
char c;
while(1)
{
printf("Inserire il numero dei giocatori \n");
c=getc(stdin);
if(isdigit((unsigned char)c))
{
players = c - '0';
break;
}
printf("inserire un numero valido\n");
};
return players;
}
int main(void)
{
printf("Number of players %d\n", controll_num());
}
https://godbolt.org/z/sf7nxE7cx

Related

incorrect output data after the second index

So im doing this homework for my programming class, but the data output doesnt match with the theoretical data output that it shoud be printing and it gives me a big number.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void menu(int *);
void CalculoVentas(float ventas[50][7], float ventasXproductos[50], int);
void PromedioDiario(float promedioXdia[7], float ventas[50][7], int);
int main()
{
char ciclos;
int sel, cont = 0, i = 0;
float ventas[50][7], ventasXproductos[50], promedioXdia[7];
bool lectura = false;
while(sel != 5)
{
menu(&sel);
system("cls");
switch(sel)
{
case 1:
printf("Hay Productos?: S/N ");
fflush(stdin);
scanf("%c", &ciclos);
while(ciclos == 's' || ciclos == 'S' && cont < 50)
{
for(i=0;i<7;i++)
{
do
{
printf("Teclea los ingresos generados por el producto %d el dia %d: ", cont+1, i+1);
scanf("%f", &ventas[cont][i]);
}while(ventas[cont][i] < 0);
printf("\n\n");
}
cont++;
system("cls");
printf("Hay Productos?: S/N ");
fflush(stdin);
scanf("%c", &ciclos);
lectura = true;
}
break;
case 2:
if(lectura == false)
printf("Primero ingresa los datos del producto!!!\n");
else
CalculoVentas(ventas, ventasXproductos, cont);
break;
case 3:
if(lectura == false)
printf("Primero ingresa los datos del producto!!!\n");
else
PromedioDiario(promedioXdia, ventas, cont);
break;
case 4:
if(lectura == false)
printf("Primero ingresa los datos del producto!!!\n");
else
printf("%35s\n", "Total de ventas");
for(i=0;i<cont;i++)
printf("%d %.2f\n", i+1, ventasXproductos[i]);
printf("\n\n\n\n");
printf("%35s\n", "Promedio de ventas por dia");
for(i=0;i<7;i++)
printf("Dia %d: %.2f\n", i+1, promedioXdia[i]);
printf("\n\n\n\n");
break;
}
}
}
void menu(int *seleccion)
{
printf("%20s\n%s\n%s\n%s\n%s\n%s\n", "Menu de opciones", "1.-lectura de datos", "2.-calculo de ventas por producto", "3.-promedio de ventas de cada dia", "4.-imprimir resultados", "5.-salir");
do{
printf("Seleccione una opcion: ");
scanf("%d", &*seleccion);
}while(*seleccion <= 0 || *seleccion > 5);
}
void CalculoVentas(float ventas[50][7], float ventasXproducto[50], int cont)
{
//realizar el calculo de ventas por productos, nada más es la suma de las ventas de todos los dias por producto
int i,j;
for (i = 0 ; i<cont ; i++)
for (j = 0 ; j < 7 ; j++)
ventasXproducto[i] = ventasXproducto[i] + ventas[i][j];
}
void PromedioDiario(float promedioXdia[7], float ventas[50][7], int cont)
{
int i,j;
for(i=0;i<7;i++)
{
for(j=0;j<cont; j++)
promedioXdia[i] = promedioXdia[i] + ventas[j][i];
promedioXdia[i] = promedioXdia[i]/cont;
}
}
the output is something like this, I try to type simple data so i can know easly if its wrong
Total de ventas
1 70.00
2 5103881324019006800000000000000000.00
3 210.00
4 280.00
Promedio de ventas por dia
Dia 1: 25.00
Dia 2: 25.00
Dia 3: 25.00
Dia 4: 1291386862541487300000000000000000.00
Dia 5: 25.00
Dia 6: -1.#R
Dia 7: 25.00
when i was trying to get help someone told me that i might be not initializing correctly the variables but i couldnt find any issue with that
When the program begins, sel is uninitialized and contains a garbage value. This garbage value is used in the while condition on its first iteration
while(sel != 5)
and as such invokes Undefined Behaviour.
You must restructure your loop to not read this uninitialized value, or simply initialize sel (to something other than 5).
Similarly, the contents of ventas, ventasXproductos, and promedioXdia are all uninitialized as well.
This means statements such as
ventasXproducto[i] = ventasXproducto[i] + ventas[i][j];
/* ... and ... */
promedioXdia[i] = promedioXdia[i]/cont;
will be operating with garbage values to start.
You can fix this by initializing your arrays:
float ventas[50][7] = { 0 }, ventasXproductos[50] = { 0 }, promedioXdia[7] = { 0 };
You should not ignore the return value of scanf. You should always check that its return value is the expected number of successful conversions, otherwise you will find yourself operating on incomplete data.
/* An example */
if (2 != scanf("%d%d", &num1, &num2)) {
/* handle failure */
}
(Better yet: avoid using scanf, and use fgets and sscanf to read and parse lines of input.)
You should clarify this expression by adding more parenthesis, otherwise you will run into issues with operator precedence:
while ((ciclos == 's' || ciclos == 'S') && cont < 50)
case 4 of the switch has misleading indentation. Only the first statement with the call to printf is contained within the else block. It is read as:
if(lectura == false)
printf("Primero ingresa los datos del producto!!!\n");
else
printf("%35s\n", "Total de ventas");
for(i=0;i<cont;i++)
printf("%d %.2f\n", i+1, ventasXproductos[i]);
/* ... */
Your lectura flag will not protect you from operating on incomplete data if this is selected. Enclose the code with curly braces:
case 4:
if(lectura == false) {
printf("Primero ingresa los datos del producto!!!\n");
} else {
printf("%35s\n", "Total de ventas");
for(i=0;i<cont;i++)
printf("%d %.2f\n", i+1, ventasXproductos[i]);
/* ... */
}
break;
Note that in &*seleccion, & and * balance each other out. This resolves to the same value as just writing seleccion would.
Note that fflush(stdin); is also (technically) Undefined Behaviour, and should not be relied upon.

Problem in C - scanf() skipping input (It is not a problem with the buffer)

Basically, I have to make a currency prices conversion with a menu (Im in first year) but the second scanf that executes when you select the 0) is totally skipped; after that the program prints the menu again around 5 times and then it lets you select an option again. This is the only part that is not working, the rest is fine.
You may think that the problem is that the buffer has a newline stored from the previous scanf, but that is not the case as I am making sure to clean it. Also, don't mind the strings, they are just in spanish.
Thanks for your time!
'''
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
char e = ' ';
float le = 1.1, de = 0.9, din = 1, c1, c2;
while (e != 's') {
puts("\n ================================================================");
puts(" CONVERSION DE DIVISAS");
puts(" ================================================================");
puts("0) Introducir valores de cotizacion de monedas");
puts("a) Convertir euros a dolares y libras");
puts("b) Convertir dolares a euros y libras");
puts("c) Convertir libras a euros y dolares");
puts("s) Salir");
printf("\nIntroduzca su eleccion: ");
scanf(" %c", &e);
e = tolower(e);
fflush(stdin);
switch (e) {
case '0':
printf("\nIntroduzca cuantas libras son un euro: ");
scanf(" %9.4f ", &le);
fflush(stdin);
printf("Introduzca cuantos dolares son un euro: ");
scanf(" %9.4f ", &de);
fflush(stdin);
break;
default:
printf("\nOpcion incorrecta");
break;
}
}
return 0;
}
'''

it shows output more than 4 times

I was trying to make a program in C that basically asks the user some information about the people they live with. The code is in Spanish, but I will show you the problem.
/*Miembros de la familia*/
#include<stdio.h>
#include<stdbool.h>
#define TRUE 1
#define FALSE 0
int main(){
int personas,i,varones=0,hembras=0,opcion;
bool mayoredad=false;
printf("Indique cuantas personas viven en su casa:\n");
scanf("%i", &personas);
struct nombre{
char primer[30];
char segundo[30];
char apellido[30];
}minombre;
struct fecha{
int dia;
int mes;
int anio;
}nacimiento, actual;
printf("\nIngrese la fecha actual:\n");
scanf("%i %i %i", &actual.dia, &actual.mes, &actual.anio);
struct familia{
struct nombre minombre;
char cedula[10];
struct fecha nacimiento;
char genero;
int edad;
}familia[personas];
for(i=0;i<personas;i++){
printf("\nIndique su primer nombre, segundo nombre y apellido:\n");
scanf("%s %s %s", &familia[i].minombre.primer, &familia[i].minombre.segundo, &familia[i].minombre.apellido);
printf("\nPor favor escriba su numero de cedula:\n");
scanf("%s", &familia[i].cedula);
do{
printf("\nIngrese la fecha de su nacimiento: (DD)(MM)(AAAA):\n");
scanf("%i %i %i", &familia[i].nacimiento.dia, &familia[i].nacimiento.mes, &familia[i].nacimiento.anio);
if(familia[i].nacimiento.anio>actual.anio){
printf("Dato invalido, por favor intente nuevamente.");
}
}while(nacimiento.anio>actual.anio);
familia[i].edad=actual.anio-familia[i].nacimiento.anio;
if(familia[i].nacimiento.mes>=actual.mes && familia[i].nacimiento.dia>actual.dia){
familia[i].edad--;
}
if(familia[i].edad>=18){
mayoredad=true;
}
do{
printf("Indique su genero: (f) o (m):");
scanf(" %c", &familia[i].genero);
if(familia[i].genero=='f'){
hembras++;
}else if(familia[i].genero=='m'){
varones++;
}
}while(familia[i].genero!='f' && familia[i].genero!='m');
}
do{
printf("Registro concluido. Desea ver las estadisticas? 1(si) 2(no)");
scanf("%i", &opcion);
if(opcion!=1 && opcion!=2){
printf("DATO INVALIDO, INTENTE NUEVAMENTE");
}else if(opcion==1){
for(i=0;i<personas;i++){
printf("Nombre: %s %s %s\n", familia[i].minombre.primer, familia[i].minombre.segundo, familia[i].minombre.apellido);
printf("Cedula:%s\n", familia[i].cedula);
printf("Edad:%i\n", familia[i].edad);
printf("Mayor de edad:\n");
switch(mayoredad){
case true:printf("Si");break;
case false:printf("No");
}
}
printf("Cantidad de personas en el hogar: %i\n", personas);
printf("Varones: %i Hembras: %i\n", varones, hembras);
}
}while(opcion>=2 && opcion<0);
printf("Presione una tecla para salir.");
getchar();
return 0;
}
In the last do-while loop that requests the person's gender (familia[i].genero)
It is supposed to ask just once, but in the last iteration of the for loop, it displays the same question four times:enter image description here
How can I fix this?
The format specifier %i will treat input whose suffix is 0 (and not 0x nor 0X) as octal number.
Therefore, 09 in your input is invalid as octal number and it will leave 9 in the stream.
This 9 is read to familia[i].nacimiento.anio by the next specifier.
Then, following scanf(" %c", &familia[i].genero); will read 2003 from the input and this will lead to the 4 extra asking.
To fix this, use %d specifier to read integers. %d spcifier will treat input as decimal number regardless of the suffix.

My program starts the loop before scan is done

I have a little problem, my program works well until it arrives to the final step, a scanf which asks for continuation of the loop. The problem is that this scan isn't working, but the following system("cls") works. Looks like javascript when async.
Here is the code.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char elegir_dificultad;
int dificil = 1;
printf("Desea que se le indique si el numero es menor o mayor? \n s/n \n");
scanf("%c",&elegir_dificultad);
if(elegir_dificultad == 's'){
dificil = 0;
}
while(1){
int aleatorio, cont, introducido;
cont = 1;
aleatorio = rand()%101;
printf("%d",aleatorio);
int fallo = 1;
while(fallo){
printf("Introduce el numero, intento numero %d \n", cont);
scanf("%d",&introducido);
if(introducido == aleatorio){
fallo = 0;
}
if(cont == 10){
break;
}
if(!dificil){
if(introducido < aleatorio){
printf("El numero introducido es menor que el aleatorio \n");
}
if(introducido > aleatorio){
printf("El numero introducido es mayor que el aleatorio \n");
}
}
if(fallo){
cont++;
}
}
char continuar;
if(fallo){
printf("Has perdido... el numero era %d \n Quieres repetirlo? s/n \n",aleatorio);
scanf("%c",&continuar);
if(continuar=='n'){
break;
}
system("cls");
}else{
printf("°Has ganado! el numero era %d \n Quieres repetirlo? s/n \n",aleatorio);
scanf("%c",&continuar);
if(continuar=='n'){
break;
}
system("cls");
}
}
system("PAUSE");
return 0;
}
This problem is because of \n character left behind by the previous scanf. Place a space before each %c specifier in scanf to eat up \n. .
scanf(" %c", &introducido);
...
scanf(" %c",&continuar);

Newbie help (in C) details inside

first of all I am a complete programming newbie, so I am sorry if there is something that does this really easily and I don't know of it, it is in no way my intention to be dumb.
[Also, sorry the programs are in spanish but I don't think the printf's really affect the whole logic thing.
Anyhow:
I made a program that evaluated a number and then got it as near as possible to the closest multiple of three, then I did the same for 5:
//cambia un numero al multiplo de 3 mas cercano
#include <stdio.h>
#include <stdlib.h>
int main(){
int a;
printf("Escribe el numero que deseas redondear: ");
scanf(" %d", &a);
while(a%3 != 0){
--a;
if (a%3 == 0)
break;
a++;
a++;
}
printf("El multiplo de 3 mas cercano es: %d\n", a);
}
//cambia un numero al multiplo de 5 mas cercano
#include <stdio.h>
#include <stdlib.h>
int main(){
int a;
printf("Escribe el numero que deseas redondear: ");
scanf(" %d", &a);
while(a%5 != 0){
--a;
if (a%5 == 0)
break;
--a;
if (a%5 == 0)
break;
a++;
a++;
a++;
if (a%5 == 0)
break;
a++;
if (a%5 == 0)
break;
if (a%5 == 0)
break;
a++;
}
printf("El multiplo de 5 mas cercano es: %d\n", a);
}
Now I want to write a program that does the same, but takes the number of the multiple from the user. I wrote this:
//cambia un numero al multiplo de n (input) más cercano
#include <stdio.h>
#include <stdlib.h>
int main(){
int a, n;
printf("Escribe el numero que deseas redondear: ");
scanf(" %d", &a);
printf("Escribe el numero base para redondear: ");
scanf(" %d", &n);
for(a, n; a%n != 0; a++);
printf("El multiplo de %d mas cercano (A la derecha) es: %d\n",n, a);
}
But of course this only makes it as near as possible from the right, and I don't know how (With n cases) to make it go to the closest number. The idea is this:
5 6 7 8 9 10
If we want it to go to the closest multiple of 5 and the input is 6-7 then it goes to 5, because that is the closest multiple of 5. If the input is 8-9 then it sends it to 10. The idea is always getting to the "closest" number. But I don't really see how to do it. Any help would be greatly appreciated.
If you could alternatively post the help in Java that would be more than sufficient as well. Since I know a bit java as well.
Thanks!
The classic way to do this is divide, round, multiply.

Resources