Ver Mensaje Individual
  #2 (permalink)  
Antiguo 26/10/2015, 02:35
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: Funciones en C

Buenas.

Vamos a ver. Si ya has conseguido que tu programa cumpla con el objetivo final entonces has hecho lo más dificil. Agrupar el código en funciones es algo relativamente sencillo.

Por cierto, tu programa no funciona:

Código C:
Ver original
  1. char cad[123];
  2. scanf("%s",&cad);

cad es de tipo char* y scanf espera un puntero... al poner &cad le estás pasando un puntero doble (char**) si te funciona es porque el compilador detecta el error y lo corrige por tí, pero no abuses de las bondades del compilador porque no es un comportamiento estándar, en clase te puede fallar y es, al fin y al cabo, un error.

Por otro lado, los caracteres hay que encerrarlos con comillas simples y eso se aplica también al caracter nulo \0.

Y, para rematar, system se encuentra en una librería que no has incluído en tu ejemplo.

Por estas tres "tonterías" tu programa no compila y no funciona. Mi consejo es que no des un programa por terminado mientras salten "warnings" al compilar. Un "warning" es un error que no impide que el programa compile... pero no deja de ser un error y puede provocar que tu programa no funcione como esperas.

Bueno, dicho esto, vamos a por las funciones.
1. Separa el código por responsabilidades

Un programa se compone de líneas de código... vale, sin embargo no todo el código se encarga de lo mismo.

Por ejemplo, en tu programa tienes una parte del código que pide datos al usuario, otra que busca una letra en una cadena y contabiliza el número de apariciones y otra que muestra un resultado al usuario. Podríamos decir, por tanto, que tu programa podría dividirse así a bote pronto en tres funciones independientes:
  • pedirDatos: Esta función le pide al usuario la información necesaria para ejecutar el programa.
  • contarApariciones: Esta función contará el número de veces que una letra se repite en una cadena.
  • mostrarResultado: Esta función le informará al usuario sobre lo devuelto por la función anterior.
Cada programa es diferente, el nombre de las funciones es libre (siempre y cuando no se repitan los nombres) y depende de ti elegir el grado de división que buscas. Si, por ejemplo, una funcionalidad determinada queda representada por una línea lo mismo no es necesario crear una función para dicho código... sin embargo si esta funcionalidad se usa en muchas partes del código puede que cobre cierto sentido tener una función específica para no repetir el mismo código.

2. Revisa las necesidades de tu nueva función

Ya has decido en cuántas partes vas a dividir el código, ahora tienes que centrarte en revisar qué va a necesitar "del exterior" cada una de estas funciones para poder realizar su cometido correctamente:
  • pedirDatos: Esta función no necesita información previa, pero si necesita un mecanismo para devoler una cadena de caracteres y la letra a buscar.
    Como son dos elementos a devolver, el return se nos queda corto. Una solución es que la función acepte dos variables a modo de punteros, en la primera almacenará la cadena y en la segunda la letra a buscar.
  • contarApariciones: Esta función necesita las dos variables devueltas por la función anterior y necesita además devolver el número total de apariciones... las dos variables iniciales se pueden pasar como parámetros y dejar que el número de apariciones lo devuelva con un return.
  • mostrarResultado: Esta función necesita la letra que se está buscando y el número de apariciones que se han encontrado... con dos parámetros debería bastar.

3. Trocear el código

Con los dos pasos anteriores ya tienes todos los requisitos necesarios para empezar a separar el código... manos a la obra.

Empezamos escribiendo la firma de la función en base a los requisitos que hemos visto en el punto 2:

Código C:
Ver original
  1. void pedirDatos(char* cadena, char* letra);
  2. int contarApariciones(char* cadena, char letra);
  3. void mostrarResultado(char letra, int apariciones);

Nota que para la letra, en pedirDatos se usa un char* y en mostrarResultado se usa char. Esto es así porque en la primera función el parámetro es de salida (es decir, es la función la que establece el valor y dicho valor se usará fuera de la función) y en la segunda función el parámetro es de entrada (nosotros le facilitamos el valor a la función).

Con las firmas ya definidas podemos empezar a rellenar su código:

Código C:
Ver original
  1. void pedirDatos(char* cadena, char* letra)
  2. {
  3.   printf("Introduce una palabra: ");
  4.   // fflush(stdin); <<---- EVITA ESTO!!!
  5.   scanf("%s",cadena);
  6.   printf("\nQue letra quiere buscar?: ");
  7.   // fflush(stdin); <<---- EVITA ESTO!!!
  8.   scanf("%c",letra);
  9. }

he comentado el código de fflush, el motivo es que esta función está pensada para vacíar buffers de salida, no de entrada. Esas dos líneas que te he comentado pueden tener consecuencias indeterminadas para tu programa.

Si necesitas limpiar el buffer de entrada te recomiendo mirar otras alternativas, como por ejemplo:

Código C:
Ver original
  1. while ( getchar() != '\n' );

Segunda función:

Código C:
Ver original
  1. int contarApariciones(char* cadena, char letra)
  2. {
  3.   int i,total;
  4.   for (i=0, total=0; cadena[i] != \0 ; i++)
  5.   {
  6.     if (cadena[i] == letra)
  7.       total++;
  8.   }
  9.   return total;
  10. }

¿Te atreves con la tercera? deberías intentarlo, necesitas aprender a hacer esto por tu cuenta.

Te pongo el código del main:

Código C:
Ver original
  1. int main()
  2. {
  3.   char cadena[100];
  4.   char letra;
  5.   int apariciones;
  6.  
  7.   pedirDatos(cadena,&letra);
  8.   apariciones = contarApariciones(cadena,letra);
  9.   mostrarResultado(letra,apariciones);
  10.  
  11.   return 0;
  12. }

Este main, a diferencia del tuyo, no tiene bucles. Lo he puesto así porque te sirve de base para comprobar que tus nuevas funciones cumplen con su cometido. Cuando te funcione esta parte será el momento de pensar en cómo incoporar (a ser posible con funciones) un bucle que le pida una letra al usuario hasta que introduzca una que sí se encuentre en la cadena introducida.

Un saludo