Reputation: 558
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;
}
Upvotes: 1
Views: 868
Reputation: 85887
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).
Upvotes: 1