Peleandome con C: hoy fgets feat strtol

3 respuestas [Último envío]
etern00b
Desconectado/a
se unió: 05/02/2022

Hola,
finalmente vengo a preguntar:
-¿que significa *nptr y **endptr? ¿son caracteres sin mas?
- tengo un código que he escrito mirando y probando, que pretende pedir al usuario la longitud de un arreglo(array) y los valores para cada componente. Según he leido, al usar fgets junto a strtol evitamos que se puedan escribir caracteres cuando pedimos cifras, etc y de ser asi devuelve 0. Pero cuando introduzco caracteres en la longitud del array no devuelve nada, cuando introduzco caracteres en los valores, devuelve algunos números grandes (parecido a cuando no se asigna valor) y luego ceros.

- este es el código:

#include
#include
#include
#include
#include

int main()
{
char entradaLongitud[2];
char *endptr;
printf("Indica la longitud del arreglo(máx 1 cifra)\n");
// scanf("%d", &longitud);
fgets(entradaLongitud, sizeof(entradaLongitud),stdin);
int salidaLongitud = strtol(entradaLongitud, &endptr, 10);
int arreglo[salidaLongitud];
int i;
for(i=0; i

etern00b
Desconectado/a
se unió: 05/02/2022

Vaya, parece que el codigo ha hecho que el mensaje no se muestre entero en la web del foro, no se si en los emails tambien.

Disculpad las molestias.

Ademas me acabo de dar cuenta que en la parte de abajo sigue con scanf, asi que este no debe ser el ultimo código, ya que no está "sustituido" por fgets + strtol.

------- Original Message -------
On Sunday, September 25th, 2022 at 11:24, lsdi.miguel <name at domain> wrote:

> Hola,
> finalmente vengo a preguntar:
> -¿que significa *nptr y **endptr? ¿son caracteres sin mas?
> - tengo un código que he escrito mirando y probando, que pretende pedir al usuario la longitud de un arreglo(array) y los valores para cada componente. Según he leido, al usar fgets junto a strtol evitamos que se puedan escribir caracteres cuando pedimos cifras, etc y de ser asi devuelve 0. Pero cuando introduzco caracteres en la longitud del array no devuelve nada, cuando introduzco caracteres en los valores, devuelve algunos números grandes (parecido a cuando no se asigna valor) y luego ceros.
>
> - este es el código:
>
> #include
> #include
> #include
> #include
> #include
>
> int main()
> {
> char entradaLongitud[2];
> char *endptr;
> printf("Indica la longitud del arreglo(máx 1 cifra)\n");
> // scanf("%d", &longitud);
> fgets(entradaLongitud, sizeof(entradaLongitud),stdin);
> int salidaLongitud = strtol(entradaLongitud, &endptr, 10);
> int arreglo[salidaLongitud];
> int i;
> for(i=0; i {
> printf("Introduce el valor del arreglo [%d] : ",i);
> scanf("%d", &arreglo[i]);
> }
> printf("Los elementos del arreglo son : \n");
> for(i=0; i printf("%d\t", arreglo[i]);
> printf("\n");
> }
>
> **Cualquier información para comprender este tipo de "programillas" es altamente apreciado, ya que en stackoverflow y otros lugares que he ido consultando, son casos mas complicados, diferentes, en inglés, o simplemente no esplican algunos conceptos que no tengo claros.
>
> Muchas gracias de antemano.

Parodper
Desconectado/a
se unió: 05/01/2020

> ¿que significa *nptr y **endptr?

Para esto es muy útil consultar las páginas del manual con el comando «man strtol» (o, para algunas funciones, «man -L es función» para la página en castellano), la página web https://man7.org/linux/man-pages/ (strtol está en la sección 3) o la página https://www.gnu.org/software/libc/manual/html_mono/libc.html, para una descripción más completa.

La función strtol toma tres parámetros: nptr (que apunta a la cadena que hay que convertir), endptr (que apunta a la parte de la cadena de entrada que no se convirtió en entero) y base (en que base está el número). Pongamos por ejemplo la cadena "123 asdf". En este caso, strtol cogería el "123", devolvería el int 123, y dejaría endptr apuntando a " asdf"; porque es ahí donde terminó de convertir.

> tengo un código que he escrito mirando y probando, que pretende pedir al usuario la longitud de un arreglo(array) y los valores para cada componente. Según he leido, al usar fgets junto a strtol evitamos que se puedan escribir caracteres cuando pedimos cifras, etc y de ser asi devuelve 0.

No se si tienes experiencia en algún otro lenguaje de programación, pero en C hay dos maneras de gestionar los errores: Mirando que devuelve la función, y la variable errno (para esto se necesita un #include ), para casos como el de strtol, en el que no puedes devolver un error. En este caso, lo que habría que hacer es, después del strtol, comprobar que el valor de errno siga siendo 0, y en caso contrario terminar el programa. Si no, se van a ir propagando los errores por el resto del código, y, en el mejor de los casos, te va a saltar algún error en otra parte del programa.

> Pero cuando introduzco caracteres en la longitud del array no devuelve nada, cuando introduzco caracteres en los valores, devuelve algunos números grandes (parecido a cuando no se asigna valor) y luego ceros.

Esto es por lo que hacen las funciones como scanf al leer texto. Estas funciones van sacando del búfer de entrada todo el texto que necesiten, y lo que no cogen lo dejan en el búfer, para las siguientes funciones. Por ejemplo, si tienes el código:

int a;
char *b;

scanf("%d", &a);
scanf("%s", b);

E introduces el texto:

abc 12 xyz

Lo que ocurre es que el primer scanf coge la primera cadena, hasta el primer espacio, y se para, al no encontrar un número. Entonces, el siguiente scanf coge la cadena "abc 12 xyz", sin modificar, al no haber encontrado un número el primer scanf, y saca el "abc".

En el caso del bucle, le introduces un "a" al primer scanf, que no lo coge al estar buscando un número, y se lo pasa al siguiente scanf del bucle, que tampoco lo coge al no ser un número; y así sucesivamente. Lo que habría que hacer, según indican en «man scanf», sección «RETURN VALUE»; es comprobar que el valor que devuelve cada scanf sea igual al número de variables que se pasan, en este caso 1; y en caso contrario seguir pidiendo el mismo número.

Por cierto, voy a intentar copiar y pegar el código desde el foro:

#include
#include
#include

int main()
{
char entradaLongitud[2];
char *endptr;

printf("Indica la longitud del arreglo(máx 1 cifra)\n");
// scanf("%d", &longitud);
fgets(entradaLongitud, sizeof(entradaLongitud),stdin);

int salidaLongitud = strtol(entradaLongitud, &endptr, 10);
int arreglo[salidaLongitud];
int i;

for(i=0; i < salidaLongitud; i++)
{
printf("Introduce el valor del arreglo [%d] : ",i);
scanf("%d", &arreglo[i]);
}

printf("Los elementos del arreglo son : \n");
for(i=0; i < salidaLongitud; i++)
{
printf("%d\t", arreglo[i]);
printf("\n");
}
}

etern00b
Desconectado/a
se unió: 05/02/2022

Muchas gracias parodper, el man -L creo que me va a ser muy util, ya que muchas veces no entiendo del todo el manual en ingles. Voy a revisar todo lo que me comentas poco a poco, ya que la poca experiencia que pueda tener en otros lenguajes, por ejemplo python son igual de escasos que en C y probablemente con lagunas por doquier.

Per aspera add astra.