Porque no puedo pasarle la direccion de la cadena? strtol

Iniciado por 7emiliosk8, 11 Febrero 2017, 22:39 PM

0 Miembros y 1 Visitante están viendo este tema.

7emiliosk8

Hola tengo este codigo, se supone que la funcion strtol recibe u puntero doble, pero se supone que la cadena "prueba" es un puntero que apunta  ala direccion de memoria del primer elemento de la cadena, o sea es como si le estuviera pasando la dir de un puntero, no se si me explico , de todos modos no me funciona :/ da un warning

#include <stdio.h>
#include <stdlib.h>

int main()
{
char str[30] = "2030300 This is test";
char prueba[20];
char *ptr;
long ret;
printf("\nLa cadena inicial es: %c%s%c\n",34,str,34);

/*  long int strtol(const char *str, char **endptr, int base)
//strtol converts the initial part of the string in str to a long int value according to the given base.
whose value is set by the function to the next character in str after the numerical value.
*/
ret = strtol(str, &ptr, 10);
printf("\nThe number(unsigned long integer) is %ld\n", ret);
printf("String part is |%s|\n", ptr);

ret = strtol(str, &prueba, 10);
printf("\nProbando: %c%s%c\n",34,prueba,34);

  return(0);

class_OpenGL

Lo que no puedes hacer es pasarle la dirección de un arreglo. Conceptualmente no puedes porque no puedes modificar la dirección de un arreglo.

Nota por si quieres sumar conocimientos (conocimientos obtenidos experimentalmente con el compilador MinGW y MinGW-w64): físicamente no puedes porque un arreglo no guarda una dirección de memoria. En realidad, un arreglo no se almacena en memoria. Al referirte a un elemento del arreglo, el compilador sabe la dirección virtual del primer elemento del arreglo, y por tanto sabe la del elemento. Cuando intentas acceder a la dirección de un arreglo, la dirección que obtienes es la misma dirección del primer elemento del arreglo. Código que lo demuestra:

#include <stdio.h>

int main() {
  char arreglo[64];
 
  fprintf(stdout, "El arreglo apunta a:        %p\n", arreglo);
  fprintf(stdout, "El arreglo tiene direccion: %p\n", &arreglo);
 
  return 0;
}


Resultado en pantalla:

El arreglo apunta a:        000000000023FE10
El arreglo tiene direccion: 000000000023FE10


Espero que se haya entendido

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

7emiliosk8

Hola gracias por responder, pero con strtol no estoy modificando la direccion del puntero simplemente llenandolo. poniendo caracteres dentro

Ademas yo lei en una parte que decia, "los arreglos se puede decir que son punteros disfrazados"  ya que el nombre de un arreglo es un puntero a la direccion de memoria del primer elemento del arreglo (que es la misma dir del arreglo), es por eso que cuando
si tengo

char prueba[20];
char *p ;

puedo usar %s de la misma forma que en ambos, printf("%s y %s",prueba,p);
porque prueba se comporta como un puntero. me explico ? entonces no entiendo porque aca no se puede pasar la dir de memoria del arreglo

class_OpenGL

Cita de: 7emiliosk8 en 11 Febrero 2017, 23:11 PMHola gracias por responder, pero con strtol no estoy modificando la direccion del puntero simplemente llenandolo. poniendo caracteres dentro

No, una de las cosas que hace strtol es guardarte en la dirección que le pasas la dirección del primer elemento después del número.

Cita de: 7emiliosk8 en 11 Febrero 2017, 23:11 PM"los arreglos se puede decir que son punteros disfrazados"

Eso se dice para facilitar la comprensión de sintaxis de los arreglos, pero la realidad es la que dije. Un arreglo NO es lo mismo que un puntero. Lo único similar entre ellos es su sintaxis.

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

7emiliosk8

Cita de: class_OpenGL en 11 Febrero 2017, 23:16 PM
No, una de las cosas que hace strtol es guardarte en la dirección que le pasas la dirección del primer elemento después del número.

No te entendi eso muy bien amigo, cuando dices "la direccion del primer elemento despues del numero" podrias detallarlo un poco mas, graciass

class_OpenGL

Lo que decía hace esto:

1º Se salta todos los espacios que haya en la cadena que le pasas.
2º Te lee y convierte los digitos del numero hasta que se encuentre uno que no sea dígito o cuando llegas al final de la cadena.
3º Te devuelve, además del número, la dirección del primer elemento que se ha encontrado que no es dígito.

Código de ejemplo:

#include <stdlib.h>
#include <stdio.h>

int main() {
  char numero_str[] = "124lo que sea";
  int numero;
  char *siguiente;
 
  numero = strtol(numero_str, &siguiente, 10);
 
  fprintf(stdout, "El numero convertido: %i\n", numero);
  fprintf(stdout, "Desplazamiento de \"siguiente\" respecto \"numero_str\": %i\n", (int)siguiente - (int)numero_str);
  fprintf(stdout, "Bytes apuntados por \"siguiente\": '%s'", siguiente);
 
  return 0;
}


Salida:

El numero convertido: 124
Desplazamiento de "siguiente" respecto "numero_str": 3
Bytes apuntados por "siguiente": 'lo que sea'


Como ves, strtol te ha convertido bien el número.

Lo que decía es que strtol lee dígitos hasta que se encuentre uno que no lo sea. En nuestro ejemplo ("124lo que sea"), strtol lee carácter a carácter. '1' es dígito, convierte y continúa. '2' es dígito, convierte y continúa. '4' es dígito, convierte y continúa. 'l' no es dígito, por lo que para ahí, y devuelve la dirección (que pertenece al arreglo) del elemento 'l'. Como se puede ver en el segundo fprintf, este elemento es el 3.

Nota un poco más técnica: te puedes fijar en el detalle de que la dirección de "siguiente" menos la del arreglo es 3, lo que quiere decir que "siguiente" apunta a 3 bytes más allá del arreglo, y como el arreglo tiene 14 elementos, eso significa que "siguiente" apunta a un elemento del arreglo. Esto deja claro que no se usa memoria dinámica.

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

7emiliosk8


7emiliosk8

Amigo, mira comente mi codigo, segun lo que tu me explicaste, me podrias decir si esta correcto


#include <stdio.h>
#include <stdlib.h>

int main()
{
char str[30] = "2030300 This is test";

char *ptr;
long ret;
printf("\nLa cadena inicial es: %c%s%c\n",34,str,34);

ret = strtol(str, &ptr, 10); //en simples palabras strtol recibe una cadena que tenga numero y palabra (en ese orden) y el numero que tenga adelante lo retorna como long int, y la palabra siguiente de la cadena la pasa a otra cadena
printf("\nThe number(unsigned long integer) is %ld\n", ret);
printf("String part is |%s|\n", ptr); //ojo que a la cadena le agrego el espacio despues del ..300 This..


//Que pasa si pongo un char ? por la premisa de que el nombre de un arreglo es un puntero a la dir de mmeoria del primer elemento (la misma la dir de todo el arreglo)
char prueba[20];
ret = strtol(str, &prueba, 10);
printf("\nProbando: %c%s%c\n",34,prueba,34);
/* Da error eso se debe a que para empezar porque Conceptualmente no puedes modificar la dirección de un arreglo, ya que strotl lo que hace es
devuelve, además del número, la dirección del primer elemento que se ha encontrado que no es dígito, o sea de vuelve la direccion de "(espacio)", espacio por que antes de "This" hay un espacio.
como un arreglo se comporta ocmo puntero pero No lo es, lo que estaria diciendo es que prueba ahora apunta a la dir de memoria del "espacio" pero no se puede
si es puntero lo que estoy diciendo en el caso de ptr es que ptr apunta a la dir de memoria de "espacio", es decir p= "dir de memoria del "espacio""
*/

  return(0);
}


class_OpenGL

Sabiendo que esto era el error,

char prueba[20];
ret = strtol(str, &prueba, 10);
printf("\nProbando: %c%s%c\n",34,prueba,34);


Está todo bien.

______________________________________________

Si quieres más información de strtol, te aconsejo visitar el siguiente link:

http://www.cplusplus.com/reference/cstdlib/strtol/

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

7emiliosk8

era para saber si estaba bien la logica del porque da ese error XDD pero gracias de todos modos