1

I have a function that read string from stdin which based on answer from here,

    char* ReadString (FILE* f) {
    int chr;
    int n=0;
    size_t size=4;
    char *st=(char*)malloc(size*sizeof(char));
    while (((chr=fgetc(f))!='\n') && (chr != EOF) ) {
        st[n]=chr;
        if (n+1==size)
            st=(char*)realloc(st,(size+=8)*sizeof(char));
        n++;
    }
    st[n]='\0';
return (char*)realloc(st,sizeof(char)*n);
}

Well function works ok, but I found a problem.

int k;
printf("number\n");
scanf("%d",&k);
while (!loop) { //infinite loof for tests
        printf("Name of the file and distination\n");
        fname= ReadString(stdin);
        printf("\"%s\"\n",fname); 
}

Now I will get a segmentation fault. Well the problem, as I understood, is that after scanf, in stdin "\n" is left. If I put

while ( getchar() != '\n' ); // clean stdin 
        fname= ReadString(stdin);

Than I will not get segmentation fault, first string will read perfectly but the next string will not read correctly I will need to enter twice. Why (((chr=fgetc(f))!='\n') && (chr != EOF) ) is not working? -------------Answer--------------

Based on answer below here is the code for future.

char* ReadString (FILE* f) {
    int chr;
    int n=0;
    size_t size=4;
    char *st=(char*)malloc(size);
    bool loop=false;
    while (!loop) {
        while (((chr=fgetc(f))!='\n') && (chr != EOF) ) {
            st[n]=chr;
            if (n+1==size)
                st=(char*)realloc(st,(size+=8)*sizeof(char));
            n++;
        }
        loop=true;
        if (n==0)
            loop=false;
    }
    if (n!=0 )
        st = (char*)realloc(st,sizeof(char)*n);
    st[n]='\0';
return st;
}
Community
  • 1
  • 1
ZeroVash
  • 546
  • 4
  • 20

1 Answers1

1

You have an off-by-one error in your last realloc. Your string stores n+1 bytes but you shorten the allocation to n bytes.

If the first character read is a newline, your loop never runs. Your st string consists of 0 characters, followed by a '\0' terminator, i.e. it uses 1 byte of storage.

But n is 0, so realloc(st,sizeof(char)*n) reallocates it down to 0 bytes, which probably frees the string (or returns a pointer to 0 bytes of memory, which must not be dereferenced).

The easiest solution is to just return st without reallocating it. Otherwise it should be something like return realloc(st, n+1); (but you should really check all of your realloc calls for errors).

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • well you right, Now it read everything. But one more moment now since stdin has "\n", it read first empty string... Is it possible to ignore it? – ZeroVash Jan 22 '17 at 16:24
  • @alex_mike The solution to that is to never use `scanf`. Do all user input by reading whole lines (using `fgets` or your `ReadString`). Once you have a line, you can convert it to a number by using e.g. `atoi` or `sscanf`. – melpomene Jan 22 '17 at 16:26