problems with a string linked list program and pointers 
Author Message
 problems with a string linked list program and pointers

I'm in the process of converting my linked list program from int to
string for the info value of the node.
It was working fine as int which I did first to check my logic, but now
I'm having problems with the pointer to the node with an array of char.
I've been having problems with pointer notation, within procedures with
passed ptr parameters, in general.  
Note: you will see I'm still in the middle of converting, I just stopped
where it won't compile anymore.

Here's the code:
/*
 * Sarah
 * Project 4 part one for Prof. Pinto. C class 3/28/98
 * This program will insert strings in order, into a linked list
 *
 */

/* Note to myself:
 * use of strcmp(const *string1, const *string2)
 * < 0 string1 less than string2
 * 0 string1 identical to string2
 * > 0 string1 greater than string2
 */

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

#define NIL 0
#define STRING_SIZE 15

struct node{
        /*int id;*/
        char stored_string[STRING_SIZE];
        struct node *next;

Quote:
};

int printnodes();
int sort(struct node *(*newnode));

struct node *first, *p, *newnode, *traverse, *q;
char uservalue[STRING_SIZE];
int j;

void main(){

        /* get 10 values and enter them in order into a linked list */
        for (j=1; j<11; j++){
                /* creates a node */
                newnode = (node*)calloc(1, sizeof(struct node));

                /* gets data from user */
                printf("\n Enter a string: ");
                scanf("%s", uservalue);

                /* sticks the value into a node */
/***** here's where the problem is, I've tried several guesses at what
the proper notation should be. it does not compile. *****/
                 *(newnode->stored_string) = uservalue;
                (*newnode).next = NIL;

                /* sort as the node comes in from the user info. */
                sort(&newnode);
        }

        printnodes();

Quote:
}

int printnodes(){

        traverse = first;
        printf("List of values inorder: \n");

        do{
                printf("   %d \n", (*traverse).stored_string);
                traverse = (*traverse).next;
        }while (traverse != NIL);

        return 0;

Quote:
}

/* not converted to use strcmp yet */
int sort(struct node *(*newnode)){

        if (first == NIL){
                /* no nodes exist yet, make this the first and only node */
                printf("first node set \n");
                first = *newnode;
        }else if ((*newnode)->stored_string < (*first).stored_string){
                /* put new node in front of the list */
                (*newnode)->next = first;
                first = *newnode;
        }else{
                p = first;
                /* drop out of the traverse when at the end of the list
                   or the next node is larger than the new node */
                while (((*p).next != NIL) && ((*newnode)->stored_string >
(*p).stored_string)){
                        q = p;
                        p = (*p).next;
                }
                /* either insert the new node inbetween 2 nodes
                   or at the end of the list */
                if ((*newnode)->stored_string < (*p).stored_string){
                        (*q).next = *newnode;
                        (*newnode)->next = p;
                }else{
                        (*p).next = *newnode;
                }
        }

        return 0;

Quote:
}

-- Sarah

_______________________________________________>^..^<_____________


(anti-spam action taken in reply-to field)
"I always have choices, sometimes it's a choice of perspective."



Thu, 14 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

: I'm in the process of converting my linked list program from int to
: string for the info value of the node.
: It was working fine as int which I did first to check my logic, but now
: I'm having problems with the pointer to the node with an array of char.
: I've been having problems with pointer notation, within procedures with
: passed ptr parameters, in general.  
: Note: you will see I'm still in the middle of converting, I just stopped
: where it won't compile anymore.

: Here's the code:
: /*
:  * Sarah
:  * Project 4 part one for Prof. Pinto. C class 3/28/98
:  * This program will insert strings in order, into a linked list
:  *
:  */

: /* Note to myself:
:  * use of strcmp(const *string1, const *string2)
:  * < 0 string1 less than string2
:  * 0 string1 identical to string2
:  * > 0 string1 greater than string2
:  */

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

: #define NIL 0
/* ### do not do this; use NULL as the compiler writers intended */
: #define STRING_SIZE 15

: struct node{
:       /*int id;*/
:       char stored_string[STRING_SIZE];
:       struct node *next;
: };

