Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: MrCorn en 29 Abril 2021, 00:05 am



Título: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MrCorn en 29 Abril 2021, 00:05 am
¡Hola! hice este programa para practicar con argc y argv y poder pasar parámetros a consola, mediante generaciones de claves, la primera parte del código la he utilizado para el 1º parámetro (que siempre va a ser fijo y por eso lo tengo apartado del otro for) que tiene que ser la longitud de la contraseña (donde el usuario mediante el número que el ponga así se generará la longitud de su clave. -10, -20...). He hecho el ciclo for para que el parámetro 1 siempre sea el de la longitud (ya que luego tengo más), y después he usado el isdigit para que reciba el char que en este caso va a ser el número de la longitud de la clave que va a querer el usuario. Pero me gustaría saber si hay alguna manera o función que con lo que llevo hecho pueda cargar el tamaño de la clave desde ahí y que luego mande el mensaje de error:

Código
  1. /*El 1º parámetro siempre va a ser la longitud de la clave*/
  2.  
  3. for (int i=1; i<argc; i++){
  4.    if (isdigit (*argv[1])){
  5.  
  6.        //¿Poder cargar el tamaño de la clave?
  7.    }
  8.    else{
  9.  
  10.    printf("Primero debes indicarle una longitud a la contrase%ca.", 164);
  11.    exit(-1);
  12.    }
  13. }

Código
  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <ctype.h>
  6.  
  7. int main(int argc, char *argv[]){
  8.  
  9. /* Cada uno de los parámetros necesarios para utilizar en la consola*/
  10.  
  11. int mayusculas = 0;
  12. int minusculas = 0;
  13. int digitos = 0;
  14. int especiales = 0;
  15.  
  16. #define CARACTERES_ESPECIALES "!@#$^&*?"
  17.  
  18. /*El 1º parámetro siempre va a ser la longitud de la clave*/
  19.  
  20. for (int i=1; i<argc; i++){
  21.    if (isdigit (*argv[1])){
  22.  
  23.        //???
  24.    }
  25.    else{
  26.  
  27.    printf("Primero debes indicarle una longitud a la contrase%ca.", 164);
  28.    exit(-1);
  29.    }
  30. }
  31.  
  32. /*A partir del 2º parámetro pueden ser mayúsculas, minúsculas...*/
  33.  
  34. for (int i=2; i<argc; i++){
  35.  
  36.    if (strcmp(argv[i], "-M") == 0){
  37.  
  38.        mayusculas = 1;
  39.    }
  40.    else if (strcmp(argv[i], "-n") == 0){
  41.  
  42.        minusculas = 1;
  43.    }
  44.    else if (strcmp(argv[i], "-ce") == 0){
  45.  
  46.        especiales = 1;
  47.    }
  48.    else if (strcmp(argv[i], "-Mn") == 0 || strcmp(argv[i], "-nM") == 0){
  49.  
  50.        mayusculas = 1;
  51.        minusculas = 1;
  52.    }
  53.    else if ((strcmp(argv[i], "-ndM") == 0) || (strcmp(argv[i], "-nMd")) == 0 || ((strcmp(argv[i], "-dnM") == 0) || (strcmp(argv[i], "-Mnd")) == 0)){
  54.  
  55.        mayusculas = 1;
  56.        minusculas = 1;
  57.        digitos = 1;
  58.    }
  59.    else if (strcmp(argv[i], "-all") == 0){
  60.  
  61.        mayusculas = 1;
  62.        minusculas = 1;
  63.        digitos = 1;
  64.        especiales = 1;
  65.    }
  66.    else{
  67.  
  68.        printf("Clave no v%clida.", 160);
  69.        exit(-1);
  70.    }
  71. }
  72. /*Creamos el alfabeto de todos los parámetros para luego hacer la clave libremente*/
  73.  
  74. int tam_alfabeto = 1; // Para finalizar la cadena - depuración
  75. if (mayusculas) tam_alfabeto += 'Z' - 'A' + 1;
  76. if (minusculas) tam_alfabeto += 'z' - 'a' + 1;
  77. if (digitos)    tam_alfabeto += 10;
  78. if (especiales) tam_alfabeto += strlen(CARACTERES_ESPECIALES);
  79.  
  80. char * alfabeto = (char*)malloc(tam_alfabeto * sizeof(char));
  81. int index = 0;
  82.  
  83. for (char c='A'; c<='Z' && mayusculas; c++)
  84.    alfabeto[index++] = c;
  85.  
  86. for (char c='a'; c<='z' && minusculas; c++)
  87.    alfabeto[index++] = c;
  88.  
  89. for (char c='0'; c<='9' && digitos; c++)
  90.    alfabeto[index++] = c;
  91.  
  92. for (int i=0; i<strlen(CARACTERES_ESPECIALES); i++)
  93.    alfabeto[index++] = CARACTERES_ESPECIALES[i];
  94.  
  95. alfabeto[index] = 0; // Solo para fines de depuración
  96.  
  97. /*Generamos la clave*/
  98.  
  99. srand(time(NULL));
  100.  
  101. int clave_ok;
  102. char*clave = (char*)malloc((argc+1)*sizeof(char));
  103. for( int i=0; i<argc; i++){
  104.  
  105.    clave[i] = alfabeto[rand()%tam_alfabeto];
  106. }
  107.  
  108. clave[argc] = 0; // Finalizamos la cadena
  109.  
  110. }


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MAFUS en 29 Abril 2021, 20:05 pm
Muy buenas. Prueba el siguiente código, he añadido unas líneas para controlar que los parámetros son más de uno:

