How to read strings of a structure passed by reference

2

This is my Structure

typedef struct{
    char Nombre[20];
  }Cliente;

And they ask me for a function that captures the name by means of the structure and performs this function

 void Captura_cliente(Cliente *client){
     printf("Escriba el nombre: \n");
     scanf("%s",client->Nombre);
  } 

I'm reading a book and it says that when you read strings you can write the scanf ("% s", var); no need to use the & but I have doubts because in several programs that I did in class we used the & for reading strings.

What is the correct way to read the strings?

    
asked by Moises 20.12.2018 в 10:19
source

3 answers

1

One possible way, as you are doing, is to use scanf( ) and using the "%s" as the format. In this way, to the function scanf( ) you have to pass a pointer to a buffer or memory area in which you can write the read characters.

If we are using a formation, whose size is known at compile time, and knowing that in C a formation decays to a pointer type, it is enough to do

#include <stdio.h>

int main( void ) {
  char buffer[100];
  scanf( "%s", buffer );
  printf( "%s", buffer );

  return 0;
}

If the training is inside of a struct , then equal:

struct dummy {
  char buffer[100];
};

int main( void ) {
  struct dummy d;
  scanf( "%s", d.buffer );
  printf( "%s", d.buffer );

  return 0;
}

What if we pass the struct as a pointer? In that case, what interests us is the relative displacement within of the struct . The final address we are looking for, in which to write, is dirección_base + dirección_relativa . With which, we open a range of options and possibilities, to which more interesting:

  • Using the pointer and adding the relative offset . We can use the standard function offsettof( ) for it, contained in <stddef.h> :

    scanf( "%s", (char *)( ptr + offsetof( struct dummy, buffer ) ) );
    
  • Using the syntactic sugar that C offers us to access members of struct through its pointer, which makes it more nice visually. Notice that we are actually doing exactly the same as in the previous case.

    scanf( "%s", ptr->buffer );
    
  • If, as in the case above, the relative displacement is 0 , then we can abbreviate the subject: -)

    scanf( "%s", (char *)( ptr ) );
    
answered by 20.12.2018 / 11:46
source
3

A scanf() must be passed as the second parameter (or terecero, etc. if there is more than one) a memory address, because it is in that direction where it will leave the data reccogido keyboard.

When you read an integer variable, or float, it is usual to use &variable to get the memory address where that variable is, and pass that address to scanf() .

When you read strings, the most usual thing is to have a pointer pointing to a memory area where you intend to read the string (although this is not your case), for example:

char *nombre;
nombre = malloc(20);  // Reservar sitio para 20 caracteres

In this case, since nombre is a pointer, you would call scanf() with:

scanf("%s", nombre);

then the value of nombre already points to the area where we want to leave the data. You should not use &nombre here, because in that case the data would be saved in the pointer , instead of in the direction pointed to by the pointer . Of course that would be wrong, since the pointer is not a place to store characters.

In your case, what you have is an array of char:

char nombre[20];

It happens that in C, the name of an array as part of an expression is equivalent to the memory address where the first element of that array is. That is, if you put:

scanf("%s", nombre);

the compiler sees:

scanf("%s", &nombre[0]);

and in that sense we can omit the & in front of an array when we want to obtain its address.

Moreover, scanf("%s", &nombre) , if you put purist, it is incorrect from the point of view of the types, since &nombre gives us the address of the array instead of the address of the first element of the array. Although both are the same address at the end, their types do not match, since &nombre is a pointer to array of characters , while &nombre[0] (or nombre to dry) is a < em> pointer to character .

Note on security .

Using scanf() to read strings is insecure because typically your string has a limited size (20 in this case), but at scanf() you do not tell the maximum number of characters to read. The user could enter more than 20 with unpredictable results. It is recommended to use fgets() instead, which does allow you to specify a maximum number of characters to read, like this:

fgets(nombre, 20, stdin);
    
answered by 20.12.2018 в 11:20
0

When you create arrays or strings, the name of that variable refers to the address, so you can use both, for example:

#include <stdio.h>

void main(){

    char cadena[4] = "uno";

    printf("Dirección cadena %x\n", cadena);
    printf("Dirección &cadena %x\n", &cadena);
    printf("Dirección &(cadena[0]) %x\n", &(cadena[0]));

    printf("Valor cadena %s\n", cadena);
    printf("Valor &cadena %s\n", &cadena);
    printf("Valor &(cadena[0]) %s\n", &(cadena[0]));


}

It will print the following:

Dirección cadena 30b39710
Dirección &cadena 30b39710
Dirección &(cadena[0]) 30b39710
Valor cadena uno
Valor &cadena uno
Valor &(cadena[0]) uno
    
answered by 20.12.2018 в 11:21