: int printnodes();
/* ### int printnodes(void) */
: int sort(struct node *(*newnode));
/* ### there doesn't seem much point in double indirection here,
 * and it's tricky to handle.  Why not '(struct node *newnode)'?
 */
: struct node *first, *p, *newnode, *traverse, *q;
: char uservalue[STRING_SIZE];
: int j;
/* ### global variables aren't a good idea, and are hard to follow.
 * globals like newnode, with the same name as variables with local
 * scope, are actively dangerous.  Drop these, perhaps keeping 'first',
 * tho' that could also be local to main and passed as a function
 * parameter.
 */
: void main(){
/* ### int main(void) */
:       /* get 10 values and enter them in order into a linked list */
:       for (j=1; j<11; j++){
/* ### (j = 0 ; j < 10 ; j++) would be more conventional */

:               /* creates a node */
:               newnode = (node*)calloc(1, sizeof(struct node));
/* ### drop the case, and check that calloc() worked, eg, newnode
 * isn't NULL.
 */
:               /* gets data from user */
:               printf("\n Enter a string: ");
/* ### add 'fflush(stdout);' here */
:               scanf("%s", uservalue);
/* ### if you must use scanf(), set a field width and check the
 * return value.
 */
:              

:               /* sticks the value into a node */
: /***** here's where the problem is, I've tried several guesses at what
: the proper notation should be. it does not compile. *****/
:                *(newnode->stored_string) = uservalue;
:               (*newnode).next = NIL;
/* ### you want
                strncpy(newnode->stored_string, uservalue, 14);
                newnode->next = NULL;
 * note that you've cleared the string part of newnode with calloc,
 * so this will leave a trailing '\0' in stored_string.  calloc()
 * doesn't necessarily set pointers to NULL, so you need the
 * second line.
 */
:               /* sort as the node comes in from the user info. */
:               sort(&newnode);
/* ### double indirection again */
:       }

:       printnodes();
: }

/* ### for the remaining code, see the versions I've added below */

: int printnodes(){

:       traverse = first;
:       printf("List of values inorder: \n");

:       do{
:               printf("   %d \n", (*traverse).stored_string);
:               traverse = (*traverse).next;
:       }while (traverse != NIL);

:       return 0;
: }

: /* not converted to use strcmp yet */
: int sort(struct node *(*newnode)){
:      
:       if (first == NIL){
:               /* no nodes exist yet, make this the first and only node */
:               printf("first node set \n");
:               first = *newnode;
:       }else if ((*newnode)->stored_string < (*first).stored_string){
:               /* put new node in front of the list */
:               (*newnode)->next = first;
:               first = *newnode;
:       }else{
:               p = first;
:               /* drop out of the traverse when at the end of the list
:                  or the next node is larger than the new node */
:               while (((*p).next != NIL) && ((*newnode)->stored_string >
: (*p).stored_string)){
:                       q = p;
:                       p = (*p).next;
:               }
:               /* either insert the new node inbetween 2 nodes
:                  or at the end of the list */
:               if ((*newnode)->stored_string < (*p).stored_string){
:                       (*q).next = *newnode;
:                       (*newnode)->next = p;
:               }else{
:                       (*p).next = *newnode;
:               }
:       }

:       return 0;
: }

int printnodes(void) {
  struct node *traverse;

  printf("List of values in order: \n");
  for (traverse = first ; traverse ; traverse = traverse->next)
        printf("   %s\n", traverse->stored_string);

  return 0;

Quote:
}

int sort(struct node *newnode) {
  struct node *p, *q;

  if (first == NULL){
        first = newnode;
  } else {
        q = p = first;
        /* drop out of the traverse when at the end of the list
           or the next node is larger than the new node */
        while (p && strcmp(newnode->stored_string, p->stored_string) > 0) {
                q = p;
                p = p->next;
        }
        /* insert the new node in the list */
        if (q == first)
                first = newnode;
        else
                q->next = newnode;
        newnode->next = p;
  }

  return 0;

Quote:
}

Will



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

Quote:

>#define NIL 0

This is unnecessary.  You can use NULL (defined in <stdlib.h> and
<stddef.h>) if you don't want to just type 0.

Quote:
>struct node{
> /*int id;*/
> char stored_string[STRING_SIZE];
> struct node *next;
>};

OK.  If you don't want to have to type 'struct node' from this point
forward, you can do something like

struct node_tag {
  char stored_string[STRING_SIZE];
  struct node *next;

Quote:
};

typedef node_tag node;

Now you can just use "node" rather than "struct node" to refer to this data
type.

Quote:
>int printnodes();

You're not passing anything to printnodes(), so you should define it as

int printnodes(void);

(As explained below, you probably actually do want to pass a parameter to
printnodes(), though.)

Furthermore, you're always returning 0, and never using the return value, so
you could just as well write

void printnodes(void);

unless you want to leave open the possibility that some day you may want to
do something with the return value.

Quote:
>int sort(struct node *(*newnode));

Consider putting sort() in a separate file, say sort.c, and putting the
above line in sort.h, which you would then #include into this file.  If, on
the other hand, you don't want sort() to be visible outside this file,
define it as static.

Quote:
>struct node *first, *p, *newnode, *traverse, *q;
>char uservalue[STRING_SIZE];
>int j;

These are all global variables, since they're defined outside any function.
Not a good idea.  Define them inside main() and pass them as parameters when
you need other functions to see their values.