Código
  1. // Comprobamos que existe más de un parámetro (el nombre) en la línea de comandos
  2. if(argc < 3) {
  3.    fprintf(stderr, "%s\n", "Debe introducir la longitud de la clave...");
  4.    exit(EXIT_FAILURE);
  5. }
  6.  
  7. /*El 1º parámetro siempre va a ser la longitud de la clave*/
  8. if(sscanf(argv[1], "%u", &longitud_clave) == 0) {
  9.    fprintf(stderr, "%s\n", "El primer parámetro debe ser un entero. Indica la longitud de la clave...");
  10.    exit(EXIT_FAILURE);
  11. }
  12.  


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MrCorn en 29 Abril 2021, 20:55 pm
Hola MAFUS, gracias por responder y por la ayuda, el problema que tengo es que a la hora de recoger la longitud de la clave me sigue saliendo una contraseña de 3 caracteres de longitud, da igual lo que ponga.


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MAFUS en 29 Abril 2021, 21:06 pm
Es por la línea 103:
Código:
for( int i=0; i<argc; i++){
Lo que haces es usar argc en vez del valor conseguido por argv[1]


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MrCorn en 29 Abril 2021, 21:21 pm
Lo he dejado tal que así, pero ahora directamente ni me da error, simplemente no sale nada en la consola :/

Código:
for( int i=0; i<*argv[1]; i++){

    clave[i] = alfabeto[rand()%tam_alfabeto];
}

Por cierto, tengo definido la longitud de la clave tal que así:

Código:
char longitud_clave[500];

Pero diría que no es el problema.


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: K-YreX en 29 Abril 2021, 21:28 pm
Tienes que convertir ese parámetro a un número positivo por ejemplo como te ha indicado MAFUS unos mensajes atrás:
Código
  1. /*El 1º parámetro siempre va a ser la longitud de la clave*/
  2. if(sscanf(argv[1], "%u", &longitud_clave) == 0) {
  3.    fprintf(stderr, "%s\n", "El primer parámetro debe ser un entero. Indica la longitud de la clave...");
  4.    exit(EXIT_FAILURE);
  5. }

EDITO: La variable longitud_clave tal y como se utiliza (y se debe utilizar) en el código citado en este mensaje debe ser de tipo unsigned int, es decir, entero sin signo. Lo que quieres guardar ahí es un número positivo con la longitud de la clave. Si utilizas como parámetro "-10" lo que quieres guardar es 10.


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MrCorn en 29 Abril 2021, 21:51 pm
Tienes que convertir ese parámetro a un número positivo por ejemplo como te ha indicado MAFUS unos mensajes atrás:

En principio lo tengo como me ha dicho MAFUS y sigue aún mostrándome 3 caracteres en vez de los que dice el usuario. Posiblemente sea algún fallo tonto que no estoy viendo o algo así.
EDITO: La variable longitud_clave tal y como se utiliza (y se debe utilizar) en el código citado en este mensaje debe ser de tipo unsigned int, es decir, entero sin signo. Lo que quieres guardar ahí es un número positivo con la longitud de la clave. Si utilizas como parámetro "-10" lo que quieres guardar es 10.

Si... He cambiado cambiado el tipo de la variable por un entero sin signo (menudo fallo).



¡Vale! He arreglado lo de que no me muestre solamente 3 caracteres, el problema se encuentra en que cuando le digo que me muestre 10 caracteres me muestra más o menos de los que deberían e incluso me da una contraseña con símbolos extraños que no tienen nada que ver con el parámetro que le proporciono.

Parece que el problema realmente está en la última parte donde hace una comprobación en la contraseña de si realmente están los parámetros que ha proporcionado el usuario, que no os la he mostrado porque pensaba que no era el problema realmente...

Os dejo todo el código a ver si me podéis ayudar:

Código
  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <ctype.h>
  6.  
  7. int main(int argc, char *argv[]){
  8.  
  9. /* Cada uno de los parámetros necesarios para utilizar en la consola*/
  10.  
  11. int mayusculas = 0;
  12. int minusculas = 0;
  13. int digitos = 0;
  14. int especiales = 0;
  15. unsigned int longitud_clave;
  16.  
  17. #define CARACTERES_ESPECIALES "!@#$^&*?"
  18.  
  19. /* Comprobamos que existe más de un parámetro (el nombre) en la línea de comandos */
  20.  
  21. if(argc < 3) {
  22.    fprintf(stderr, "%s\n", "Primero, debes introducir la longitud de la clave.");
  23.    exit(EXIT_FAILURE);
  24. }
  25.  
  26. /*El 1º parámetro siempre va a ser la longitud de la contraseña*/
  27.  
  28. if(sscanf(argv[1], "%u", &longitud_clave) == 0) {
  29.    fprintf(stderr, "%s\n", "El primer parametro debe ser un entero. Vuelve a ingresar la longitud.");
  30.    exit(EXIT_FAILURE);
  31. }
  32.  
  33. /*A partir del 2º parámetro pueden ser mayúsculas, minúsculas...*/
  34.  
  35. for (int i=2; i<argc; i++){
  36.  
  37.    if (strcmp(argv[i], "-M") == 0){
  38.  
  39.        mayusculas = 1;
  40.    }
  41.    else if (strcmp(argv[i], "-n") == 0){
  42.  
  43.        minusculas = 1;
  44.    }
  45.    else if (strcmp(argv[i], "-ce") == 0){
  46.  
  47.        especiales = 1;
  48.    }
  49.        else if (strcmp(argv[i], "-d") == 0){
  50.  
  51.        digitos = 1;
  52.    }
  53.    else if (strcmp(argv[i], "-Mn") == 0 || strcmp(argv[i], "-nM") == 0){
  54.  
  55.        mayusculas = 1;
  56.        minusculas = 1;
  57.    }
  58.    else if ((strcmp(argv[i], "-ndM") == 0) || (strcmp(argv[i], "-nMd")) == 0 || ((strcmp(argv[i], "-dnM") == 0) || (strcmp(argv[i], "-Mnd")) == 0)){
  59.  
  60.        mayusculas = 1;
  61.        minusculas = 1;
  62.        digitos = 1;
  63.    }
  64.    else if (strcmp(argv[i], "-all") == 0){
  65.  
  66.        mayusculas = 1;
  67.        minusculas = 1;
  68.        digitos = 1;
  69.        especiales = 1;
  70.    }
  71.    else{
  72.  
  73.        fprintf(stderr, "Clave no v%clida. Debes utilizar los par%cmetros indicados:", 160, 160);
  74.        fprintf(stderr, "\n-M, -n, -ce, -d, -Mn/-nM, -Mnd (y sus combinaciones) y -all");
  75.        exit(EXIT_FAILURE);
  76.    }
  77. }
  78. /*Creamos el alfabeto de todos los parámetros para luego hacer la contraseña libremente*/
  79.  
  80. int tam_alfabeto = 1; // Para finalizar la cadena - depuración
  81. if (mayusculas) tam_alfabeto += 'Z' - 'A' + 1;
  82. if (minusculas) tam_alfabeto += 'z' - 'a' + 1;
  83. if (digitos)    tam_alfabeto += 10;
  84. if (especiales) tam_alfabeto += strlen(CARACTERES_ESPECIALES);
  85.  
  86. char * alfabeto = (char*)malloc(tam_alfabeto * sizeof(char));
  87. int index = 0;
  88.  
  89. for (char c='A'; c<='Z' && mayusculas; c++)
  90.    alfabeto[index++] = c;
  91.  
  92. for (char c='a'; c<='z' && minusculas; c++)
  93.    alfabeto[index++] = c;
  94.  
  95. for (char c='0'; c<='9' && digitos; c++)
  96.    alfabeto[index++] = c;
  97.  
  98. for (int i=0; i<strlen(CARACTERES_ESPECIALES); i++)
  99.    alfabeto[index++] = CARACTERES_ESPECIALES[i];
  100.  
  101. alfabeto[index] = 0; // Solo para fines de depuración
  102.  
  103. /*Generamos la contraseña*/
  104.  
  105. srand(time(NULL));
  106.  
  107. int clave_ok;
  108. char*clave = (char*)malloc((*argv[1]+1)*sizeof(char));
  109. for( int i=0; i<*argv[1]; i++){
  110.  
  111.    clave[i] = alfabeto[rand()%tam_alfabeto];
  112. }
  113.  
  114. clave[argc] = 0; // Finalizamos la cadena
  115.  
  116. /*Hacemos una comprobación para que la contraseña tenga los parámetros que queremos*/
  117.  
  118.    do{
  119.  
  120.        for( int i=0; i<*argv[1]; i++){
  121.  
  122.            clave[i] = alfabeto[rand()%tam_alfabeto];
  123.        }
  124.  
  125.        int hay_mayusculas = 0;
  126.        int hay_minusculas = 0;
  127.        int hay_digitos    = 0;
  128.        int hay_especiales = 0;
  129.  
  130.        for (int i=0; i<*argv[1]; i++){
  131.  
  132.            hay_mayusculas |= (clave[i] >= 'A' && clave[i] <= 'Z');
  133.            hay_minusculas |= (clave[i] >= 'a' && clave[i] <= 'z');
  134.            hay_digitos    |= (clave[i] >= '0' && clave[i] <= '9');
  135.            hay_especiales |= (strchr(CARACTERES_ESPECIALES, clave[i]) != NULL);
  136.        }
  137.  
  138.        clave_ok = 1;
  139.        if (mayusculas) clave_ok &= hay_mayusculas;
  140.        if (minusculas) clave_ok &= hay_minusculas;
  141.        if (digitos)    clave_ok &= hay_digitos;
  142.        if (especiales) clave_ok &= hay_especiales;
  143.  
  144.        if (!clave_ok){
  145.  
  146.            printf("Clave no vaclida: %s\n", clave);
  147.            exit(-1);
  148.        }
  149.    } while (!clave_ok);
  150.  
  151.    printf("Clave generada: %s\n", clave);
  152.    free(clave);
  153. }

Menudo dolor de cabeza me está dando este código  :/


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MAFUS en 30 Abril 2021, 13:12 pm
Sigues teniendo muchos fallos lógicos, por ejemplo:

Línea 98, falta '&&especiales' en la condición de continuación
Código:
for (int i=0; i<strlen(CARACTERES_ESPECIALES) && especiales; i++)

Línea 109, usas *argv[1] cómo valor para dimensionar el un array dinámico. Está mal porque ves el entero que representa el primer carácter de la cadena argv[1], no el entero que debería ser. Habíamos dicho que quien guardaba el tamaño de la contraseña era la variable longitud_clave
Código:
char*clave = (char*)malloc((longitud_clave+1)*sizeof(char));

Algo parecido lo anterior en la línea 110, 120 y 130.

Línea 114, usas argc en vez de i para poner el carácter nulo. Tendrás que trabajar en ello porque i, tal y como está, no puede verse fuera del bucle. Tienes una solución a un bucle anterior en el que usas 'index'.

Ya con esto tienes unas pautas para seguir arreglando el código.
[code]clave[i] = 0;
[/code]


Título: Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa
Publicado por: MrCorn en 30 Abril 2021, 19:10 pm
Ha sido hacer esos cambios y ahora cuando estoy en consola, simplemente no me aparece nada, se queda como si estuviese cargando cuando meto cualquier parámetro. (Este va a ser el último programa de C porque es lamentable, esto no está hecho para mi)



Vale, al final conseguí solucionar el problema que tenía, estaba relacionado con el signo "-" a la hora de poner la longitud de la contraseña, simplemente me he saltado el signo y funciona perfectamente el programa.

Muchas gracias por la ayuda a ambos.