LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   linkedlist c program (https://www.linuxquestions.org/questions/programming-9/linkedlist-c-program-805840/)

shariefbe 05-04-2010 08:17 AM

linkedlist c program
 
Here is my linked list c program i dont know what is the error in this program before posting the error could anyone please tell me what is the error in this?
Code:

#include<stdio.h>
#include<stdlib>
struct node
{
  int data;
  struct node *ptr;
}
int a,i=0;
  struct node *tmp,*lob,*pnt;
  tmp=(struct node *)malloc(sizeof(struct node));
  lob=(struct node *)malloc(sizeof(struct node));
  pnt=(struct node *)malloc(sizeof(struct node));
main()
{
  int o;
 while(1)
{
 printf("Whether you want to add data\n"
        "1.yes\n"
        "2.print\n"
        "3.exit                :");
scanf("%d",&o);
switch(o)
{
case(1):

add();
break;
}
case(2):

print();
break;
}
case(3)
exit(1);
}
}
}
add()
  {
scanf("%d",&a);
lob->data=a;
lob->ptr=NULL;
tmp->ptr=lob;
tmp=lob;
if(i<1)
{
pnt=tmp;
i++;
}
}
print()
  {
while(pnt->data==NULL)
{
printf("%d\n",pnt->data);
pnt=pnt->ptr;
}
}

I am doing my program in GCC. Not in turbo c

theNbomr 05-04-2010 09:25 AM

Without close scrutiny, I see that you are trying to initialize pointers by calling malloc(), but trying to do so outside of any code block. Move the lines:
Code:

  tmp=(struct node *)malloc(sizeof(struct node));
  lob=(struct node *)malloc(sizeof(struct node));
  pnt=(struct node *)malloc(sizeof(struct node));

inside the main() function. There seems to be issues with your add() function. In there, you re-assign a variable tmp, after theoretically having assigned to it with a call to malloc() (memory leak). I don't quite understand how you seem to intend to build up a linked list, but the usual idiom goes something like this:
Code:

    /* lob is pointer to head node. */
    tmp * struct node;
    tmp = lob;
    /* Traverse list, to end node */
    while( tmp->ptr ){ tmp = tmp->ptr; }

    /* Append node and go there */
    tmp->ptr = (struct node *)malloc( sizeof( struct node) );
    tmp = tmp->ptr;
    tmp->ptr = NULL;

    /* Put data in new node */
    tmp->data=a;

It would be more conventional to pass the head node as a parameter to the add() function, and avoid the use of global variables. Thanks for posting in [C O D E] tags, but your indenting style with everything left aligned could be made more readable. It would be helpful to reader if you posted some evidence of what the problem is, like compiler/linker output, etc.

C is C. Turbo C is like C, but full of DOS/Windows cruft.

--- rod.

shariefbe 05-04-2010 10:19 AM

now i am getting these errors
Code:

linkedlist.c:7: error: two or more data types in declaration specifiers
linkedlist.c:7: error: invalid initializer
linkedlist.c: In function ‘main’:
linkedlist.c:12: warning: incompatible implicit declaration of built-in function ‘malloc’
linkedlist.c:36: error: expected ‘:’ or ‘...’ before ‘exit’
linkedlist.c:36: warning: incompatible implicit declaration of built-in function ‘exit’
linkedlist.c: In function ‘add’:
linkedlist.c:42: warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘struct node *’
linkedlist.c:43: error: ‘lob’ undeclared (first use in this function)
linkedlist.c:43: error: (Each undeclared identifier is reported only once
linkedlist.c:43: error: for each function it appears in.)
linkedlist.c:45: error: ‘tmp’ undeclared (first use in this function)
linkedlist.c:47: error: invalid operands to binary < (have ‘struct node’ and ‘int’)
linkedlist.c:49: error: ‘pnt’ undeclared (first use in this function)
linkedlist.c:50: error: wrong type argument to increment
linkedlist.c: In function ‘print’:
linkedlist.c:55: error: ‘pnt’ undeclared (first use in this function)

could anyone please help me what is the error

theNbomr 05-04-2010 11:00 AM

Most of those error messages are not helpful, without seeing the code to which they refer. Some of them can be inferred without great difficulty, like 'implicit declarations'; did you include the appropriate header file(s)? Undeclared variables should be trivial to fix; declare the variables as required.
You don't seem to have tried very hard to track down any of the errors yourself. If this is simply because you are new to the language, then my best advice is to get out your C language books & man pages, and start using the practice to learn the language. Look at the error messages, and then at the lines of source code to which each message refers. See anything? Very often in C, the actual error will be 'above' the reported error. If the error message seems nonsensical as reported, scroll up in the source and scrutinize each line. Often, you will find things like missing semi-colons, unbalanced parentheses, unbalanced curly-braces, or unbalanced quotes, which causes the compiler to mis-interpret what is written, and report errors where it finally gives up compiling.
--- rod.