Quote:
>void main(){

This should be

int main(void)
{

Quote:
> /* get 10 values and enter them in order into a linked list */
> for (j=1; j<11; j++){
> /* creates a node */
> newnode = (node*)calloc(1, sizeof(struct node));

It would be more efficient to allocate all the nodes in one block.  You also
didn't check the return value of calloc.  If it returns a null pointer, you
didn't get the memory you asked for.  The typecast (node *) is not necessary
in standard C.  Be careful to observe that, although calloc sets the
allocated bits to zero, that's not necessarily the same as setting, for
example, the "next" pointer to NULL.

Quote:
> /* gets data from user */
> printf("\n Enter a string: ");
>     scanf("%s", uservalue);

You're in big trouble here if the user types more than STRING_SIZE - 1
characters.  fgets() is safer in this regard.  Alternatively, you could
specify a field width.  Keep in mind that scanf() stops when it hits
whitespace (not just a newline), so you might not get the results you expect
for the next string if the user types a string with spaces.  You also need
to check the return value of scanf().

Quote:

> /* sticks the value into a node */
>/***** here's where the problem is, I've tried several guesses at what
>the proper notation should be. it does not compile. *****/
> *(newnode->stored_string) = uservalue;

You can't set one array equal to another.  That is,

char x[10] = ...;
char y[10] = ...;
x = y;

does not work.  You can't assign to an array.  (FAQ 6.7.)  You might want to
look at strcpy().  Or, just read the user input directly into the node's
stored_string field.

Quote:
> (*newnode).next = NIL;

This is valid, but it's more typical to write
newnode->next = NIL;

The big problem here is that you aren't connecting your nodes together.
You're setting each node's "next" pointer to NIL.

Quote:

> /* sort as the node comes in from the user info. */
> sort(&newnode);

It should be possible to write sort() in such a way that you don't have to
have this extra level of indirection.  That is, it's possible to write sort
in such a way that you can call it as sort(newnode);

Quote:
> }

> printnodes();

return EXIT_SUCCESS; /* let's be optimistic here */

Quote:
>}
>int printnodes(){

> traverse = first;

Here's where the you start getting into trouble with the global variables.
Did you set first to something yet?  You have to trace back through your
main() code to see if there are any prior function calls that might have
given first a value.  This can become a nightmare when you have hundreds of
function calls.

Quote:
> printf("List of values inorder: \n");
> do{
> printf("   %d \n", (*traverse).stored_string);

%d won't work for a string.  And are you sure that you will always have at
least one element in your linked list when you call printnodes()?

Quote:
> traverse = (*traverse).next;
> }while (traverse != NIL);

You have a fair amount of work to do before worrying about converting your
sort routine to work with strings.  One hint: it should be possible to write
sort() such that its interface (i.e. the parameters you pass it) does not
change regardless of what type of data you store in your linked list.  In
fact, if you think about it, all that changes is the "compare" operation and
the "swap" operation.  If you write your sort routine so that the _user_
provides (pointers to) functions that perform compare and swap, then the
same sort() function can be used regardless of what kind of data you have.
Take a look at the function prototype for qsort(), which is in <stdlib.h>.

Hope this helps.

--
Please disregard the e-mail address in the header of this message.
I may be addressed as "syd" at the commercial internet service
provider "Netroplex."



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

Subject: Re: problems with a string linked list program and pointers

Please take this lightly.  It is a common mistake.

This one should fall under the category of Duhhh?

 *(newnode->stored_string) = uservalue;

your problem is definitely here!

You cannot simply reassign the base address of the character array to the
address of the character string uservalue.  This is exactly what you are trying
to do.  More preferrable is to  use

#include <string.h>
strcpy(newnode->stored_string, uservalue);

I guarantee that will help!



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

: : I'm in the process of converting my linked list program from int to
: : string for the info value of the node.
[...]
: int sort(struct node *newnode) {
:   struct node *p, *q;

:   if (first == NULL){
:       first = newnode;
:   } else {
:       q = p = first;
:       /* drop out of the traverse when at the end of the list
:          or the next node is larger than the new node */
:       while (p && strcmp(newnode->stored_string, p->stored_string) > 0) {
:               q = p;
:               p = p->next;
:       }
:       /* insert the new node in the list */
:       if (q == first)
/* ### should be q = p */
:               first = newnode;
:       else
:               q->next = newnode;
:       newnode->next = p;
:   }

:   return 0;
: }

And in the main program, the memory allocated for the linked list
should have been free'd before the return from main().

Will



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

|I'm in the process of converting my linked list program from int to
|string for the info value of the node.
|It was working fine as int which I did first to check my logic, but now
|I'm having problems with the pointer to the node with an array of char.
|I've been having problems with pointer notation, within procedures with
|passed ptr parameters, in general.
|Note: you will see I'm still in the middle of converting, I just stopped
|where it won't compile anymore.

Sarah,
I bet you knew the answer but just forgot...

The marked line (for the structure
|struct node{
| /*int id;*/
| char stored_string[STRING_SIZE];
| struct node *next;
|};

Quote:
}

is

| /* sticks the value into a node */
|/***** here's where the problem is, I've tried several guesses at what
|the proper notation should be. it does not compile. *****/
| *(newnode->stored_string) = uservalue;

since you are trying to copy a string `uservalue' into a
string `newnode->stored_string', the obvious answer is
strcpy.  I'm sure that once I've jogged your memory, you
will remember how to do this.  And think about whether
there is any point to dereferencing newnode->stored_string.



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

Quote:

> >struct node{
> > /*int id;*/
> > char stored_string[STRING_SIZE];
> > struct node *next;
> >};

> OK.  If you don't want to have to type 'struct node' from this point

That should be "struct node_tag" right above.

Quote:
> forward, you can do something like

> struct node_tag {
>   char stored_string[STRING_SIZE];
>   struct node *next;
> };
> typedef node_tag node;

And this better be:
  typedef struct node_tag node;

Quote:

> Now you can just use "node" rather than "struct node" to refer to this data
> type.

Again it should be "struct node_tag", this is rather consufing,
ain't it  :-)

Quote:
> Consider putting sort() in a separate file, say sort.c, and putting the
> above line in sort.h, which you would then #include into this file.  If, on
> the other hand, you don't want sort() to be visible outside this file,
> define it as static.

This is good advice, as it all the other advice that you give !
(I just felt that I had to say this :-) )

Quote:
> > (*newnode).next = NIL;

> This is valid, but it's more typical to write
> newnode->next = NIL;

And even more typical to write "newnode->next = NULL;"  ;-)

Stephan
(initiator of the campaign against grumpiness in c.l.c)



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

Quote:

