how to copy strings into a linked list?

Discussion in 'C Programming' started by Jim Showalter, Aug 23, 2006.

  1. I'm trying to write code that gets fixed-length strings from the user
    and then stores them in a linked list.

    Here's the definition of my list node:

    struct node {char str[19]; struct node* next; };

    And here is my attempt at Push(), the function that adds new nodes
    to the list:

    void Push(struct node** head, char *str) {

    struct node* newNode = malloc(sizeof(struct node));
    newNode->str = *str;
    newNode->next = *head;
    *head = newNode;
    }

    It worked fine when testing with int's, but I don't know how to get the
    strings copied to "newNode->str".
    Jim Showalter, Aug 23, 2006
    #1
    1. Advertising

  2. In article <i83Hg.730$>,
    Jim Showalter <> wrote:
    >I'm trying to write code that gets fixed-length strings from the user
    >and then stores them in a linked list.


    >Here's the definition of my list node:


    >struct node {char str[19]; struct node* next; };


    >And here is my attempt at Push(), the function that adds new nodes
    >to the list:


    >void Push(struct node** head, char *str) {


    > struct node* newNode = malloc(sizeof(struct node));


    You should check the result of the malloc() -- if there was no
    available memory then malloc() will return a NULL pointer.

    > newNode->str = *str;
    > newNode->next = *head;
    > *head = newNode;
    >}


    >It worked fine when testing with int's, but I don't know how to get the
    >strings copied to "newNode->str".


    strncpy( &newNode->str, str, sizeof(newNode->str) - 1 );
    newNode->str[sizeof newNode->str - 1] = '\0';

    But this code depends upon you really wanting strings -- which is
    to say, null terminated character arrays. You said that you
    have "fixed-length strings": does that mean that there are 18
    used characters and the 19th is for the null, or does that mean
    that there are 19 used characters and you will supply the null
    when needed? The code as written assumes that the null needs
    to be stored and protects itself in case the null was not present
    in the first 18 characters of the input.
    --
    Programming is what happens while you're busy making other plans.
    Walter Roberson, Aug 23, 2006
    #2
    1. Advertising

  3. Walter Roberson wrote:

    > In article <i83Hg.730$>,
    > Jim Showalter <> wrote:


    > You should check the result of the malloc() -- if there was no
    > available memory then malloc() will return a NULL pointer.


    Thanks - I will when I get this function working.

    >
    > strncpy( &newNode->str, str, sizeof(newNode->str) - 1 );
    > newNode->str[sizeof newNode->str - 1] = '\0';


    I think you're close, but now I'm getting:
    "warning: passing argument 1 of ‘strncpy’ from incompatible pointer type"

    >
    > .... does that mean that there are 18
    > used characters and the 19th is for the null, ...


    Yes
    Jim Showalter, Aug 23, 2006
    #3
  4. In article <294Hg.9709$>,
    Jim Showalter <> wrote:
    >Walter Roberson wrote:


    >> .... does that mean that there are 18
    >> used characters and the 19th is for the null, ...


    >Yes


    In that case, you can use strcpy() instead of strncpy(), and
    you can skip the statement that sets the final character to '\0'.
    However, it is -safer- to use strncpy() and set the '\0'
    as that way a small mistake somewhere else in constructing the
    string will not end up potentially trashing random bits of memory.

    >> strncpy( &newNode->str, str, sizeof(newNode->str) - 1 );


    >I think you're close, but now I'm getting:
    >"warning: passing argument 1 of ‘strncpy’ from incompatible pointer type"


    Ugly, why doesn't the warning message just stick to the basic
    character set instead of moving into UTF-8 extensions for whatever
    kind of quotation marks it is using around strncpy ?

    Anyhow, better than &newNode->str would be either
    newnode->str without the &, or else &newNode->str[0]

    --
    Programming is what happens while you're busy making other plans.
    Walter Roberson, Aug 23, 2006
    #4
  5. Jim Showalter

    pete Guest

    Jim Showalter wrote:
    >
    > I'm trying to write code that gets fixed-length strings from the user
    > and then stores them in a linked list.


    In line_to_string.c, string_node is the function
    which copies strings into a linked list.

    /* BEGIN line_to_string.c */

    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <string.h>

    struct list_node {
    struct list_node *next;
    void *data;
    };

    int line_to_string(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 *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;
    while ((rc = line_to_string(stdin, &buff_ptr, &buff_size)) > 1) {
    ++line_count;
    tail = 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."
    );
    }
    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 = 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 = string_node(&head, tail, buff_ptr);
    }
    break;
    default:
    break;
    }
    if (line_count != 0 && tail == NULL) {
    puts("Node allocation failed.");
    puts("The last line entered didnt't make it onto the list:");
    puts(buff_ptr);
    }
    free(buff_ptr);
    puts("\nThe line buffer has been freed.\n");
    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");
    return 0;
    }

    int line_to_string(FILE *fp, char **line, size_t *size)
    {
    int rc;
    void *p;
    size_t count;

    count = 0;
    while ((rc = getc(fp)) != EOF) {
    ++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 *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 line_to_string.c */


    --
    pete
    pete, Aug 24, 2006
    #5
  6. Walter Roberson wrote:

    > In article <294Hg.9709$>,
    > Jim Showalter <> wrote:
    >>Walter Roberson wrote:

    >
    > In that case, you can use strcpy() instead of strncpy(), and
    > you can skip the statement that sets the final character to '\0'.
    > However, it is -safer- to use strncpy() and set the '\0'
    > as that way a small mistake somewhere else in constructing the
    > string will not end up potentially trashing random bits of memory.


    Thanks for the tip. I may stick with strncpy() as you suggest.

    >
    > Anyhow, better than &newNode->str would be either
    > newnode->str without the &, or else &newNode->str[0]


    newnode->str works. Thank you!
    Jim Showalter, Aug 24, 2006
    #6
  7. pete wrote:
    >
    > In line_to_string.c, string_node is the function
    > which copies strings into a linked list.
    >
    > /* BEGIN line_to_string.c */
    >


    Wow - thanks for the routines! And it all compiled without a whimper. That
    should get me over this particular hurdle.

    >
    > /* END line_to_string.c */
    >


    Thanks again, pete!
    Jim Showalter, Aug 24, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Ritchey
    Replies:
    7
    Views:
    476
    emerth
    Jul 10, 2003
  2. Chris Ritchey

    Generating a char* from a linked list of linked lists

    Chris Ritchey, Jul 9, 2003, in forum: C Programming
    Replies:
    7
    Views:
    463
    emerth
    Jul 10, 2003
  3. fool
    Replies:
    14
    Views:
    501
    Barry Schwarz
    Jul 3, 2006
  4. joshd
    Replies:
    12
    Views:
    664
    John Carson
    Oct 2, 2006
  5. jawdoc
    Replies:
    9
    Views:
    747
    Chris Thomasson
    Mar 10, 2008
Loading...

Share This Page