shariefbe 05-06-2010 05:01 AM

I declared all the things and i included all the header files. still i am getting some errors
Code:

linkedlist.c: In function ‘main’:
linkedlist.c:36: error: expected ‘:’ or ‘...’ before ‘exit’
linkedlist.c: In function ‘add’:
linkedlist.c:43: error: ‘lob’ undeclared (first use in this function)
linkedlist.c:43: error: (Each undeclared identifier is reported only once
linkedlist.c:43: error: for each function it appears in.)
linkedlist.c:45: error: ‘tmp’ undeclared (first use in this function)
linkedlist.c:49: error: ‘pnt’ undeclared (first use in this function)
linkedlist.c: In function ‘print’:
linkedlist.c:55: error: ‘pnt’ undeclared (first use in this function)

How i declared all pointer variables inside the main().
i question is why cant we declare the struct pointer variable outside main as global declaration. if i want to do that what is the procedure?

ArthurSittler 05-06-2010 05:06 AM

The usual convention when using C is to separate the code body into two files: the header file <filename>.h, and the program file <filename>.c.

The dummy variable <filename> is just the name of your program. That is, <filename>.h might be mylistprog.h and <filename>.c might be mylistprog.c.

The header file contains preprocessor directives to define constants, compilation control switches, typedefs for the structures used in the programs, and prototypes for all the functions (except, perhaps main()). Nothing in the header file actually generates any code nor allocates any storage.

The header file is then included in the program file with the preprocessor directive

#include "<filename>.h"

For simple example code, however, you can simply put everything that would be included in the header file at the beginning of the code file, and use a single file.

The program file contains any global storage definitions, and all the actual code. I strongly recommend avoiding global variables. It is much safer to allocate the most global data in main() and pass pointers to it as parameters to functions which need to manipulate that data.

Trying to call malloc() outside of any function may not actually be permitted. I never tried to do that.

I would define the list node in the header file with something like

typedef datanode
{
int iValue;
datanode *psNextNode;
} DATANODE, *DATANODE_PT;

Then I would have a list head pointer in main() something like

DATANODE_PT psListHead = NULL; /* empty list */

Now, at this point, you may wish to ask yourself, "Self, what do you want to do with your lists?" If you want to build a stack, you only need functions to push data onto the list and pop data from the list. You may also want a function to test if the stack is empty, but another possibility is that trying to pop an empty stack simply returns an error indication. Whatever type of list you want, you will probably want to define some operations on that list. The easy way to handle this is to write simple functions, one function for each list operation, which take the list head as a parameter and return a node pointer. Operations which add data to the list would need to include the new data as another parameter. The prototypes for the functions for a simple stack of ints might look something like

/* push another int onto the stack
* AT ENTRY:
* psHead points to top of stack
* iValue is integer value to push onto stack
* AT RETURN:
* return 0 on success, or -ErrLevel on failure
*/
int iPush( DATANODE_PT psHead, int iValue );

/* pop int from stack
* AT ENTRY:
* psHead points to top of stack
* AT RETURN:
* return 0 on success, or -ErrLevel on failure
*/
int iPop( DATANODE_PT psHead, int *piPopValue );

You will need to call malloc() to allocate the new list node inside iPush with this code code layout and call free() within iPop to release the list node.

Of course, you could use a less simplistic structure than just a list node pointer for your stack, and store nodes popped from the stack for re-use to economize on calls to malloc() at the expense of needing a function to create an empty stack. However, it is best to just keep it simple at first until you are comfortable with manipulating your lists.

A great debugging aid is to also write a function which dumps the contents of your lists (or any other data structures) along with your other list manipulation functions. The printf() family of functions can print the values of pointers with the %p format specifier.

Aquarius_Girl 05-06-2010 05:34 AM

Quote:

Originally Posted by shariefbe
How i declared all pointer variables inside the main().
i question is why cant we declare the struct pointer variable outside main as global declaration. if i want to do that what is the procedure?

There is a difference between definition and declaration !!
Now see the below code, there are 2 errors left now, solve them yourself at least. I have solved the rest for you !
compare your code and this code and see for yourself where you were wrong !
Code:

#include<stdio.h>
#include<stdlib.h>
struct node
{
  int data;
  struct node *ptr;
}

  int a;
  int i;
  struct node *tmp;
  struct node *lob;
  struct node *pnt;
 
 
main()
{
    i  = 0;
    tmp = (struct node *)malloc(sizeof(struct node));
    lob = (struct node *)malloc(sizeof(struct node));
    pnt = (struct node *)malloc(sizeof(struct node));
    int o;
   
    while(1)
    {
          printf("Whether you want to add data\n"
              "1.yes\n"
              "2.print\n"
              "3.exit                :");
          scanf("%d",&o);
          switch(o)
          {
              case 1:
              { 
                    add();
                    break;
              }
              case 2:
              { 
                    print();
                    break;
              }
              case 3:
              {
                    exit(1);
              }
          }
    }
}


add()
{
    scanf("%d",&a);
    lob->data=a;
    lob->ptr=NULL;
    tmp->ptr=lob;
    tmp=lob;
    if(i<1)
    {
          pnt=tmp;
          i++;
    }
}

print()
{
    while(pnt->data==0)
    {
          printf("%d\n",pnt->data);
          pnt=pnt->ptr;
    }
}


ArthurSittler 05-07-2010 02:35 PM

confusion between declaration and definition
 
Thank you, anishakaul, for trying to clarify the distinction between definition and declaration. I frequently confuse the two terms. Section A8 of Appendix A of K & R 2ed begins with these two sentences:

"Declarations specify the interpretation given to each identifier; they do not necessarily reserve storage associated with the identifier. Declarations that reserve storage are called definitions. ... "

I had it backwards.

Since one never actually uses the terms "declaration" and "definition" in C program code, using the wrong term does not cause compiler errors. I am living proof that such a confusion can persist for decades in a programmer.

What I was trying to say was that the declaration of the node structure and function prototypes can be (perhaps should be) done within a header file which is split out from the C code file. This makes it easy to easier to modularize larger C and C++ programs by separating the format of external variables, structs, and functions from their implementations.

In retrospect, I can see that the whole discussion of .c files and .h files may have simply added unnecessary confusion to my previous posting. I put it in there because I thought the writer of the original post may have been a novice to C programming, and might benefit from a little background that is often glossed over in the instructional materials but is expected later in the workplace.

Global variables may be declared and defined outside of any function by placing them preceding their first reference by any function. Declaration of a pointer to a data node may be done within any function, but to be useful in the context of my incorrect example one would need to pass the address of the list pointer, which would be the address of the pointer, that is, a pointer to a pointer to a struct. The typedef may have been better if it defined an addition type (as does my actual working code), something like the following:

typedef struct sDataNode
{
int iValue;
sDataNode *NextDataNode;
} DATANODE, *DATANODE_PT, **DATANODE_PT_ADDR

Then the function prototypes for iPush and iPop would look like

int iPush( DATANODE_PT_ADDR ppsListHead, int iNewValue);
int iPop( DATANODE_PT_ADDR ppsListHead, *int piPoppedValue );

The List pointer definition would look like

DATANODE_PT psListHead;

The invocation of the push and pop functions would look like

errlevel = iPush( &psListHead, iNewValue );

...

errlevel = iPop( &psListHead, &piPoppedValue );

I hope this helps, but I fear it may simply further muddy the water.

Passing the address of the list head pointer enables using multiple stacks of the same type data. One can further generalize by enabling variations in the data type, but such additional discussion may further confuse the issue, and I likely would get it wrong, anyway.

johnsfine 05-07-2010 03:03 PM

Quote:

Originally Posted by anishakaul (Post 3959071)
You can't define any variable outside any function !

Please stop confusing the beginner.

Quote:

There is a difference between definition and declaration !!
There is a difference, and you have described it incorrectly.

You can declare variables outside of functions.

You can define variables outside of functions.

You can even initialize variables in definitions outside of functions.

But there are restrictions on how you initialize variables in definitions outside of functions and the original code of this thread violated such restrictions.

ArthurSittler 05-07-2010 03:34 PM

correction to previous correction
 
When I showed the data node, I forgot to tell the compiler that the NextDataNode was a pointer to a struct. I also failed to terminate the typedef statement with a semicolon. That typedef should have been as follows:

typedef struct sDataNode
{

int iValue;
struct sDataNode *NextDataNode;

} DATANODE, *DATANODE_PT, **DATANODE_PT_ADDR;

I also now realize that my example is not quite analogous to yours because I use typedef to create a type, which does not define a variable which would allocate storage. No storage is allocated until I declare a variable which is a pointer to the structure. I only actually allocate the structures by calling malloc() at run time (e.g., in the iPush() function).

I think the error message on line 7 is because there is no semicolon, which is required at the end of the statement which declares (and defines) your struct variable. Line 7 is the line with the closing semicolon at the end of your struct declaration. The error message is misleading because the compiler can tell that there is an error at or before the indicated place in the code, but makes an incorrect guess about the actual type of the error. Error interpretation by the compiler is always a difficult thing to implement, because there may be more than one way to complete the construct of which the parser has seen the prefix. The compiler writer has tried to give you a more helpful message than the unhelpful and possibly incomprehensible "parse error" message, but this time it looks like it is giving a misleading message.

ArthurSittler 05-07-2010 03:48 PM

oops, a couple more errors
 
Perhaps I should not try to post here. I make errors in my posts, then I make errors when I try to correct the errors in my earlier posts.

Where I was talking about my typedef declaration, I meant to say that I used an "additional" type, not an "addition" type. I also misplaced the prefix unary asterisk in the iPop prototype. That should have been

int iPop( DATANODE_PT_ADDR ppsListHead, int *piPoppedValue );

instead of

int iPop( DATANODE_PT_ADDR ppsListHead, *int piPoppedValue );

sundialsvcs 05-08-2010 08:54 AM

Ask your teacher...? To help you with your homework...?

ArthurSittler 05-09-2010 04:19 AM

You may wish to approach this in smaller steps
 
Shariefbe, you might want to approach this in smaller steps. Your code suggests to me that you might not be very familiar with C. Manipulating linked lists abstractly is independent of programming language. Implementing linked lists in C implies a familiarity with C, including its implementation of structs, arrays, and pointers. Beyond that, implementing linked lists in C is still not trivial, but it is a smaller step than stepping into C cold and trying to implement linked lists as a first program in the language.

I always recommend The C Programming Language, second edition, by Brian W. Kernighan and Dennis M. Ritchie, ISBN 0-13-110362-8, as an indispensable reference for anyone wishing to learn or use C. It is the definition of the language, though you should also locate the errata and addenda from the internet and keep that handy as well.

You obviously have succeeded in the most fundamental and major hurdle with using C, because you have entered source code and invoked the compiler. The next step might be to manipulate some arrays. Then write a little test program using structs.

Your compiler tells you what line number it is compiling when it detects each error. The error may be on the indicated line or previous to it, depending on the error. It is common for an error to cause a cascade of errors later in the compilation. However, it may be worth while to examine the code at or before the line number indicated in every error message. This may save a few iterations in debugging.

Implement some functions to simplify the logic in your program. My rule for when it is appropriate to separate code out into a function is that when you do the same instruction sequence with the same meaning more than once, that portion of the code should be made into a function. If it looks like you could accomplish your goal by copying a block of code and editing little pieces in the copies, don't do it! Make it a function, and pass the parts that you would change as parameters to the function.

Somewhere throw in a program to use pointers to simple variables and to array elements. Then progress to using pointers with structs and the pointer dereference operator ->. I recommend always initializing pointers when you create them. If you don't initialize them to the address of some appropriate variable, set them to NULL. Make sure you always test pointers to make sure they are not NULL before attempting to dereference them. Dereferencing NULL pointer will usually abend with segmentation fault (unless you use assertions and trap the fault).

I also write my code in comments before I write it in the implementation language, what ever that might be. Using descriptive variable names also helps me or anyone else who later looks at my code later (if later ever comes).

There are some of us here who are willing to help in any way we can to offer help, guidance, and encouragement to anyone at any time. But there are others who simply will try to encourage you to stay out of the forum until you are more experienced. My personal goal is to be as helpful as I can be and try to help anyone as best I can. That means trying to figure out what they need to progress toward their desired goal and pointing them to actions or information resources that can help them advance toward their goals. I also would try to encourage everyone to be as civil as possible, but I have no authority nor ability to enforce that standard on anyone else. I am not a moderator here and the forum is better off that way. The posters who may seem very terse also have much to offer the forum, so I would not wish to interfere with their contributions, either.

Aquarius_Girl 05-09-2010 11:36 PM

Quote:

Originally Posted by johnsfine (Post 3960698)
Please stop confusing the beginner.

There is a difference, and you have described it incorrectly.

You can declare variables outside of functions.

You can define variables outside of functions.

You can even initialize variables in definitions outside of functions.

But there are restrictions on how you initialize variables in definitions outside of functions and the original code of this thread violated such restrictions.

Yes you are right and i was wrong !! :banghead:
I should have been more careful in remembering things while posting that reply, Apologies !

Aquarius_Girl 05-09-2010 11:39 PM

Quote:

Originally Posted by ArthurSittler
Thank you, anishakaul, for trying to clarify the distinction between definition and declaration. I frequently confuse the two terms. Section A8 of Appendix A of K & R 2ed begins with these two sentences:

Well you are welcome, but I had mentioned some incorrect statements in that post which John has corrected duly .


All times are GMT -5. The time now is 02:49 PM.