> I'm in the process of converting my linked list program from int to
> string for the info value of the node.
> It was working fine as int which I did first to check my logic, but now
> I'm having problems with the pointer to the node with an array of char.
> I've been having problems with pointer notation, within procedures with
> passed ptr parameters, in general.
> Note: you will see I'm still in the middle of converting, I just stopped
> where it won't compile anymore.

> Here's the code:
> /*
>  * Sarah
>  * Project 4 part one for Prof. Pinto. C class 3/28/98
>  * This program will insert strings in order, into a linked list
>  *
>  */

> /* Note to myself:
>  * use of strcmp(const *string1, const *string2)
>  * < 0 string1 less than string2
>  * 0 string1 identical to string2
>  * > 0 string1 greater than string2
>  */

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

> #define NIL 0
> #define STRING_SIZE 15

> struct node{
>         /*int id;*/
>         char stored_string[STRING_SIZE];
>         struct node *next;
> };

> int printnodes();
> int sort(struct node *(*newnode));

> struct node *first, *p, *newnode, *traverse, *q;
> char uservalue[STRING_SIZE];
> int j;

> void main(){

>         /* get 10 values and enter them in order into a linked list */
>         for (j=1; j<11; j++){
>                 /* creates a node */
>                 newnode = (node*)calloc(1, sizeof(struct node));

>                 /* gets data from user */
>                 printf("\n Enter a string: ");
>                 scanf("%s", uservalue);

>                 /* sticks the value into a node */
> /***** here's where the problem is, I've tried several guesses at what
> the proper notation should be. it does not compile. *****/
>                  *(newnode->stored_string) = uservalue;
>                 (*newnode).next = NIL;

>                 /* sort as the node comes in from the user info. */
>                 sort(&newnode);
>         }

>         printnodes();
> }

> int printnodes(){

>         traverse = first;
>         printf("List of values inorder: \n");

>         do{
>                 printf("   %d \n", (*traverse).stored_string);
>                 traverse = (*traverse).next;
>         }while (traverse != NIL);

>         return 0;
> }

> /* not converted to use strcmp yet */
> int sort(struct node *(*newnode)){

>         if (first == NIL){
>                 /* no nodes exist yet, make this the first and only node */
>                 printf("first node set \n");
>                 first = *newnode;
>         }else if ((*newnode)->stored_string < (*first).stored_string){
>                 /* put new node in front of the list */
>                 (*newnode)->next = first;
>                 first = *newnode;
>         }else{
>                 p = first;
>                 /* drop out of the traverse when at the end of the list
>                    or the next node is larger than the new node */
>                 while (((*p).next != NIL) && ((*newnode)->stored_string >
> (*p).stored_string)){
>                         q = p;
>                         p = (*p).next;
>                 }
>                 /* either insert the new node inbetween 2 nodes
>                    or at the end of the list */
>                 if ((*newnode)->stored_string < (*p).stored_string){
>                         (*q).next = *newnode;
>                         (*newnode)->next = p;
>                 }else{
>                         (*p).next = *newnode;
>                 }
>         }

>         return 0;
> }

> -- Sarah

> _______________________________________________>^..^<_____________


> (anti-spam action taken in reply-to field)
> "I always have choices, sometimes it's a choice of perspective."

Dear Sarah,

Some observations to consider

00."#define NIL 0" is not necessary.The symbolic constant NULL should
   really be used instead. I think NIL is used in Pascal and LISP
   but I am not sure. It may not be a good idea to "hybridize" your
   code by re-introducing "NIL" in a C context.

01.In most cases you must give your function declarations explicit
   parameter lists.In your present code, for example, printout() has
   no parameter list specified.From reading your code, however, I can
   see that you meant to specify an empty parameter list. You should
   have written "int printnodes(void)" not "int printnodes()".

02.I like your idea of signalling a successful operation to the client
   by returning a value 0 from printout().It is a good idea to return a
   status value from a function and I commend you for this inclusion.
   However, two questions come to mind.Why do you need to check
   whether printout() was successful or not ? Look at printf() for
   example.It returns a status flag which few people check.Secondly,
   what is the point of returning a value, that presumably indicates
   success or failure, and then not check that return value from the
   client function  i.e. main() ? What exactly was the point of
   returning the value in the first place ?  

03.Using global variables variables is not a good idea.You may have
   been better off declaring them in main().The reason many people
   try and localize variables to specific functions,is so that it
   is easier to see what code interacts with what data.Having data
   sprawled around the program defeats the dual goals of data hiding
   and encapsulation,things that your programs really should aspire
   to obtain.

04.Ah yes. The canonical mistake of void main(). Please do not ever
   specify main() as returning void. The return value of main should
   always be specified as "int".Also, do not leave the parameter list
   of main() empty. If you plan to include command line processing
   declare main() as "int main(int argc, char** argv){...}", or as
   "int main(int argc, char* argv[]){...}". If you do not intend to
   use command line arguments, an acceptable alternative is
   "int main(void){...}".

05.In sort() you are passing the address of the pointer to node.
   Excellent ! I never really realized this in my earlier programming
   days. However, would it not be clearer to rewrite this as
   "int sort(struct node **nodepp)" ? I have removed the extraneous
   parentheses. They were obscuring the definition.I have appended the
   suffix "-pp", to indicate a pointer to pointer. Sometimes having a
   more semantically laden name is useful.It connects the name to the
   type.You wish to employ this convention or discard it.Likewise it
   is occasionally clearer to create type definitions e.g.

   typedef struct node Node;
   int sort( Node **nodepp ){...}

   This may be clearer or more messy. Like most stylisms, it is your
   prerogative to adopt or discard.

06.Your counting loop has the bouquet of a Pascalian vintage...Loops
   in C start with 0.Assymetric bounds of inclusive lower bounds and
   exclusive upper bounds should start off with 0 and end before N
   e.g. rather than "for(j=1;j<11;j++)" use "for(j=0;j<10;j++)".Just
   by subtracting the lower bounds from the upper bounds you know
   how many elements are in the range.While this is true for your loop
   too, C programmers would much rather prefer you to start with zero.

07.Using scanf() in your particular situation incurs two disadvantages.
   Firstly you will not be able to read a name composed of more than
   one string.Secondly if your user enters a string that is longer than
   14 characters( the 15th character space is reserved for the nul ! ),
   the remaining characters may remain in the keyboard buffer, polluting
   any subsequent reads from the stdin stream.You may resolve both
   problems by using fgets() to read the name and getchar() to clear the
   stdin stream.For example,  

   if(!fgets(uservalue,sizeof(uservalue),stdin))
     error_handler();

   while(getchar()!=EOF)
     ; /* yum yum ! */

   Note that error_handler is a function you define yourself. Do not be
   alarmed ! You could write a simple handler like this

   void error_handler(void){
     printf( "error reading stdin stream.\n" );
     exit( EXIT_FAILURE );
   }

   I would recommend you increase STRING_SIZE to at least 100. Some
   people may think you want their full name and some South Indian
   names or East European names are very long indeed !

08.You cannot simply assign a string to a pointer to allocated memory,
   else all your pointers will alias the same string ! What you want to
   do is create a copy of that read string and store that copy in your
   node. For example,

   strcpy(newnode->stored_string, uservalue);
   newnode->next = NULL;

09.I find it strange that in main() you ask for strings, but then in
   printnodes(), you want to print those same strings out as integers.
   You would be better off trying the below.

   printf( "%s.\n",traverse->stored_string);

   Yes, that strange arrow shaped symbol is legal and clearer.It offers
   the same functionality as what you were doing before, but in a more
   readable form.  

10.I do not see anywhere in your program, provisions for freeing all
   the memory you have been allocating. C is not like Dylan or Java.
   It does not have a background garbage collector routine that
   automatically releases memory back to the operating system. You
   must explicitly release that memory back yourself.

11.I reserve judgment on sort() till you have converted it to using
   strcmp().I wish you every success with that venture :)

12.We will also have a discussion on the importance of interface design,
   modularisation and structured programming.I want to make sure that
   your instructor gives you the best marks possible. From what I can
   see of your post, you have worked exceptionally hard. That work
   should be rewarded with an equally exceptional grade :)Do post the
   rest of your program to comp.lang.c. The programmers who
...

read more »



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

Quote:

> 04.Ah yes. The canonical mistake of void main(). Please do not ever
>    specify main() as returning void. The return value of main should
>    always be specified as "int".Also, do not leave the parameter list
>    of main() empty. If you plan to include command line processing
>    declare main() as "int main(int argc, char** argv){...}", or as
>    "int main(int argc, char* argv[]){...}". If you do not intend to
>    use command line arguments, an acceptable alternative is
>    "int main(void){...}".

Yes, it's wrong to use 'void main()'; but can you mention a case
where it makes any difference? Generally speaking, it's a 'who cares?'
kind of thing.

/RF



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

[snip]

Quote:
>Yes, it's wrong to use 'void main()'; but can you mention a case
>where it makes any difference? Generally speaking, it's a 'who cares?'
>kind of thing.

It really does cause systems to crash.  I once posted a spigot algorithm for
calculation of the digits of pi.  It had main declared as void, and I got an
email explaining that running the program caused his system to crash.  After
repairing void main() to int main(), there were no problems.  Suppose that a
banking transaction had been running simultaneously to his experiment with
my file, or some similar goof.  That could be a very, very bad thing.

It's not some purely pedagocial thing made up for scholars to sniff about.
It causes real problems on real systems.

And is this really so hard:

int main(void)
{
   /* do useful stuff... */
   return 0;

Quote:
}

?
I can't imagine anyone so lazy as to feel that this microscopic bit of extra
effort to make a conforming program is not worth while.  Of course, my
imagination can be very limited.
--
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ ftp: ftp://rtfm.mit.edu, C-FAQ Book: ISBN 0-201-84519-9
Try "C Programming: A Modern Approach" ISBN 0-393-96945-2
Want Software?  Algorithms?  Pubs? http://www.infoseek.com


Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

Quote:

> Yes, it's wrong to use 'void main()'; but can you mention a case
> where it makes any difference? Generally speaking, it's a 'who cares?'
> kind of thing.

Ha! Tell that to myself and the legions of other gcc users in the world!
Observe:

        metroid$ cat tmp.c
        void main(void)
        {
                return;
        }
        metroid$ gcc -ansi -pedantic-errors tmp.c
        tmp.c: In function `main':
        tmp.c:2: return type of `main' is not `int'

Aha! See what happens when you invoke undefined behavior? gcc refuses to
translate the program!

It is not difficult to hypothesize about a machine where the consequences
of 'lying' to the compiler, and changing the type of a function like this
has more drastic effects.

You just don't get it, do you? It's undefined behavior. That means -we
don't do it-. Then again, you may enjoy having 0xDEADBEEF spewed all over
your hard drive. I don't know about you, but I sure don't.

--
(initiator of the campaign for grumpiness where grumpiness is due in c.l.c)

Attempting to write in a hybrid which can be compiled by either a C compiler
or a C++ compiler produces a compromise language which combines the drawbacks
of both with the advantages of neither.



Fri, 15 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers



Quote:

>Yes, it's wrong to use 'void main()'; but can you mention a case
>where it makes any difference? Generally speaking, it's a 'who cares?'
>kind of thing.

I notice you posted this from a machine running Linux, so you're
certainly aware of shell scripts and probably of return codes.  On my
Linux machine, if I do 'void main' then the return code turns out to
be whatever integer value was last returned from a function (which makes
perfect sense when you start thinking about the likely implementation,
but I don't feel like explaining it yet again).  Now visuialise using
that program in a script, or makefile, or anything else which used the
return code to determine success or failure.

Voila -- one extremely common case where it makes a difference.  (There
are probably many others.)

Cheers,
Richard
--
Richard Stamp
Churchill College, Cambridge



Sat, 16 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

I'm not arguing in favor of incorrectly declaring main() -
and I never do it. However, in the majority of instances,
it just doesn't matter. Yes, recursive calls to main() won't
have a valid prototype; that's not a very common thing to do.
And if you expect a valid return value from your program,
of course you should declare it correctly. In both these cases,
you'd KNOW that you want predictable behavior from main().

One person mentioned a system where a 'void main()' function
caused a system crash. I hope the system's designers have a
good rationalization for allowing that to happen.

I maintain that in the huge preponderence of cases, it doesn't
matter. But I'll continue to do it right.

/RF

Quote:



> >Yes, it's wrong to use 'void main()'; but can you mention a case
> >where it makes any difference? Generally speaking, it's a 'who cares?'
> >kind of thing.

> I notice you posted this from a machine running Linux, so you're
> certainly aware of shell scripts and probably of return codes.  On my
> Linux machine, if I do 'void main' then the return code turns out to
> be whatever integer value was last returned from a function (which makes
> perfect sense when you start thinking about the likely implementation,
> but I don't feel like explaining it yet again).  Now visuialise using
> that program in a script, or makefile, or anything else which used the
> return code to determine success or failure.

> Voila -- one extremely common case where it makes a difference.  (There
> are probably many others.)

> Cheers,
> Richard
> --
> Richard Stamp
> Churchill College, Cambridge



Sat, 16 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers

[ regarding the use of the forbidden "void main()" ]

|> I maintain that in the huge preponderence of cases, it doesn't
|> matter. But I'll continue to do it right.

A man lives in an extremely sparsely populated area.  Furthermore,
he works the graveyard shift, which means that he usually drives
to work during the late hours of night.  Driving to work on a
lonely country road, the man decides (for whatever reason) that
he is going to drive on the wrong side of the road from now on.

Now this is certainly a silly choice; after all, driving on the
wrong side of the road accomplishes nothing and saves no time in
the man's trip.  Furthermore, driving on the right side of the
road would require no more effort than driving on the wrong side.

Still, the area is remote, deserted and rarely-traveled, so the
man decides that it really doesn't matter *what* side of the road
that he drives on.  I mean, think about it .. what are the chances
that somebody is going to come along from the opposite direction
in this area, at this time of ni

*WHAM*

--
Chris Engebretson - Raytheon STX Corporation | Ph#: (605)594-6829
USGS EROS Data Center, Sioux Falls, SD 57198 | Fax: (605)594-6940

Opinions are not those of  Raytheon Systems Company  or the USGS.



Sat, 16 Sep 2000 03:00:00 GMT  
 problems with a string linked list program and pointers



Quote:
>One person mentioned a system where a 'void main()' function
>caused a system crash. I hope the system's designers have a
>good rationalization for allowing that to happen.

How about "you can't possibly do that"?  Older Amiga systems would
actually crash completely if you divided by zero.  If you don't like
this, you're welcome to not divide by zero.

It invokes undefined behavior; the implementor is hardly obliged to
take pains to make it "work".

Quote:
>I maintain that in the huge preponderence of cases, it doesn't
>matter. But I'll continue to do it right.

It probably doesn't.  Most of the time.  But, well, who wants software
to run *most* of the time?  In my utilities (I maintain a small suite
of utilities that I rely on heavily), something has to fail once to
justify me spending an entire afternoon making sure I understand the failure
and that it will never happen again.  Why?  Because, sooner or later, I'll
be trying to get something done under a brutal deadline, and I do *NOT* want
the "rare" case to come up again.  So, I make sure there isn't a rare case
where things fail.

Defensive programming R Us.

-s
--

C/Unix wizard, Pro-commerce radical, Spam fighter.  Boycott Spamazon!
Not speaking for my employer.  Questions on C/Unix?  Send mail for help.
Visit my new ISP <URL:http://www.plethora.net/> --- More Net, Less Spam!



Sat, 16 Sep 2000 03:00:00 GMT  
 
 [ 21 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Problems with linked lists and strings (char *)

2. link list of a linked list (chained links?)

3. Incompatible NULL Assignments || Linked List inside Linked List

4. Clearing Memory || Linked List INSIDE of a Linked List

5. Freeing a Linked List inside of a Linked List

6. Linked List of Linked Lists

7. Define a linked list of a linked list

8. Link List to Link List, HELP friends

9. Linked List with Void Pointers

10. Pointer, Linked List, Pass by Reference ???

11. Please check my Linked Lists and Pointers

12. Linked lists and pointers

 

 
Powered by phpBB® Forum Software