-2

After having so many problems using the scanf() function I decided to search for an alternative to read whole strings (and by whole strings I mean words mixed with white spaces and numbers etc, until a \n is found) from the keyboard. I stumbled upon an interesting bit of code here on stackoverflow. So I changed that code to be more dynamic, I wanted to allocate memmory after a char input from the keyboard. I got it to work but only with char **a as an argument and ,in main(), I would call it like this read(&w);.My idea is to create an argument-less function so that I can use it without having to declare a variable char *w each time I need to read a string. Here's the code I got:

char *read(char **a) {
int i = 0;

while (1) {
    *a = (char *)realloc(*a, (i + 1) * sizeof(char));
    scanf("%c", &(*(*a + i)));

    if ( *(*a+i) == '\n')
        break;
    else 
        i++;
}
*(*a+i) = '\0';
return *a;}

Now i'm trying to modify this function to take no arguments but I'm getting write/read access violation errors :

char *read2() {
int i = 0;
char **a = NULL;

while (1) {

    *a = (char *)realloc(*a, (i + 1) * sizeof(char)) // Error here
        scanf("%c", &(*(*a + i)));
        if (*(*a + i) == '\n') { break; }
        else { i++; }
}
    *(*a + i) = '\0';
return *a;}

Thanks in advance

Ferro
  • 35
  • 7
  • What, precisely, is your question? – Robᵩ Mar 15 '17 at 22:06
  • POSIX has a `getline()` function that does what you want. Can you use that? – Barmar Mar 15 '17 at 22:09
  • Are you trying to re-invent the 1000th version of `fgets` or `getline`? And using the name`read` is a very bad idea, because that is commonly already defined by your platforms system library. – too honest for this site Mar 15 '17 at 22:10
  • Well I was trying to create an argument-less version of this `read()` function. I can´t seem to make it through all the` *` and pointers . Seemed like a good practice but I didn´t remember about the `getline()` or the `fgets()` functions. I'll try them ,thanks. – Ferro Mar 15 '17 at 22:21

2 Answers2

1

The problem with your function is that you've declared too many levels of indirection. You declare

char **a = NULL;

and then assign to *a. But since a == NULL, this indirects through a null pointer, which is undefined behavior.

You don't need an extra level of indirection for a local variable, that's only needed for a parameter so you can update the caller's variable.

You should also check for EOF when reading. Instead of using scanf(), use getc().

char *read2() {
    int i = 0;
    char *a = NULL;

    while (1) {
        a = (char *)realloc(a, (i + 1) * sizeof(char));
        int c = getc(stdin);
        if (c == '\n' || c == EOF) {
            break;
        } else {
            a[i] = c;
            i++;
        }
    }
    a[i] = '\0';
    return a;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • wow , levels of indirection , not knowing this makes me feel like a complete newbie in C but thanks @Barmar it worked wonderfully. Thank you all – Ferro Mar 15 '17 at 22:28
0

You really don't need to roll your own, just use fgets().

Also if you MUST roll your own getline() function, do it with fgetc() instead.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97