0

I have this peace of C Programming code to take multiple literal strings from the user and store each address to each pointer and print out the value

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *ptr[3];
    int i = 0;

    for (; i < 3; i++) {
        printf("ptr_%d:  ", i + 1);
        fgets(ptr[i], 15, stdin);
        ptr[i][strlen(ptr[i]) - 1] = 0;
        puts(ptr[i]);
    }

    return 0;
}

However, only the first one is printed. Here is the output

ptr_1:  first line
first line
Segmentation fault

[Program finished]

I want the same result that is produced Here

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *ptr[] = {
        "first line", 
        "second line", 
        "third line"
    };

    puts(ptr[0]);
    puts(ptr[1]);
    puts(ptr[2]);
        
    return 0;
}

output

first line
second line
third line

[Program finished]

Thanks in advance

3
  • 7
    fgets needs an actual buffer of bytes to put the input into. Right now you're just handing it an uninitialized Pointer, which means it's going to write the input bytes to random places in memory Commented Mar 15, 2022 at 23:42
  • 3
    need to allocate for char *ptr[3] Commented Mar 15, 2022 at 23:47
  • 1
    Or declare as an array of arrays: char ptr[3][15] (though then the name is no longer very approriate). Commented Mar 15, 2022 at 23:54

3 Answers 3

3
fgets(ptr[i], 15, stdin);

You've declared an array of three pointers:

char *ptr[3];

But none of those actually point to buffers of memory.

You can either create those buffers automatically:

char ptr[3][15];

Or dynamically with malloc.

char *ptr[3];

for (size_t i = 0; i < 3; i++) {
    ptr[i] = malloc(15);
}

If you do this, make sure to free the memory you've allocated.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this made it work. I was missing the allocation part. Marking as solved.
1

If you are running gcc (with glibc 2.7 or greater), you can use the m modifier with scanf to allocate memory:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *ptr[3];

    for (i = 0; i < 3; i++) {
        printf("ptr_%d:  ", i + 1);
        while (scanf(" %m[^\n]",&ptr[i]) != 1)
            printf("Try again: ");
        puts(ptr[i]);
    }

    for (; i < 3; i++)
        free(ptr[i]);
    return 0;
}

And be sure to free the memory when you are done with it.

2 Comments

check errno to make sure scanf allocated successfully
@long.kl The OP was using fget, so %m[^\n] gives the most similar behavior (spaces allowed)
0

You'd probably want to put the scanf section of this code into a function but here is the smallest change to your existing sample that should work.

$ cat allocinput.c 

#include <stdio.h>
#include <string.h>

#define MAX_LEN 80

int main(int argc, char *argv[])
{
        char c;
    char ptr[3][MAX_LEN];
    int i = 0;

for (;i<3;i++) {
    printf("ptr_%d:  ", i + 1);
    // could overflow if the user types more than MAX_LEN characters
    char *p = ptr[i];
    while (scanf("%c", &c) && (p - ptr[i] < MAX_LEN)) {
        if (c == '\n') break;
        *p++ = c;
        *p = 0;
        }
    puts(ptr[i]);
}

return 0;}
$ gcc -Wall allocinput.c 
$ ./a.out
ptr_1:  first line
first line
ptr_2:  second line
second line
ptr_3:  third line
third line
$ 

P.S. I recommend astyle to clean up the formatting:

$ astyle allocinput.c 
Formatted  /tmp/overflow/allocinput.c
$ cat allocinput.c

#include <stdio.h>
#include <string.h>

#define MAX_LEN 80

int main(int argc, char *argv[])
{
    char c;
    char ptr[3][MAX_LEN];
    int i = 0;

    for (; i<3; i++) {
        printf("ptr_%d:  ", i + 1);
        // could overflow if the user types more than MAX_LEN characters
        char *p = ptr[i];
        while (scanf("%c", &c) && (p - ptr[i] < MAX_LEN)) {
            if (c == '\n') break;
            *p++ = c;
            *p = 0;
        }
        puts(ptr[i]);
    }

    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.