954,492 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

mimic fgets without including stdio.h

the problem is if you increase buff size and also change the buff size in a3_fgets_2 function call to more than 15, the program will run in an infinite loop, Can anybody tell me why?

Thanks

#include<unistd.h>
#include<string.h>

char * a3_fgets ( char * str, int num, int fd );
char * a3_fgets_2 ( char * str, int num, int fd );

int main(int argc, char **argv){
	char buff[15];
	
/*
	while(fgets(buff, 256, stdin))
		printf("%s", buff);
	puts("\n================================");
*/
	
/*
	while(a3_fgets(buff, 5, 0) != NULL)
		printf("%s", buff);
	puts("\n================================");
*/
	
	while(a3_fgets_2(buff, 15, 0) != NULL){
		write(1, buff, strlen(buff));
	}
	puts("\n================================");
	
	return 0;
}

char * a3_fgets ( char * str, int num, int fd ){
	char buffer;
	int i = 0;
	
	while(i < num-1 && read(fd, &buffer, 1) != 0){
		str[i++] = buffer;
		if(buffer == '\n')
			break;
	}
	if(i == 0)
		return NULL;
	
	str[i] = '\0';
	
	return str;
}

char * a3_fgets_2 ( char * str, int num, int fd ){
	int i = 0;
	
	memset(str, '\0', num);
	
	if(read(fd, str, num-1) == 0)
		return NULL;
	
	while(i < num-1){
		if(str[i++] == '\n')
			break;
	}
	lseek(fd, i-(num-1), SEEK_CUR);
	
	str[i] = '\0';
	
	return str;
}


This is the data file that I use to check the program(its code, but I use it as input to the first program. Using input redirection)

char buffer[1];
int readVal = 0;
int i = 0;

while(i < num-1){
readVal = read(fd, buffer, 1);
if(i == 0 && readVal == 0)
return NULL;
else if(readVal == 0)
break;
str[i++] = buffer[0];
if(buffer[0] == '\n' || readVal == 0)
break;
}
str[i] = '\0';

return str;

efronefron
Light Poster
35 posts since Jan 2011
Reputation Points: 10
Solved Threads: 0
 

I don't like the function at all. It would be better IMO to read the file a character at a time and watch for the \n rather than reading an entire buffer, finding the \n and seeking back to reset the file pointer. Much less work.

WaltP
Posting Sage w/ dash of thyme
Moderator
10,505 posts since May 2006
Reputation Points: 3,348
Solved Threads: 944
 
I don't like the function at all. It would be better IMO to read the file a character at a time and watch for the \n rather than reading an entire buffer, finding the \n and seeking back to reset the file pointer. Much less work.

You may not like the function but there are much less system calls made by the function, which makes it noticeably faster with huge input.

So, can you see what is wrong with the program?

efronefron
Light Poster
35 posts since Jan 2011
Reputation Points: 10
Solved Threads: 0
 
So, can you see what is wrong with the program?


I'd wager that it has something to do with your math. You're using the size of the buffer rather than the number of extracted characters to calculate the seek offset. Compare and contrast:

char *a3_fgets_2(char *str, int num, int fd)
{
    int n = read(fd, str, num - 1);
    int i = 0;
    
    if (n <= 0)
        return NULL;

    while (i < n) {
        if (str[i++] == '\n')
            break;
    }
    
    lseek(fd, i - n, SEEK_CUR);
    str[i] = '\0';

    return str;
}
Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

Yes it works perfectly, I got what you mean, thanks a lot :D
I was trying to solve this for almost 12 hours straight couldnt find the answer.
Thanks again!

efronefron
Light Poster
35 posts since Jan 2011
Reputation Points: 10
Solved Threads: 0
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: