vukstudent
vukstudent

Reputation: 23

getting a pointer filled with input from stdin and using the pointer as input for a function

I have the following problem: I need to read a string from stdin and must put it in an pointer. Then I must use this pointer as input for a function that isn't in the main function.

This is what I tried so far

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define LINE_LENGTH 50
     
    void print (char*text)
    {
        printf("%c", *text);
     
    }
     
    int main (void)
    { 
    char*keyboard;
    fgets(keyboard, LINE_LENGTH, stdin);   
     
     
    print (*keyboard);
     
     
    return 0;
    }

Thank you very much for reading this and thank you very much for answering.

Upvotes: 0

Views: 401

Answers (2)

mrbrobro
mrbrobro

Reputation: 26

Thinking more concretely about what is going on should help.

An object is a continuous set of bits in memory. A variable is a name which is associated with an object. A type is a more abstract idea which is associated with a variable, and can be "applied" to an object.

A pointer is a type which conveys the idea: "treat this object as a memory address". A pointer can further convey a type that can be applied to the object at that address.

Memory can be allocated in different ways in different areas (statically, on the stack, or in some managed area, etc.).

So, when you declared char*keyboard in main(), you instructed the compiler to allocate an object on the stack, with the size of a memory address (e.g. 32 bits for x86 or 64 bits for x86_64), and associate it with the variable name keyboard. The value stored in that object will then be treated as an address when it is accessed through keyboard. If that address is dereferenced using keyboard, the (probably different) object at the address stored in the object associated with keyboard will be accessed, and treated as a char.

Here is a diagram to illustrate:

...
       keyboard
-------[0x1234]---------
...        \
...         \
...          v   
-------------[?]------
...

If the object associated with keyboard contains the value 0x1234, then when it is treated as a char * and dereferenced, the character at location 0x1234 will be accessed, shown as ?.

fgets() will write characters to memory, starting at the address provided as its first argument. So it could store up to LINE_LENGTH characters, starting at the address stored in the object associated with keyboard, in your code.

But no value has been assigned to keyboard.

That means that the fgets() call could write characters to an undefined location in memory.

If you want to write up to 50 characters somewhere, you first must establish a safe place to write them. You could do this by allocating 50 characters on the stack:

int main...
{
    char buffer[50];
    ...

or allocating static space for them:

char buffer[50];
...
int main...
{
    ...

Or by allocating some space in managed memory for them:

int main...
{
    char *buffer_ptr = malloc(50 * sizeof(char));
    if (!buffer_ptr) ...
    ...
    free(buffer_ptr);

You could then point keyboard to that storage by assigning the address of the first character to it:

    keyboard = &buffer[0];
    /* or */
    keyboard = buffer;

    /* or for the malloc() example case: */
    keyboard = buffer_ptr;

But in this case, you could probably just use buffer or buffer_ptr directly.


Thinking about it more concretely like this should hopefully clear up some confusion, but it might help to point out a couple more things:

Your print() function takes a char * argument, but your code passes a char to it. This is because keyboard, which is a pointer to a char, has been dereferenced, yielding a char.

If the intent is to print only the first character of the memory which has been written to by the fgets() call, then either accessing that character and then passing it directly, or passing a pointer to it and dereferencing it within print() would work, but not both. If the intent is to print the entire string which has been read, then the pointer could be passed (without dereferencing it), but the format argument passed to printf() should contain %s for the string, and a pointer to that string should be passed to be converted by it.

Upvotes: 0

Oka
Oka

Reputation: 26355

char *keyboard; is an uninitialized pointer. It reserves no memory for a string.

printf("%c", *text); would print the first character of a string. %s is the format specifier for printing entire strings, and expects a char *.

Try using an array, which automatically reserves memory on the stack. Arrays decay to pointers when passed to functions.

#include <stdio.h>

#define LINE_LENGTH 50

void print(char *text)
{
    printf("%s", text);
}

int main(void)
{
    char keyboard[LINE_LENGTH];

    if (fgets(keyboard, LINE_LENGTH, stdin))
        print(keyboard);
}

Upvotes: 1

Related Questions