[ Foro de C++ ]
Buenas, me gustaria hacer un programa en c++ que me crease una matricula de coche ( en españa es 4 numeros y 3 letras ) en char y no encuentro el error que tengo.
este es el codigo
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <iostream>
using namespace std;
int main() {
char nmatricula[7];
cout<<"a"<<endl;
string numeros="0123456789";
string letrasma="BCFGHJKLMNPRSTVWXYZ";
/* alteramos la secuencia de azar */
srand ( time(NULL) );
for(int i=0;i<=4;i++) //generamos los 4 numeros
{
nmatricula[i]=numeros[rand()%10];
}
for(int i=4;i<=8;i++) //generamos las 3 letras
{
nmatricula[i]=letrasma[rand()%20];
cout<<"c"<<endl;
}
cout<<nmatricula<<endl;
cout<<"c"<<endl;
}
gracias de antemano.
En el primer ciclo for estás generando 5 números en vez de 4, debería ser así:
for(int i=0;i<4;i++)
En el segundo ciclo for estás generando 5 números en vez de 3, debería quedarte así:
for(int i=4;i<7;i++)
Antes de la última llave te faltó colocar: return 0;
Muchas gracias por contestar, he probado lo que dices y al imprimir nmatricula el inicio me sale correctamente, salen los cuatro numero y los tres caracteres de forma aleatoria pero justo a continuacion me salen 6 caracteres que no tendrian que estar ahí (siempre me salen los mismos) =S
0483JZF¼[?u0@
3295BMV¼[?u0@
6568KLC¼[?u0@
He conseguido evitar que me saliese ese error poniendo despues del segundo for
nmatricula[7]='\0';
Para marcarlo como final
¿Seria una solución valida?
PD: Habéis conseguido un usuario habitual mas de vuestra pagina, muy amables
El problema es que estás mezclando cadenas al estilo de C++, que son fáciles de manejar, con cadenas al estilo C (arrays de caracteres), que obligan a ser muy precavido.
En las cadenas al estilo C debes terminar con un carácter nulo (como has hecho al final), y en la longitud debes tener en cuenta ese carácter extra (algo que no has hecho todavía, y que puede dar problemas de tener el efecto colateral de modificar otras variables de forma inesperada). Decláralo como
char nmatricula[8];
La alternativa más elegante, en mi opinión, es que, ya que usas C++, la matrícula también sea un "string", en vez de un array de caracteres.
Sí, Kiraez, eso se me había olvidado comentarlo, y es totalmente válido, es más, es un requisito para terminar cadena de caracteres en lenguaje C. Tal como dice el prof. Nacho, ese caracter nulo '\0' al ser un caracter extra, debe ser considerado al declarar la variable nmatricula. O sea que nmatricula va a contener 7 caracteres correspondientes al número de matrícula más el caracter nulo, en total son 8 caracteres. Así:
.
char nmatricula[8]; // 7 caracteres de la matrícula más el caracter nulo
.
.
.
nmatricula[7] = '\0'; // finalizamos la cadena con el caracter nulo '\0', requisito obligatorio
.
.
.
Bueno, fui trasteando un poco con lo que me dijisteis y ayer hice un programa que me generaba mediante métodos estáticos una matricula, 50 matriculas o simplemente me pedía una por teclado y la validaba que se puede aprovechar para otros programas mayores. No esta perfecta por que en vez de generarlas directamente en string como me comentasteis primero las hago en char y luego las paso a string, pero ya lo arreglare cuando pueda =S
PD: en vez de almacenarla en un string normal lo hago en una estructura por que necesito practicar y ponerme al dia con segun que cosas, que para septiembre tengo que hacer un programa de gestion de archivos y me estoy poniendo bastante las pilas. Muchas gracias a los dos por responderme y echarme una mano ^^.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
using namespace std;
typedef struct{ //definimos la estructura
string matricula;
}coche;
void generarmatricula (string &matricula);
void mayuscula (string &s);
bool validamatriculas(string &matricula);
int main() {
coche coches;
coche cincoche[50];
int opcion,x;
bool estado;
do{
do{
cout<<"1. Genera matricula aleatorias"<<endl;
cout<<"2. Genera 50 matriculas aleatorias"<<endl;
cout<<"3. Mete matricula por teclado y validala"<<endl;
cout<<"0. Salir del programa"<<endl;
cin>>opcion;
}
while(opcion<0|| opcion>3);
switch(opcion){
case 1:
cout<<"generamos una matricula aleatoria"<<endl;
generarmatricula(coches.matricula);
cout<<coches.matricula<<endl;
break;
case 2:
cout<<"generamos cincuenta matriculas aleatorias"<<endl;
for(x=0;x<50;x++){
generarmatricula(cincoche[x].matricula);
}
for(x=0;x<50;x++){
cout<<cincoche[x].matricula<<endl;
}
break;
case 3:
do{
cout << "Introduce la matricula por teclado: ";
cin >> coches.matricula;
mayuscula(coches.matricula);
cout<<coches.matricula<<endl;
estado=validamatriculas(coches.matricula);
if(estado==true){
cout<<"La matricula introducida es valida y se ha guardado correctamente"<<endl;
}
else{
cout<<"Introduzca una matricula valida"<<endl;
}
}while(estado==false);
break;
}
}
while(opcion!=3);
return 0;
}
void generarmatricula (string &matricula){
char nmatricula[8];
string numeros="0123456789";
string letrasma="BCFGHJKLMNPRSTVWXYZ";
for(int i=0;i<4;i++) //generamos los 4 numeros
{
nmatricula[i]=numeros[rand()
%numeros.length()];
}
for(int i=4;i<7;i++) //generamos las 3 letras
{
nmatricula[i]=letrasma[rand()
%letrasma.length()];
}
nmatricula[7] = '\0';
matricula = string(nmatricula); //lo pasamos a string para que sea mas facil su manejo
}
void mayuscula (string &s){
/*for(int i;i<s.length;i++){ //esto funcionaria si el string solo fueran caracteres
s[i]=toupper(s[i]);
}*/
for(int i=4;i<7;i++){ //solo pasamos a mayuscula los caracteres
s[i]=toupper(s[i]);
}
}
bool validamatriculas(string &matricula){
string numeros="0123456789";
string letrasma="BCFGHJKLMNPRSTVWXYZ";
bool valida=true;
if (matricula.length()==7){ //revisamos que sea si o si de 7 caracteres
for(int i=0;i<4;i++){ //validamos los cuatro numeros
if(numeros.find(matricula[i])>numeros.length())
valida=false;
}
for(int i=4;i<7;i++){ //validamos los tres caracteres
if (letrasma.find(matricula[i])>letrasma.length())
valida=false;
}
}else
valida=false;
return valida;
}
Yo en general lo veo bien. Apenas alguna sugerencia de mejora poco importante, con la sana intención de que mejores aún más algo que ya funciona:
- Yo le haría algún retoque a nivel de estilo: las tabulaciones son demasiado grandes en general pero en cambio los "for" no están tabulados.
- Debes cuidar el paso de parámetros: le pasas la matrícula por referencia a "validar" sin que necesite modificarla, lo que puede dar efectos colaterales no deseados.
- Eso de que "generarmatricula" sea un "void" que modifica un parámetro por referencia en vez de devolver un "string" es un tanto desconcertante. Para mí sería más natural que fuera una función, y lo mismo ocurre con "mayuscula",
- Los nombres de las funciones son inconsistentes: una se llama "generarmatricula", que es un buen nombre, salvo por que una mayúscula intermedia lo haría más legible: "generarMatricula"; otra se llama "validamatriculas", con el verbo en imperativo en vez de infinitivo y el nombre en plural a pesar de que sólo valida una matrícula cada vez; "mayuscula" ni siquiera es un verbo, sería preferible algo como "convertirAMayusculas".
- Ese 50 que usas como límite sería mejor como constante, en vez de un "número mágico", o puedes dejar alguno sin corregir si en algún momento decides probar con otra cantidad.
- En las funciones que devuelven booleanos, como tu "validamatriculas", generalmente la ejecución será más rápida si cambias los "valida = false" por un "return false" y así dejas de evaluar en cuanto ya sabes que no vas a llegar a algo útil. En tu programa no es grave, hablamos de 7 letras, pero sí en un caso más complejo.
- "estado" es un nombre poco claro para un "booleano". ¿Que quiere decir el estado "true"? ?No sería mejor algo como "valido" o "terminado"?
Ya ves que son sólo pequeños detalles, pero las funcionalidades de tu programa parecen correctas.
(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)