elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado:


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Petición de ayuda para un problema bastante básico de programación en c++
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Petición de ayuda para un problema bastante básico de programación en c++  (Leído 3,561 veces)
JoaquinVT312

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Petición de ayuda para un problema bastante básico de programación en c++
« en: 9 Mayo 2021, 11:55 am »

Soy nuevo programando, y tengo que entregar un ejercicio y estoy bastante perdido, debo hacer que el programa me diga si una receta de comida es vegetariana o no, viendo si alguno de los ingredientes que contiene es animal, imprimiendo un 1 si lo es, un 0 si no lo es o un -1 si hay algún ingrediente de la receta que no este en la base de datos que da el enunciado.
Llevo algo hecho pero estoy muy perdido puesto que soy nuevo y no sé aún como funcionan este tipo de programas. Agradecería algo de ayuda, por favor. Adjunto el programa tal y como lo llevo. :P

Código
  1. #include <stdio.h>
  2. #define TAMCAD 100 // Tamaño máximo de cadenas de caracteres
  3. #define MAXING 20  // Nro máximo de ingredientes por receta
  4. // Definición de estructuras del problema
  5.  
  6. struct propiedades{
  7. float grasas; // gramos de grasa por cada 100gr
  8. float hidratos; // gramos de hidratos de carbono por cada 100gr
  9. float proteina; // gramos de proteina de carbono por cada 100gr
  10. int Kcalorias; // KiloCalorías por 100gr
  11. char tipo; // Tipo de alimento: 'V'=Vegetal, 'A'=Animal, 'M'=Mineral, 'L'=Lacteo o huevo
  12. };
  13. struct ingredientes{
  14. int id; // Identificador del ingrediente
  15. char nombre[TAMCAD]; // Nombre del ingrediente
  16. struct propiedades nutrientes; // Propiedades del ingrediente
  17. };
  18. struct receta{
  19. char nombre[TAMCAD]; // Nombre de la receta
  20. int numIngredientes; // Nro de ingredientes de la receta
  21. int id[MAXING]; // Identificador del ingrediente
  22. int cantidad[MAXING]; // Gramos del ingrediente a utilizar
  23. };
  24.  
  25. // PROTOTIPO: COMPLETAR
  26. float procesaReceta(int ingredientes tipos[], int tiposIngredientes, int receta R[]);
  27.  
  28. int main()
  29. {
  30. float res;
  31. int numTiposIngredientes = 11; // Nro de tipos de ingrediente disponibles
  32. // Tabla de ingrediente de ejemplo
  33. struct ingredientes tiposIngredientes[]={
  34. {2543,"Aceite de oliva",{99.9, 0, 0, 887,'V'}},
  35. {2361,"Ajo",{0.23,24.3,4,117,'V'}},
  36. {2660,"Arroz",{0.9,86,7,387,'V'}},
  37. {2134,"Atun",{3.3,0,22,119,'A'}},
  38. {2127,"Huevo",{11.1,0,12.5,150,'L'}},
  39. {2403,"Patata",{0.2,15.2,2.2,73,'V'}},
  40. {2419,"Setas",{0.3,4,1.8,26,'V'}},
  41. {2677,"Harina de trigo",{0,71.5,10,333,'V'}},
  42. {866, "Sal",{0,0,0,0,'M'}},
  43. {2493,"Leche de vaca",{3.8,4.7,3,65,'L'}},
  44. {2285,"Pavo",{8.5,0,21,158,'A'}}
  45. };
  46. // Algunas recetas de prueba
  47. struct receta r[3]={
  48. {"Tortilla",4,{2543,2403,866,2127},{60,300,3,100}},
  49. {"Arroz con setas",5,{2543,2361,2660,2419,866},{40,15,250,125,5}},
  50. {"Pizza",6,{2543,2677,2134,2127,866,0},{20,150,100,80,4,0}} // Esta receta tiene un ingrediente 0 que no existe
  51. };
  52. // LLamada a función procesaReceta. Pruebe diferentes recetas anteriores: r[0], r[1] o r[2]
  53. res = procesaReceta(ingredientes tipos, tiposIngredientes, receta R[0]);
  54.  
  55. // Resultado
  56. printf("El valor resultado es %f\n",res);
  57. }
  58. // ======= COPIE EN DOCTUS A PARTIR DE ESTA lÍNEA ===========================
  59. // Aquí prototipo de posbles funciones auxiliares que emplee
  60.  
  61.  
  62.  
  63. // Definición de su función solución
  64. float procesaReceta(int ingredientes tipos[], int tiposIngredientes, int receta R[])
  65. {
  66. int i,j,flag;
  67. float receta=1;
  68. for(i=0;i<(R->numIngredientes) && receta!=-1; i++){
  69. for(j=0; j<tiposIngredientes && receta!=-1; j++){
  70. if(R->id[i]==tipos[j].id){
  71. receta=(tipos[j].nutrientes.tipo=='A');
  72.    receta=0;
  73.    if(R->id[i]!=tipos[j].id){
  74.      receta=-1;
  75.    }
  76.  
  77. }
  78. }
  79. return receta;
  80. }

MOD: El código debe ir entre etiquetas de Código GeSHi


« Última modificación: 9 Mayo 2021, 12:36 pm por K-YreX » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Petición de ayuda para un problema bastante básico de programación en c++
« Respuesta #1 en: 9 Mayo 2021, 13:13 pm »

El código está bastante bien estructurado (que no es poco decir).
Sin embargo, la función procesarReceta() sí que tiene algunos errores: utilizas dos tipos al mismo tiempo (int y struct...).

Antes de empezar con el problema concreto voy a mencionar un par de consejos para utilizarlos yo mismo a partir de aquí:
Cuando se define una estructura, puedes utilizar la palabra typedef para crear un nuevo tipo y no tener que utilizar siempre la palabra struct.
Los nombres de los structs es mejor que empiecen por mayúscula.
Código
  1. typedef struct {
  2.  char nombre[TAMCAD];
  3.  int numIngredientes;
  4.  int id[MAXING];
  5.  int cantidad[MAXING];
  6. } Receta;
  7. // Ahora puedes utilizar el tipo Receta asi:
  8. Receta miReceta;
  9. // en vez de asi:
  10. struct Receta miReceta;

En primer lugar, tal y como dices en la explicación, la función debe devolver {1, 0, -1} por lo que el tipo de valor de retorno deberá ser int, mejor que float.
Ahora vamos a ver los parámetros... Si tú quieres ver si una receta tiene ingredientes de origen animal necesitarás, para empezar, la receta. ¿Cuántas? 1, la que quieres procesar. No todas las recetas. Por lo que de momento:
Código
  1. int procesarReceta(Receta receta, ...);
Ahora esa receta tiene una lista de ingredientes (concretamente un array con los ids de los ingredientes). Entonces necesitarás recibir una lista con todos los ingredientes para poder buscar según su id. Por lo tanto:
Código
  1. int procesarReceta(Receta receta, Ingrediente ingredientes[], int numeroIngredientes, ...);
* En C/C++, cuando se pasa un array como parámetro suele ser necesario en la mayoría de los casos pasar un parámetro adicional para saber la longitud de ese array.
** En vez de llamar a la struct "Ingredientes" (en plural), la llamaría "Ingrediente" (en singular). Porque cada instancia será un ingrediente y no varios. A diferencia de "Propiedades" que cada instancia engloba varias propiedades.

Y con esos parámetros ya podemos implementar la función, por lo que quedaría así:
Código
  1. int procesarReceta(Receta receta, Ingrediente ingredientes[], int numeroIngredientes) {
  2.  // tu codigo aqui
  3. }

Ahora el algoritmo de tu función:
Teniendo la receta que quieres comprobar, tienes que recorrer todos sus ingredientes mientras que no hayas encontrado uno que sea animal y mientras no se acaben los ingredientes. Por cada uno de esos ingredientes, debes recorrer el array de ingredientes para encontrar el que coincide según su id y mirar si es de tipo animal.
Hay un pequeño detalle que no está bien definido en la explicación: si una receta tiene un ingrediente de origen animal y otro desconocido, qué se debe devolver? 1 o -1? Eso quedará a decisión tuya.
En pseudocódigo sería algo así:
Código:
i := 0 // Indica el indice del ingrediente actual de la receta
resultado := 0 // Indica: 0 (no animal) | 1 (animal) | -1 (desconocido)
MIENTRAS i < receta.numIngredientes && resultado == 0 HACER
  j := 0 // Indica el indice del ingrediente actual entre todos los ingredientes
  MIENTRAS j < numIngredientes && ingredientes[j].id != receta.ingredientes[i] HACER
    j := j +1
  FIN MIENTRAS
  // Aqui llegamos si hemos encontrado el ingrediente correspondiente segun el id o si no existe
  SI j < numIngredientes ENTONCES // lo hemos encontrado en la posicion j
    resultado := (ingredientes[j].tipo == 'A') // Esto sera 1 si la comparacion es true o 0 si es false
  SINO // no lo hemos encontrado
    resultado := -1
  FIN SI
  i := i + 1
FIN MIENTRAS
RETURN resultado
* Este algoritmo devuelve 1 o -1 en función de lo primero que encuentre. Y 0 si no encuentra ninguno de los otros dos casos.
Conviértelo a C (es muy sencillo) y pruébalo. A partir de ahí puedes hacer los cambios que consideres.


En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
JoaquinVT312

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Re: Petición de ayuda para un problema bastante básico de programación en c++
« Respuesta #2 en: 9 Mayo 2021, 14:04 pm »

El código está bastante bien estructurado (que no es poco decir).
Sin embargo, la función procesarReceta() sí que tiene algunos errores: utilizas dos tipos al mismo tiempo (int y struct...).

Antes de empezar con el problema concreto voy a mencionar un par de consejos para utilizarlos yo mismo a partir de aquí:
Cuando se define una estructura, puedes utilizar la palabra typedef para crear un nuevo tipo y no tener que utilizar siempre la palabra struct.
Los nombres de los structs es mejor que empiecen por mayúscula.
Código
  1. typedef struct {
  2.  char nombre[TAMCAD];
  3.  int numIngredientes;
  4.  int id[MAXING];
  5.  int cantidad[MAXING];
  6. } Receta;
  7. // Ahora puedes utilizar el tipo Receta asi:
  8. Receta miReceta;
  9. // en vez de asi:
  10. struct Receta miReceta;

En primer lugar, tal y como dices en la explicación, la función debe devolver {1, 0, -1} por lo que el tipo de valor de retorno deberá ser int, mejor que float.
Ahora vamos a ver los parámetros... Si tú quieres ver si una receta tiene ingredientes de origen animal necesitarás, para empezar, la receta. ¿Cuántas? 1, la que quieres procesar. No todas las recetas. Por lo que de momento:
Código
  1. int procesarReceta(Receta receta, ...);
Ahora esa receta tiene una lista de ingredientes (concretamente un array con los ids de los ingredientes). Entonces necesitarás recibir una lista con todos los ingredientes para poder buscar según su id. Por lo tanto:
Código
  1. int procesarReceta(Receta receta, Ingrediente ingredientes[], int numeroIngredientes, ...);
* En C/C++, cuando se pasa un array como parámetro suele ser necesario en la mayoría de los casos pasar un parámetro adicional para saber la longitud de ese array.
** En vez de llamar a la struct "Ingredientes" (en plural), la llamaría "Ingrediente" (en singular). Porque cada instancia será un ingrediente y no varios. A diferencia de "Propiedades" que cada instancia engloba varias propiedades.

Y con esos parámetros ya podemos implementar la función, por lo que quedaría así:
Código
  1. int procesarReceta(Receta receta, Ingrediente ingredientes[], int numeroIngredientes) {
  2.  // tu codigo aqui
  3. }

Ahora el algoritmo de tu función:
Teniendo la receta que quieres comprobar, tienes que recorrer todos sus ingredientes mientras que no hayas encontrado uno que sea animal y mientras no se acaben los ingredientes. Por cada uno de esos ingredientes, debes recorrer el array de ingredientes para encontrar el que coincide según su id y mirar si es de tipo animal.
Hay un pequeño detalle que no está bien definido en la explicación: si una receta tiene un ingrediente de origen animal y otro desconocido, qué se debe devolver? 1 o -1? Eso quedará a decisión tuya.
En pseudocódigo sería algo así:
Código:
i := 0 // Indica el indice del ingrediente actual de la receta
resultado := 0 // Indica: 0 (no animal) | 1 (animal) | -1 (desconocido)
MIENTRAS i < receta.numIngredientes && resultado == 0 HACER
  j := 0 // Indica el indice del ingrediente actual entre todos los ingredientes
  MIENTRAS j < numIngredientes && ingredientes[j].id != receta.ingredientes[i] HACER
    j := j +1
  FIN MIENTRAS
  // Aqui llegamos si hemos encontrado el ingrediente correspondiente segun el id o si no existe
  SI j < numIngredientes ENTONCES // lo hemos encontrado en la posicion j
    resultado := (ingredientes[j].tipo == 'A') // Esto sera 1 si la comparacion es true o 0 si es false
  SINO // no lo hemos encontrado
    resultado := -1
  FIN SI
  i := i + 1
FIN MIENTRAS
RETURN resultado
* Este algoritmo devuelve 1 o -1 en función de lo primero que encuentre. Y 0 si no encuentra ninguno de los otros dos casos.
Conviértelo a C (es muy sencillo) y pruébalo. A partir de ahí puedes hacer los cambios que consideres.

Primero muchas gracias por la atención.

Tengo varias dudas al respecto, por si podrías ayudarme, por favor.

Primero decir que es verdad que me expliqué mal acerca del ejercicio. El programa devolvería 1 de ser totalmente vegetariana la receta y 0 de encontrar algún alimento animal, pero siempre prevalecería el encontrar un ingrediente desconocido, es decir, de encontrar uno devolvería -1, independientemente ya de que sea vegetal o animal la receta.

Segundo decir que es un ejercicio predefinido y, por lo tanto, solo puedo tocar la función, ( no me permite editar el enunciado en sí, y el nombre de las cosas, (lo digo por el tema que me has comentado de facilitar algunas cosas utilizando plurales o no teniendo que usar struct siempre, aún así me ha venido bien y te lo agradezco, puesto que me lo he apuntado para futuros programas en los que si pueda aplicarlos.
Tengo dudas sobre la llamada a la función:

// LLamada a función procesaReceta. Pruebe diferentes recetas anteriores: r[0], r[1] o r[2]

res = procesarReceta(Receta receta, Ingredientes ingredientes[],  numIngredientes);


Eso me da error y no me deja compilar, por lo que me quedo ahí atascado y no puedo compilar e ir probando s editar el código de la función para ver si va funcionando correctamente o no.

Gracias de nuevo por la atención.
En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Petición de ayuda para un problema bastante básico de programación en c++
« Respuesta #3 en: 9 Mayo 2021, 14:30 pm »

Primero decir que es verdad que me expliqué mal acerca del ejercicio. El programa devolvería 1 de ser totalmente vegetariana la receta y 0 de encontrar algún alimento animal, pero siempre prevalecería el encontrar un ingrediente desconocido, es decir, de encontrar uno devolvería -1, independientemente ya de que sea vegetal o animal la receta.
En el algoritmo anterior he intercambiado el significado del 1 y el 0 pero puedes corregir eso sin mayor problema.
También deberás cambiar un poco el código para que busque todos los ingredientes por si alguno es desconocido.

Tengo dudas sobre la llamada a la función:
// LLamada a función procesaReceta. Pruebe diferentes recetas anteriores: r[0], r[1] o r[2]
res = procesarReceta(Receta receta, Ingredientes ingredientes[],  numIngredientes);
Eso me da error y no me deja compilar, por lo que me quedo ahí atascado y no puedo compilar e ir probando s editar el código de la función para ver si va funcionando correctamente o no.
Gracias de nuevo por la atención.
Te dará error de compilación porque el prototipo de la función tiene que ser igual que la implementación y no lo habrás cambiado en ambas partes del código.
Si el problema no es ese, añade el prototipo de la función, la implementación y la llamada para ver cómo la utilizas.
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
JoaquinVT312

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Re: Petición de ayuda para un problema bastante básico de programación en c++
« Respuesta #4 en: 9 Mayo 2021, 17:32 pm »

En el algoritmo anterior he intercambiado el significado del 1 y el 0 pero puedes corregir eso sin mayor problema.
También deberás cambiar un poco el código para que busque todos los ingredientes por si alguno es desconocido.
Te dará error de compilación porque el prototipo de la función tiene que ser igual que la implementación y no lo habrás cambiado en ambas partes del código.
Si el problema no es ese, añade el prototipo de la función, la implementación y la llamada para ver cómo la utilizas.

Te adjunto lo que llevo porque me sigue saliendo error en la llamada y estoy atascado ahí.
De nuevo gracias por la ayuda.
Código
  1. #include <stdio.h>
  2. #define TAMCAD 100 // Tamaño máximo de cadenas de caracteres
  3. #define MAXING 20  // Nro máximo de ingredientes por receta
  4. // Definición de estructuras del problema
  5.  
  6. struct propiedades{
  7. float grasas; // gramos de grasa por cada 100gr
  8. float hidratos; // gramos de hidratos de carbono por cada 100gr
  9. float proteina; // gramos de proteina de carbono por cada 100gr
  10. int Kcalorias; // KiloCalorías por 100gr
  11. char tipo; // Tipo de alimento: 'V'=Vegetal, 'A'=Animal, 'M'=Mineral, 'L'=Lacteo o huevo
  12. };
  13. struct ingredientes{
  14. int id; // Identificador del ingrediente
  15. char nombre[TAMCAD]; // Nombre del ingrediente
  16. struct propiedades nutrientes; // Propiedades del ingrediente
  17. };
  18. struct receta{
  19. char nombre[TAMCAD]; // Nombre de la receta
  20. int numIngredientes; // Nro de ingredientes de la receta
  21. int id[MAXING]; // Identificador del ingrediente
  22. int cantidad[MAXING]; // Gramos del ingrediente a utilizar
  23. };
  24.  
  25. // PROTOTIPO: COMPLETAR
  26. int procesarReceta(receta receta, ingredientes ingredientes[], int numIngredientes);
  27.  
  28. int main()
  29. {
  30. float res;
  31. int numTiposIngredientes = 11; // Nro de tipos de ingrediente disponibles
  32. // Tabla de ingrediente de ejemplo
  33. struct ingredientes tiposIngredientes[]={
  34. {2543,"Aceite de oliva",{99.9, 0, 0, 887,'V'}},
  35. {2361,"Ajo",{0.23,24.3,4,117,'V'}},
  36. {2660,"Arroz",{0.9,86,7,387,'V'}},
  37. {2134,"Atun",{3.3,0,22,119,'A'}},
  38. {2127,"Huevo",{11.1,0,12.5,150,'L'}},
  39. {2403,"Patata",{0.2,15.2,2.2,73,'V'}},
  40. {2419,"Setas",{0.3,4,1.8,26,'V'}},
  41. {2677,"Harina de trigo",{0,71.5,10,333,'V'}},
  42. {866, "Sal",{0,0,0,0,'M'}},
  43. {2493,"Leche de vaca",{3.8,4.7,3,65,'L'}},
  44. {2285,"Pavo",{8.5,0,21,158,'A'}}
  45. };
  46. // Algunas recetas de prueba
  47. struct receta r[3]={
  48. {"Tortilla",4,{2543,2403,866,2127},{60,300,3,100}},
  49. {"Arroz con setas",5,{2543,2361,2660,2419,866},{40,15,250,125,5}},
  50. {"Pizza",6,{2543,2677,2134,2127,866,0},{20,150,100,80,4,0}} // Esta receta tiene un ingrediente 0 que no existe
  51. };
  52. // LLamada a función procesaReceta. Pruebe diferentes recetas anteriores: r[0], r[1] o r[2]
  53. res = procesarReceta(receta receta, ingredientes ingredientes[], int numIngredientes);
  54.  
  55. // Resultado
  56. printf("El valor resultado es %f\n",res);
  57. }
  58. // ======= COPIE EN DOCTUS A PARTIR DE ESTA lÍNEA ===========================
  59. // Aquí prototipo de posbles funciones auxiliares que emplee
  60.  
  61.  
  62.  
  63. // Definición de su función solución
  64. int procesarReceta(receta receta, ingredientes ingredientes[], int numIngredientes)
  65.  
  66. int i:= 0; // Indica el indice del ingrediente actual de la receta
  67. int resultado := 0; // Indica: 0 (no animal) | 1 (animal) | -1 (desconocido)
  68. while(i < receta.numIngredientes && resultado !=-1) {
  69. j := 0;
  70.  
  71.    while(j < numIngredientes && ingredientes[j].id != receta.ingredientes[i])  {
  72.  j := j +1;// Indica el indice del ingrediente actual entre todos los ingredientes
  73.  
  74. }
  75.  
  76.  // Aqui llegamos si hemos encontrado el ingrediente correspondiente segun el id o si no existe
  77.  if (j < numIngredientes){
  78.   // lo hemos encontrado en la posicion j
  79.    if (resultado := (ingredientes[j].tipo == 'A')){
  80.     resultado:=0;
  81. }
  82. }// Esto sera 0 si la comparacion es true o 1 si es false
  83.  else{// no lo hemos encontrado
  84.    resultado := -1}
  85.  
  86.  i := i + 1;
  87. }
  88. return resultado;
  89. }

MOD: El código debe estar entre etiquetas de Código GeSHi
« Última modificación: 9 Mayo 2021, 17:33 pm por K-YreX » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Petición de ayuda para un problema bastante básico de programación en c++
« Respuesta #5 en: 9 Mayo 2021, 17:56 pm »

El código publicado en un mensaje debe estar entre etiquetas de Código GeSHi. Puedes seleccionarlas desde el desplegable que dice Código GeSHi (eligiendo el lenguaje adecuado) o escribiendo directamente:
[code=c]
Tu código aquí
[/code]

Tienes 3 problemas:
  • Al no estar utilizando typedef como indiqué en el primer mensaje, debes utilizar la palabra struct obligatoriamente cada vez que quieras hacer referencia a un struct (struct receta, struct ingredientes,...). Además no utilices el mismo nombre para la struct que para la variable, no es nada recomendable.
  • Al momento de utilizar la función (línea 53) no tienes que indicar el tipo sino una variable que se corresponda con ese tipo.
Código
  1. res = procesarReceta(r[0], tiposIngredientes, numTiposIngredientes);
  • Te has limitado a copiar casi literalmente mi pseudocódigo (y el pseudocódigo es una forma más o menos flexible de diseñar un algoritmo utilizando sintaxis que no tiene que ser de ningún lenguaje concreto). En C las asignaciones no se hacen con := por lo que esa sintaxis no existe. Además hay un par de líneas que te has medio inventado (79-81) y te he indicado en el comentario anterior que tendrías que hacer ciertos cambios que tampoco veo.
Todos esos errores son muy básicos y cualquier compilador que utilices para compilar tu programa seguro que te indicará la línea del error y el motivo.

Si te limitas a copiar la solución sin entenderla, no vas a conseguir nada. El segundo problema demuestra que intentas utilizar una función sin entender su funcionamiento y en general todo demuestra que no quieres entenderlo, sólo conseguir que funcione. Y eso va a ser tu mayor problema.

Igual de fácil que me es a mí saber todo eso sólo viendo tu código, le será a tu profesor/a o a quien tengas que entregar ese programa. Y una simple búsqueda por Internet le servirá para ver de dónde has sacado la solución... :rolleyes: :rolleyes: Intentando engañar a los demás, sólo te engañas a ti mismo.
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines