El juego del ahorcado!

Iniciado por kuhi, 24 Abril 2017, 21:34 PM

0 Miembros y 2 Visitantes están viendo este tema.

kuhi

Hola, estoy trabajando en hacer el juego del ahorcado, me lo piden como trabajo de final de curso de la introducción a la programación en C.

La idea es tener listas con palabras de cierta longitud (de letras), en este caso son 5 y 6 palabras de longitud.
Lo que quiero es que el usuario me diga con cuantas letras quiere jugar, y entonces el programa seleccione aleatoriamente una palabra.
Una vez se seleccione la palabra seguiría el juego (aquí he usado el "canario" printf para comprobar que realiza las acciones que yo quiero).

Bien, el problema que me da primero es de un overflow del array en su definición.
Luego ejecuta el programa con normalidad pero no saca ningún printf. Se queda pillado y me salta un dejó de funcionar.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
char palabras5[100][5]={'CASCO','ZASKO','HOLAS','FAJOS'};
char palabras6[100][6]={'FAMAZO','FAROLA','FASETA','FAJOTE'};
int choice;

printf("Cuantas letras quieres usar?\n");
scanf("%i",choice);

if(choice==5)
{
srand(time(NULL));
{
int rand_num=rand()%6;
printf("%s\r\n",palabras5[rand_num]);
}
}
if(choice==6)
{
srand(time(NULL));
{
int rand_num=rand()%6;
printf("%s\r\n",palabras6[rand_num]);
}
}
}


Por favor, quiero aprender así que agradecería mucho que no me deis mas información de la necesaria, ya que quiero hacer el trabajo yo y solo consultar dudas puntuales. Darme más información de la que necesito sería contraproducente ya que no quiero que me hagan mi trabajo.

MUCHAS GRACIAS!!!!
El conocimiento no ocupa lugar, somos libres de saber cuánto queramos...

MAFUS

#1
Vale, en otros lenguajes puede funcionar pero en C las cadenas no se declaran de esa forma. Repasa cadenas y caracteres sueltos.

CalgaryCorpus

Los string literales usan doble comilla, e internamente usan 1 caracter adicional para guardar el final del string. Entonces lo que se ve asi  "hola" tiene en realidad 5 caracteres, no 4.
Aqui mi perfil en LinkedIn, invitame un cafe aqui

kuhi

#3
Hola, gracias otra vez @MAFUS :)

No encuentro el temario en mi libro de la universidad, le he escrito al profesor que me lo pase pero hasta el viernes no está (sólo trabaja Lunes y Viernes).
Lo digo porqué he buscado la información por google, según lo que he entendido, he modificado el código y el resultado es el siguiente:

int main()
{
char palabras5[100][5]={{"CASCO"},
{"ZASKO"},
{"HOLAS"},
{"FAJOS"}};
char palabras6[100][6]={{"FAMAZO"},
{"FAROLA"},
{"FASETA"},
{"FAJOTE"}};
int choice;

printf("Cuantas letras quieres usar?\n");
scanf("%i",choice);

if(choice==5)
{
srand(time(NULL));
{
int rand_num=rand()%6;
printf("%s\r\n",palabras5[rand_num]);
}
}
if(choice==6)
{
srand(time(NULL));
{
int rand_num=rand()%6;
printf("%s\r\n",palabras6[rand_num]);
}
}
}



Sigo teniendo el mismo error, introduzco las letras que quiero que tenga la palabra y se queda pillado el programa y pone dejó de funcionar. Por lo menos ahora no me da errores el compilador.

Debería usar 1 letra por cada espacio del array? Es decir: array[1][1] puede contener una cadena de caracteres o solo puede contener 1 letra?
Por lo que debería poner por ejemplo para la palabra casa:
array[100][0]=c
array[100][1]=a
array[100][2]=s
array[100][3]=a
array[100][4]=\0
Puede ser? Yo tenía entendido que de la forma que está puesta en el código ya se almacena así la cadena. Si no es así, debería usar un bucle para almacenar la palabra?

@CalgaryCorpus yo tengo entendido que los arrays se cuentan desde 0. Es decir:

cadena[4] contiene 5 posiciones:[0][1][2][3][4]
Del 0 al 3 va la palabra, en 4 es donde quedará el \0.

Si no es así corregidme por favor.

Muchas gracias a todos, de verdad <3
El conocimiento no ocupa lugar, somos libres de saber cuánto queramos...

MAFUS

Entrecomillando una cadena has dado un paso pero sigues teniendo un fallo.
Un poco de teoría: Los lenguajes de programación, al menos antes de la era de la programación orientada a objetos, tenían el problema de saber dónde termina una cadena de texto. Nosotros entendemos las palabras, pero la máquina no; para ella son sólo una secuencia de números en una sección de su memoria lineal. Pero ¿dónde termina?
Para resolver el problema los diseñadores pensaron en dos soluciones totalmente diferentes pero totalmente funcionales:
1. El tamaño de la cadena lo marcaba el primer byte de ésta. Como pro no se necesitaba calcular el tamaño pues ya lo daba la cadena misma; por contra una cadena no podía superar los 255 caracteres.
2. Marcar la cadena con un carácter especial que no será usado en otra situación. Como pro una cadena puede ser tan larga como el programador necesita; por contra el tamaño debe ser calculado programáticamente, hay un carácter que no puede ser usado en los textos y el auténtico tamaño del array de caracteres es un byte más largo a lo que el programador escribe, por ese mismo carácter.

C usa la segunda opción.
Cuando tu escribes una cadena de esta forma
"HOLA"lo que C hace por debajo es{'H', 'O', 'L', 'A', '\0}es decir, prepara un array con las letras que le has dado entrecomilladas y agrega el carácter nulo, que vale 0 (cero) en decimal, para marcar el final de la cadena. Esa es la base de todas las funciones que trabajan con cadenas.

Por tanto cuándo defines un array para alojar una cadena y debes darle las dimensiones a mano piensa que debes sobredimensionar a 1 elemento más que el número de letras tiene la cadena.

Por tanto debes redimensionar tus arrays de palabras para poder alojar el carácter nulo.

kuhi

#5
@MAFUS Hola MAFUS! Muchas gracias de nuevo, al final te voy a tener que pagar a ti el sueldo de mi profesor 😂😂😂
Entonces cuando pongo por ejemplo: array[4]=casa (escribo desde el móvil no me currare mucho las sintaxis en esta respuesta) el array es de 4 posiciones y no incluye el \0?
Yo pensaba que al poner como en el ejemplo array[4] se contaba desde 0 hasta 4, por lo que estoy indicando 4 posiciones pero ya va incluido el \0, lo que en realidad son 5 posiciones: 0,1,2,3,4
en la posición 4 iría el \0
Entonces tengo que dejarlo así?: {"ZASKO\0"}, y dejo igual la longitud [100][5]?
Muchas gracias <3
PD: hay alguna forma de dar honor o reputación o algo? Me gustaría devolverte la ayuda que me das!
El conocimiento no ocupa lugar, somos libres de saber cuánto queramos...

MAFUS

Al entrecomillar una cadena el compilador ya pone automáticamente el caracter nulo pero deberás tenerlo en cuenta al dimensionar un array manualmente.

Sobre dimensionar los arrays.
Cuando le das un tamaño estás indicando el número máximo de elementos que va a contener pero  como la numeración del índice empieza en el 0  el índice sulerior será siempre el número usado para dimensionar menos 1.

Por ejemplo
miarray [4]

Los elementos serán:
#1: miarray[0]
#2: miarray[1]
#3: miarray[2]
#4: miarray[3]

kuhi

Cita de: MAFUS en 26 Abril 2017, 11:16 AM
Al entrecomillar una cadena el compilador ya pone automáticamente el caracter nulo pero deberás tenerlo en cuenta al dimensionar un array manualmente.

Sobre dimensionar los arrays.
Cuando le das un tamaño estás indicando el número máximo de elementos que va a contener pero  como la numeración del índice empieza en el 0  el índice sulerior será siempre el número usado para dimensionar menos 1.

Por ejemplo
miarray [4]

Los elementos serán:
#1: miarray[0]
#2: miarray[1]
#3: miarray[2]
#4: miarray[3]
Pero entonces no entiendo que hago mal, si ya se pone automáticamente el \0, no entiendo que está mal en el código... espacio si que tiene el array para las letras y para el \0...


Enviado desde mi iPhone utilizando Tapatalk
El conocimiento no ocupa lugar, somos libres de saber cuánto queramos...

MAFUS

Lo escribo desde el móvil así que voy a simplificar.
Tu dices:
char palabras[5] = "CASCO"
Ahora como está entrecomillado hay que pensar hay el carácter nulo.
Así que tu array queda
#1: palabras[0] = 'C'
#2: palabras[1] = 'A'
...
#5: palabras[4] = 'O'

Y fuera de los límites de array está el caracter nulo.

Esto es peligroso porqué el programa sí copia dicho caracter nulo pero no tiene un espacio reservado. Eso significa que otra vatiable que tenga asignada esa zona de memoria te sobreescribirá ese caracter nulo y si ese es un valor distinto a 0 las funciones encargadas de manejar cadenas no encontrarán el final de esta donde tu lo esperas. Que es lo que te pasa. Así como lo tienes una cadena machaca el caracter nulo de la anterior por tanto printf escribe toda la ristra de palabras que hay en el array.

kuhi

Ahora lo entiendo, debería poner char palabras[6] = "CASCO" para que el 6 este reservado para el nulo entonces... cuando llegue a casa lo pruebo! @MAFUS muchísimas gracias!!! <3 se agradece que haya gente así ☺️


Enviado desde mi iPhone utilizando Tapatalk
El conocimiento no ocupa lugar, somos libres de saber cuánto queramos...