S
santosh
I've written the following function to return a string of arbitrary
length from stdin. So far, it seems to work as it should. Are there any
unportable assumptions and/or logical errors in the code? Would it be
better to return the length of the string? Or an integer value
indicating success or failure, (the type of failure too)?
Thanks.
#include <stdio.h>
#include <stdlib.h>
#define IBUFSIZ 32
#define BUF_DELTA IBUFSIZ
#define BUF_INP_DIFF 3
#define BUF_CROP_THRESHOLD (BUF_INP_DIFF + 1)
char *getl_stdin(void);
char *getl_stdin(void) {
char *inp_p = NULL, *inp_p_cpy;
int nc, buffer_exists = 0, no_buf_crop = 0;
size_t curr_bufsiz = 0, curr_inpsiz = 0;
while((nc = fgetc(stdin)) != EOF) {
if((curr_bufsiz - curr_inpsiz) < BUF_INP_DIFF) {
curr_bufsiz += BUF_DELTA;
if((inp_p = realloc(inp_p, curr_bufsiz)) == NULL) {
if(buffer_exists) {
inp_p = inp_p_cpy;
inp_p[curr_inpsiz] = nc;
inp_p[curr_inpsiz + 1] = '\0';
++curr_inpsiz;
curr_bufsiz -= BUF_DELTA;
no_buf_crop = 1;
break;
}
else
break;
}
else {
inp_p_cpy = inp_p;
inp_p[curr_inpsiz] = nc;
++curr_inpsiz;
if(!buffer_exists)
buffer_exists = 1;
else {
if(nc == '\n') {
inp_p[curr_inpsiz] = '\0';
++curr_inpsiz;
break;
}
}
}
}
else {
inp_p[curr_inpsiz] = nc;
++curr_inpsiz;
if(nc == '\n') {
inp_p[curr_inpsiz] = '\0';
++curr_inpsiz;
break;
}
}
}
if(inp_p != NULL && !no_buf_crop) {
if((curr_bufsiz - curr_inpsiz) >= BUF_CROP_THRESHOLD) {
if((inp_p = realloc(inp_p, curr_inpsiz)) == NULL)
inp_p = inp_p_cpy;
else {
inp_p_cpy = inp_p;
curr_bufsiz = curr_inpsiz;
}
}
}
return inp_p;
}
int main(void) {
char *input = NULL;
int main_RV = 0;
puts("Enter a line of text:");
input = getl_stdin();
if(input == NULL) {
puts("getl_stdin() returned NULL.");
main_RV = EXIT_FAILURE;
}
else
printf("You wrote:\n%s\n", input);
return main_RV;
}
length from stdin. So far, it seems to work as it should. Are there any
unportable assumptions and/or logical errors in the code? Would it be
better to return the length of the string? Or an integer value
indicating success or failure, (the type of failure too)?
Thanks.
#include <stdio.h>
#include <stdlib.h>
#define IBUFSIZ 32
#define BUF_DELTA IBUFSIZ
#define BUF_INP_DIFF 3
#define BUF_CROP_THRESHOLD (BUF_INP_DIFF + 1)
char *getl_stdin(void);
char *getl_stdin(void) {
char *inp_p = NULL, *inp_p_cpy;
int nc, buffer_exists = 0, no_buf_crop = 0;
size_t curr_bufsiz = 0, curr_inpsiz = 0;
while((nc = fgetc(stdin)) != EOF) {
if((curr_bufsiz - curr_inpsiz) < BUF_INP_DIFF) {
curr_bufsiz += BUF_DELTA;
if((inp_p = realloc(inp_p, curr_bufsiz)) == NULL) {
if(buffer_exists) {
inp_p = inp_p_cpy;
inp_p[curr_inpsiz] = nc;
inp_p[curr_inpsiz + 1] = '\0';
++curr_inpsiz;
curr_bufsiz -= BUF_DELTA;
no_buf_crop = 1;
break;
}
else
break;
}
else {
inp_p_cpy = inp_p;
inp_p[curr_inpsiz] = nc;
++curr_inpsiz;
if(!buffer_exists)
buffer_exists = 1;
else {
if(nc == '\n') {
inp_p[curr_inpsiz] = '\0';
++curr_inpsiz;
break;
}
}
}
}
else {
inp_p[curr_inpsiz] = nc;
++curr_inpsiz;
if(nc == '\n') {
inp_p[curr_inpsiz] = '\0';
++curr_inpsiz;
break;
}
}
}
if(inp_p != NULL && !no_buf_crop) {
if((curr_bufsiz - curr_inpsiz) >= BUF_CROP_THRESHOLD) {
if((inp_p = realloc(inp_p, curr_inpsiz)) == NULL)
inp_p = inp_p_cpy;
else {
inp_p_cpy = inp_p;
curr_bufsiz = curr_inpsiz;
}
}
}
return inp_p;
}
int main(void) {
char *input = NULL;
int main_RV = 0;
puts("Enter a line of text:");
input = getl_stdin();
if(input == NULL) {
puts("getl_stdin() returned NULL.");
main_RV = EXIT_FAILURE;
}
else
printf("You wrote:\n%s\n", input);
return main_RV;
}