Hi,
Everybody, i have a situation where i receive data in a buffer and i
read the buffer and store it in a linked list, one the problem is i can
receive any number of data... so i might run out of the memory, and the
utiltimate aim is to return the header of the linked list to the caller
of the function, so that they can process the list and do the concerned
thing.
ht list is like this
struct list
{
int date;
struct *list
};
so having seen this limitation, is there any way of work around,
where i still can return the
header of the node to the caller and don't
run out of memory simultaneously.
When I build a list, I keep track of both ends,
the head and the tail.
You can use the tail value to indicate node allocation failure.
/* BEGIN line2string.c */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
struct list_node {
struct list_node *next;
void *data;
};
int line2string(FILE *fp, char **line, size_t *size);
void list_free(struct list_node *node, void (*free_data)(void *));
void list_fprint(FILE *stream, struct list_node *node);
struct list_node *
allocate_string_node(struct list_node **head,
struct list_node *tail,
char *data);
int main(void)
{
struct list_node *head, *tail;
int rc;
char *buff_ptr;
size_t buff_size;
long unsigned line_count;
puts(
"\nThis program makes and prints a list of all the lines\n"
"of text entered from the standard input stream.\n"
"Just hit the Enter key to end,\n"
"or enter any line of characters to continue."
);
tail = head = NULL;
line_count = 0;
buff_size = 0;
buff_ptr = NULL;
rc = line2string(stdin, &buff_ptr, &buff_size);
while (rc > 1) {
++line_count;
tail = allocate_string_node(&head, tail, buff_ptr);
if (tail == NULL) {
break;
}
puts(
"\nJust hit the Enter key to end,\n"
"or enter any other line of characters to continue."
);
rc = line2string(stdin, &buff_ptr, &buff_size);
}
switch (rc) {
case EOF:
if (buff_ptr != NULL && strlen(buff_ptr) > 0) {
puts("rc equals EOF\nThe string in buff_ptr is:");
puts(buff_ptr);
++line_count;
tail = allocate_string_node(&head, tail, buff_ptr);
}
break;
case 0:
puts("realloc returned a null pointer value");
if (buff_size > 1) {
puts("rc equals 0\nThe string in buff_ptr is:");
puts(buff_ptr);
++line_count;
tail = allocate_string_node(&head, tail, buff_ptr);
}
break;
default:
break;
}
printf("%lu lines of text were entered.\n", line_count);
puts("They are:\n");
list_fprint(stdout, head);
list_free(head, free);
puts("\nThe list has been freed.\n");
if (line_count != 0 && tail == NULL) {
puts("Node allocation failed.");
puts("The last line enetered didnt't make it onto the list:");
puts(buff_ptr);
}
free(buff_ptr);
puts("\nThe line buffer has been freed.\n");
return 0;
}
int line2string(FILE *fp, char **line, size_t *size)
{
int rc;
void *p;
size_t count;
count = 0;
for (rc = getc(fp); rc != EOF; rc = getc(fp)) {
++count;
if (count + 2 > *size) {
p = realloc(*line, count + 2);
if (p == NULL) {
if (*size > count) {
(*line)[count] = '\0';
(*line)[count - 1] = (char)rc;
} else {
ungetc(rc, fp);
}
count = 0;
break;
}
*line = p;
*size = count + 2;
}
if (rc == '\n') {
(*line)[count - 1] = '\0';
break;
}
(*line)[count - 1] = (char)rc;
}
if (rc != EOF) {
rc = count > INT_MAX ? INT_MAX : count;
} else {
if (*size > count) {
(*line)[count] = '\0';
}
}
return rc;
}
void list_free(struct list_node *node, void (*free_data)(void *))
{
struct list_node *next_node;
while (node != NULL) {
next_node = node -> next;
free_data(node -> data);
free(node);
node = next_node;
}
}
void list_fprint(FILE *stream, struct list_node *node)
{
while (node != NULL) {
fputs(node -> data, stream);
putc('\n', stream);
node = node -> next;
}
}
struct list_node *
allocate_string_node(struct list_node **head,
struct list_node *tail,
char *data)
{
struct list_node *node;
node = malloc(sizeof *node);
if (node != NULL) {
node -> next = NULL;
node -> data = malloc(strlen(data) + 1);
if (node -> data != NULL) {
if (*head == NULL) {
*head = node;
} else {
tail -> next = node;
}
strcpy(node -> data, data);
} else {
free(node);
node = NULL;
}
}
return node;
}
/* END line2string.c */