#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    11
    Rep Power
    0

    Error while displaying single linked list


    I am trying to create a single linked list with two elements in each node. I am storing the first two fields from input file and displaying the contents that are stored in my Linked List. While printing the output is always the last element while it should have been the first two elements of each row in the file.



    Code:
    #include<stdio.h>
    #include<stdlib.h>
    struct node
    {   char *key;
        char *str;
    	struct node *link;
    };
    void append(struct node **, char *, char *);
    void display(struct node *);
    int bufferSize = 3500;
    
    
    int main (int argc, char *argv[] )
    {
        struct node *p;  /* p can be said as the head or a start ptr */
        p=NULL;
        char line[bufferSize];
        int i, j;
        char c;
        char f1[bufferSize], f2[bufferSize];
        
        int k;
        //Read reference file (patent file) and count total number of lines in it
        FILE* reffile_ptr;
        reffile_ptr = fopen(argv[1], "r");
        if (!reffile_ptr) {
            printf("Couldn't open the file %s for reading\n", argv[1] );
            return 0;
        }
        
        fscanf(reffile_ptr, "%*[^\n]\n", NULL);
        while(fgets(line, bufferSize, reffile_ptr) != NULL)
        {
                i=0, j=0;
                printf("%s", line);
                //read first field
                while(line[i] != '\t')
                    f1[j++]= line[i++];
                f1[j] = '\0';
                //read second field
                j=0;
                i++;
                while(line[i] != '\t')
                    f2[j++] = line[i++];
                f2[j] = '\0';
                //printf("%s\t%s\n\n", f1, f2);
                append(&p,f1, f2);
                //Ignore other elements in the 'line'
        }
        fclose(reffile_ptr);
        display(p);
    }
    
    
    void append(struct node **q,char *mykey, char *mystr)
    {
        printf("%s\t%s\n\n", mykey, mystr);
        struct node *temp,*r;
        temp = *q;
        if(*q==NULL)
        {
            //printf("first");
            temp = (struct node *)malloc(sizeof(struct node));
            temp->key = mykey;
            temp->str = mystr;
            temp->link=NULL;
            *q=temp;
        }
        else
        {  temp = *q;
            //printf("next\n");
            while(temp->link !=NULL)
                temp=temp->link;
            r = (struct node *)malloc(sizeof(struct node));
            r->key = mykey;
            r->str = mystr;
            r->link=NULL;
            temp->link=r;
        }
    }
    
    
    void display(struct node *q)
    {
        if(q==NULL)
            printf("\n\nEmpty Link List.Can't Display The Data");
        while(q->link!=NULL)
            {
            printf("\n%s\t%s\n",q->key, q->str);
            q=q->link;
            }
    }

    My input file is a tab-delimited file
    Code:
    ID	seq	len
    082054	AAAG	46742
    53948	AAAGGGATAGAAAAAACGAA	37
    53948	AAAGGGAGACTTTGGATAAGG	39
    253	ALFPGELDY	15
    085241	ASHHHHHH	23
    184152	ASAS	11
    184152	AGGSGASAS	16
    184152	AGGGSGASAS	21
    184152	AGGGSGASAS	26
    184152	AASGASAS	31
    184152	AAS	13

    The output shown is the last element in each node, while I am expecting first two fields of each roe in the input file.

    Code:
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS
    184152	AAS

    From replies, I am able to print correctly but it is not displaying the first line. My modified code is :

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    struct node
    {   char *key;
        char *str;
    	struct node *link;
    };
    void append(struct node **, char *, char *);
    void display(struct node *);
    int bufferSize = 3500;
    
    
    int main (int argc, char *argv[] )
    {
        struct node *p;  /* p can be said as the head or a start ptr */
        p=NULL;
        char line[bufferSize];
        int i, j;
        char c;
        char f1[bufferSize], f2[bufferSize];
        
        int k;
        //Read reference file (patent file) and count total number of lines in it
        FILE* reffile_ptr;
        reffile_ptr = fopen(argv[1], "r");
        if (!reffile_ptr) {
            printf("Couldn't open the file %s for reading\n", argv[1] );
            return 0;
        }
        
        fscanf(reffile_ptr, "%*[^\n]\n", NULL); //skip the first line
        while(fgets(line, bufferSize, reffile_ptr) != NULL)
        {
                i=0, j=0;
                printf("%s", line);
                //read first field
                while(line[i] != '\t')
                    f1[j++]= line[i++];
                f1[j] = '\0';
                //read second field
                j=0;
                i++;
                while(line[i] != '\t')
                    f2[j++] = line[i++];
                f2[j] = '\0';
                //printf("%s\t%s\n\n", f1, f2);
                append(&p,f1, f2);
        }
        fclose(reffile_ptr);
        
        display(p);
    }
    
    
    void append(struct node **q,char *mykey, char *mystr)
    {
        printf("%s\t%s\n\n", mykey, mystr);
        struct node *temp,*r;
        temp = *q;
        if(*q==NULL)
        {
            //printf("first");
            temp = (struct node *)malloc(sizeof(struct node));
            temp->key = malloc(strlen(mykey)+1);
            strcpy(temp->key, mykey);
            temp->str = malloc(strlen(mystr)+1);
            strcpy(temp->str, mystr);
            temp->link=NULL;
            *q=temp;
        }
        else
        {  temp = *q;
            //printf("next\n");
            while(temp->link !=NULL)
                temp=temp->link;
            r = (struct node *)malloc(sizeof(struct node));
            temp->key = malloc(strlen(mykey)+1);
            strcpy(temp->key, mykey);
            temp->str = malloc(strlen(mystr)+1);
            strcpy(temp->str, mystr);
            r->link=NULL;
            temp->link=r;
        }
    }
    
    
    void display(struct node *q)
    {
        if(q==NULL)
            printf("\n\nEmpty Link List.Can't Display The Data");
        while(q->link!=NULL)
            {
            printf("\n%s\t%s\n",q->key, q->str);
            q=q->link;
            }
    }
    New output:

    Code:
    53948	AAAGGGATAGAAAAAACGAA
    53948	AAAGGGAGACTTTGGATAAGG
    253	ALFPGELDY
    085241	ASHHHHHH
    184152	ASAS
    184152	AGGSGASAS
    184152	AGGGSGASAS
    184152	AGGGSGASAS
    184152	AASGASAS
    184152	AAS

    The first line
    Code:
    082054	AAAG
    is still missing here:


    After input from dwise1_aol, I am ablr to solve the problem now:
    Thanks dwise1_aol
    Code:
    void append(struct node **q,char *mykey, char *mystr)
    {
        //printf("%s\t%s\n\n", mykey, mystr);
        struct node *temp,*r;
        temp = *q;
        if(*q==NULL)
        {
            printf("first\n");
            temp = (struct node *)malloc(sizeof(struct node));
            temp->key = malloc(strlen(mykey)+1);
            strcpy(temp->key, mykey);
            temp->str = malloc(strlen(mystr)+1);
            strcpy(temp->str, mystr);
            temp->link=NULL;
            *q=temp;
        }
        else
        {
            temp = *q;
            //printf("next\n");
            while(temp->link !=NULL)
                temp=temp->link;
            r = (struct node *)malloc(sizeof(struct node));
            r->key = malloc(strlen(mykey)+1);
            strcpy(r->key, mykey);
            r->str = malloc(strlen(mystr)+1);
            strcpy(r->str, mystr);
            r->link=NULL;
            temp->link=r;
        }
    }
    
    
    void display(struct node *q)
    {
        printf("In display:\n");
        if(q==NULL)
            printf("\n\nEmpty Link List.Can't Display The Data");
        while(q!=NULL)
            {
            printf("\n%s\t%s\n",q->key, q->str);
            q=q->link;
            }
    }
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    WTF? Are you using C99? Sorry, can't help you.

    I am displaying the linked list but it the output is wrong.
    Do you see the part in bold? It would help immensely if you were to expand upon that. Like explain what output you are getting and how that differs from the output that you expect. Be very specific and provide examples.

    Otherwise, we'll see that you are expecting us to read your mind and nobody will make the attempt.

    Also this on Line 31:
    Code:
        fscanf(reffile_ptr, "%*[^\n]\n", NULL);
    I don't understand what that NULL is doing there. Is it supposed to read and discard that line? A comment informing the read of your intent would be helpful.

    BTW, that line generated this warning:
    kindall2.c:31: warning: too many arguments for format
    I'm guessing that it might have something to do with the asterix, but double-check that guess. To me, that entire line smells of "huh?"
    Last edited by dwise1_aol; December 3rd, 2013 at 07:18 PM.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    11
    Rep Power
    0
    I modified the OP. This line
    Code:
        fscanf(reffile_ptr, "%*[^\n]\n", NULL);
    is working fine as you can see in the output. The problem is either during the insertion of node or displaying the node. Are the following assignments in 'append' function okay?
    Code:
     temp->key = mykey;
            temp->str = mystr;



    Originally Posted by dwise1_aol
    WTF? Are you using C99? Sorry, can't help you.


    Do you see the part in bold? It would help immensely if you were to expand upon that. Like explain what output you are getting and how that differs from the output that you expect. Be very specific and provide examples.

    Otherwise, we'll see that you are expecting us to read your mind and nobody will make the attempt.

    Also this on Line 31:
    Code:
        fscanf(reffile_ptr, "%*[^\n]\n", NULL);
    I don't understand what that NULL is doing there. Is it supposed to read and discard that line? A comment informing the read of your intent would be helpful.

    BTW, that line generated this warning:

    I'm guessing that it might have something to do with the asterix, but double-check that guess. To me, that entire line smells of "huh?"
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    Does this line, fscanf(reffile_ptr, "%*[^\n]\n", NULL);, still throw warnings at you? If so, then you still need to fix it. If you are telling the compiler to not display warnings, then you are a fool; you probably also love to drive at high speed down a mountain road while blindfolded, because that is how you are programming. If you have warnings enabled but you are willfully ignoring them, then you are an even greater fool.

    What do you want those lines in append to do? What you are doing is that you are saving the addresses of those two char arrays in each node. That way every node is pointing to the exact same pair of char arrays. And you keep overwriting what's in those char arrays, so when you print out each node then each and every node will point to the last thing that was written to those two char arrays. Is that really what you want to do?

    If instead you want to save a copy of the two strings in each node, then that is what you must do instead. To the pointers in the node, malloc/calloc memory large enough to hold the strings plus one more character for the null-terminator; something like malloc(strlen(mykey)+1); Then copy the string to that malloc'd memory; eg, strcpy(temp->key, mykey);

    Remember, with C-style strings, you need to actually perform a copy in order to copy a string. Assigning one pointer to another, which is what you are doing, only saves the string's address in that char pointer.

    Comments on this post

    • marykindall agrees : thanks
    Last edited by dwise1_aol; December 4th, 2013 at 11:34 AM.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    11
    Rep Power
    0
    no warning is thrown from 'fscanf' and is working fine as I printed what is being scanned in the subsequent lines. I am writing C code after a long time as I feel that this will give me speed. Ususally I work with high level language from which i am planning to call this.
    Thanks your suggestion worked.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    11
    Rep Power
    0
    dwise1_aol thanks. I realized that the output is still missing the first element.
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    Originally Posted by marykindall
    no warning is thrown from 'fscanf' and is working fine as I printed what is being scanned in the subsequent lines. I am writing C code after a long time as I feel that this will give me speed. Ususally I work with high level language from which i am planning to call this.
    Thanks your suggestion worked.
    What about this warning?:
    kindall2.c:52: warning: control reaches end of non-void function
    You promised the compiler that main would return an int, but you broke that promise. Why haven't you fixed that warning yet?

    If you aren't getting any warnings, then you have warnings turned off. Put on a blindfold and go out for a drive. Always turn warnings on and up! And never ignore warnings! Warnings are telling you that your code has problems. You may be able to start your car and get it to start moving, so you think that it's working perfectly, but that wheel that's about to fall off while you're on the freeway will spoil your drive.

    Never ignore warnings!
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    11
    Rep Power
    0
    My compiler didn't show me any warning. Although I fixed that. Why is that first element not being printed? My gcc version is:
    Code:
    $ gcc -v
    Using built-in specs.
    Target: i686-apple-darwin11
    Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/src/configure --disable-checking --enable-werror --prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1
    Thread model: posix
    gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)
  16. #9
  17. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    Originally Posted by marykindall
    My compiler didn't show me any warning. Although I fixed that.
    I do not know what you mean by that last sentence.

    When you run gcc, always tell it to display warnings. I always use the -Wall option, which tells gcc to display all warnings. There's also -Werror which treats warnings as errors, and --pedantic which I've never used but which may make the testing more strict.

    Some of the problems that warnings flag can be minor, but many are major. And if you made stupid mistakes, such as using = where you really meant ==, then the resultant warnings will point you directly to the line that you need to correct. And some warnings that seem minor end up being major, so always follow up on every warning. Until your program compiles cleanly, meaning no errors and no warnings, you should not try to run it, since the results may be meaningless.

    In the case of that fscanf,
    fscanf(reffile_ptr, "%*[^\n]\n", NULL); //skip the first line
    produces this warning:
    kindall2.c:31: warning: too many arguments for format

    If you were to read the documentation for fscanf, you would find something like this:
    Originally Posted by man page
    * Suppresses assignment. The conversion that follows occurs as usual, but no pointer is used; the result of the conversion is simply discarded.
    That means that that NULL is extraneous; you do not need it. Since *scanf can be a bit tricky, especially if you're not using it correctly (the warning tells us that you are not using it correctly), we don't know what effect that extraneous pointer may have. Probably none (too many pointers is not as bad as too few), but we don't know.

    First order of business: clear that warning. Lose the NULL. When I tried that, it did clear that warning, though I still get tons of errors and warnings because of the C99 code. See if that changes the output. I doubt that it will, but it's worth a try and very easy to do.

    You appear to be writing in C99, which neither I nor a fairly large number of members here can compile. Therefore, I cannot experiment with it in order to figure out what's wrong. I would have to go through it entirely by hand, which I do not have the time for for at least another couple hours.

    I recommend that you add a print statement to the code in append that adds the first node. Print out the two strings that are going into that first node. If it's not the first line of data from the file, then that will be a clue.

    For that matter, you do print out each line of data as you read it in. What does that output look like?

    When we cannot run the program ourselves, you need to provide us with all the output.

    PS

    Since you're using fgets anyway, why not just use fgets to read the first line and then just throw it away (ie, don't process it and call fgets a second time for the first line of data)? Simpler and more consistent and you're not mixing two different input methods, thus avoiding any potential incompatibilities.
    Last edited by dwise1_aol; December 4th, 2013 at 01:16 PM.
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    Consider the else block in append():
    Code:
        else
        {  temp = *q;
    //        printf("next\n");
            while(temp->link !=NULL)
                temp=temp->link;
            r = (struct node *)malloc(sizeof(struct node));
            temp->key = malloc(strlen(mykey)+1);
            strcpy(temp->key, mykey);
            temp->str = malloc(strlen(mystr)+1);
            strcpy(temp->str, mystr);
            r->link=NULL;
            temp->link=r;
        }
    temp points to the last node in the list. r is the new node. Why are you modifying the results of the previous node? In the case of adding the second node, you will have overwritten the data for the first node, causing the data of the first line to disappear. Shouldn't you instead be updating the fields in r?

    Copy-and-paste and then modifying what you just pasted is a common technique. However, you must always remember to modify the copied code.

    Also, in display():
    Code:
    void display(struct node *q)
    {
        if(q==NULL)
            printf("\n\nEmpty Link List.Can't Display The Data");
        while(q->link!=NULL)
            {
            printf("\n%s\t%s\n",q->key, q->str);
            q=q->link;
            }
    }
    When you advance to where q is pointing to the last node, you will fail to display the values in that node. Instead of displaying 11 lines of data for the 11 nodes, you will only display 10, leaving the last node off.

    Instead, shouldn't you be looping until q == NULL ? I assume that you had originally done that, but since the bug above had caused your last node's strings to be pointing to garbage you "fixed" that by not displaying the last node. Fix the bug above in append and you will no longer need this "fix".

    Comments on this post

    • marykindall agrees : Thanks
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    11
    Rep Power
    0
    You are just awesome. You hit the nail on the head. Thanks again.

    Comments on this post

    • dwise1_aol agrees : Never could have done it without the output and what was expected. That is you helping us to help you and it is a must.

IMN logo majestic logo threadwatch logo seochat tools logo