1

I am trying to make a function that input an unknown length of a string , but I don't want it to return anything I want it to make changes by using the pointer that I pass.

this was my attempt .

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

void get(char * string){

    int size=1;
    string = malloc(size);
    char c;
    int i=0;    

    while(1){
        c = getchar();
        if(c=='\n'){break;}
        string[i] = c;
        i++;
        string = realloc(string , ++size);
    }

    string[i] = '\0';

}

int main(){

    char *buff;

    printf("String :");
    get(buff);
    printf("%s" , buff);


    return 0;
}

the output on my gcc windows os :

PE

1- what is the PE 2- what is wrong here 3- is the c=='\n' line good for the test if the user pressed an enter or should i use EOF or something else

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
random
  • 55
  • 1
  • 9
  • "unknown length of a string" --> No limit at all? How about 1000 or 2 billion? – chux - Reinstate Monica Nov 22 '20 at 17:15
  • (A) Yes you do need to check for EOF, otherwise your program will loop infinitely if the user causes EOF (Ctrl-Z, Ctrl-D depending on system). To handle this properly, your `char c` must be `int` instead, see https://stackoverflow.com/questions/35356322/difference-between-int-and-char-in-getchar-fgetc-and-putchar-fputc/35356684#35356684. (B) You must check that `malloc` and `realloc` succeed before using the pointers they return. – Nate Eldredge Nov 22 '20 at 17:16
  • 1
    (C) C passes arguments by value, so the buffer you so carefully allocated gets lost when `get` returns and the only pointer to it ceases to exist. Assigning to `string` in `get` has no effect on the variable `buff` in `main`. The simplest approach is to return the pointer from `get`; otherwise you will need to pass a pointer to a pointer. – Nate Eldredge Nov 22 '20 at 17:18
  • https://github.com/wrp/examples/blob/main/c/dynamic-array.c – William Pursell Nov 22 '20 at 17:25
  • malloc returns void type (void \*) pointer, string = malloc(size); you should cast it to char pointer like: string = (char \*) malloc(size * sizeof(char \*)); Another issue uncertanity is one of the worst things for programmers, cause your program will not run on a machine that has an infinite memory. I mean you should limit the input to certain length eg. max 2048 characters. – Kozmotronik Nov 22 '20 at 17:26
  • 1
    @Kozmotronik *you should cast it to char pointer like: string = (char *) malloc(size * sizeof(char *))* Not in C. [**Do I cast the result of malloc?**](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Andrew Henle Nov 22 '20 at 17:38
  • May be it is because of habbits. Thanks for the update. – Kozmotronik Nov 22 '20 at 17:49
  • @NateEldredge after i changed '\n' to EOF now when i hit enter it doesnt stop it just go back to line on winodws and it keep getting input – random Nov 22 '20 at 18:46
  • You want to break out of the loop if you get *either* `\n` or EOF. But you probably want to return some indication of the EOF to the caller, so that they don't keep calling `get()` which will never succeed – Nate Eldredge Nov 22 '20 at 18:47

1 Answers1

0

I made a few changes to your code so that it would use the pointer passed to it and handle a possible EOF in the input:

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

void get(char **string){
    char *input = NULL;
    int result, index = 0;

    while (1) {
        result = getchar();
        if (EOF == result) { printf("\n"); break; }
        if ('\n' == result) break;
        char *temp = realloc(input , index + 2);
        if (NULL == temp) {
            perror("Could not increase memory for string");
            if (input) free(input);
            exit(1);
        }
        input = temp;
        input[index++] = (char) result;
    }

    if (input) {
        input[index] = '\0';
        *string = input;
    }
}

int main(void) {
    char *buff = NULL;
    printf("String : ");
    get(&buff);
    if (buff) {
        printf("%s\n" , buff);
        free(buff);
    }
    return 0;
}

Output

$ ./main
String : a short string
a short string
$ ./main
String : input with EOF
input with EOF

Note

I do my best to handle error conditions, but I am not certain I caught everything.

  • @random Because you want to change the address stored in `buff`, you have to pass its address. –  Nov 22 '20 at 18:58
  • and why did you use a temp variable instead of just reallocating in string – random Nov 22 '20 at 19:01
  • @random If the call to `realloc` fails, `*string` still points to valid memory, so we don't want to overwrite the pointer. –  Nov 22 '20 at 19:06