EbookManager program: Struct & Pointers 
Author Message
 EbookManager program: Struct & Pointers

Hi.

I'm writing a ebook manager for Linux. There's problem, though. For the
following code:
-----------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct author {
  char *name;

  struct book *b;
  struct author *prev;
  struct author *next;

Quote:
} *curr, *first;

struct book {
  char *title;
  int noOfVersions;
  short int frontcover;
  short int backcover;
  FILE *rawbook;

  struct author *a;
  struct book *prev;
  struct book *next;

Quote:
};

int scanBookList();
int newBook();
int removeBook();
int newAuthor(struct author *target, char *authorname);
int removeAuthor(struct author *target);

int newAuthor(struct author *target, char *authorname) {
  /*A new author will have NULL books*/
  /*Tip: Transparent activity: If a non-empty target is passed,
overwrite it*/

  struct author *tmp;

  if (target == NULL) {
    tmp = malloc(sizeof(struct author));

    if (tmp == NULL) {
      return;
    }
    else {
      target = (struct author *)tmp;
    }

    target->name = authorname; /*Pointing, not copying*/
    target->b = NULL;
    target->prev = NULL;
    target->next = NULL;

    return 1;
  }
  else {
    return 0;
  }

Quote:
}

int removeAuthor(struct author *target) {

  if (target != NULL) {
    target->name = NULL;

    target->b = NULL; /*loop over all books with removeBook*/

    /*Detach Author from list*/
    if (target->prev != NULL) {
      target->prev->next = target->next;
    }
    if (target->next != NULL) {
      target->next->prev = target->prev;
    }

    free(target);
    return 1;
  }

  return 1;

Quote:
}

int main () {
  char n[30];
  strcpy(n, "D H Lawrence");

  if (newAuthor(curr, n)) {

    printf("Author successfully added\n");

    if (curr != NULL) {
      printf("Author's Name is: %s\n", curr->name);
    }

    if (removeAuthor(curr)) {
      printf("Author successfully deleted from memory\n");
    }

  }

Quote:
}

---

The Error is this: After the newAuthor function is called, curr is still
NULL. Why is this ???

Any help is appreciated,

Best Regards,

Ahsan

--
Posted via Mailgate.ORG Server - http://www.*-*-*.com/



Wed, 02 Feb 2005 19:54:07 GMT  
 EbookManager program: Struct & Pointers


Quote:
>Hi.

>I'm writing a ebook manager for Linux. There's problem, though. For the
>following code:
>-----------
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>#include <ctype.h>

>struct author {
>  char *name;

>  struct book *b;
>  struct author *prev;
>  struct author *next;
>} *curr, *first;

>int newAuthor(struct author *target, char *authorname);
>int removeAuthor(struct author *target);

>int newAuthor(struct author *target, char *authorname) {
>  /*A new author will have NULL books*/
>  /*Tip: Transparent activity: If a non-empty target is passed,
>overwrite it*/

>  struct author *tmp;

>  if (target == NULL) {
>    tmp = malloc(sizeof(struct author));

>    if (tmp == NULL) {
>      return;
>    }
>    else {
>      target = (struct author *)tmp;
>    }

>    target->name = authorname; /*Pointing, not copying*/
>    target->b = NULL;
>    target->prev = NULL;
>    target->next = NULL;

>    return 1;
>  }
>  else {
>    return 0;
>  }
>}

>int removeAuthor(struct author *target) {

>  if (target != NULL) {
>    target->name = NULL;

>    target->b = NULL; /*loop over all books with removeBook*/

>    /*Detach Author from list*/
>    if (target->prev != NULL) {
>      target->prev->next = target->next;
>    }
>    if (target->next != NULL) {
>      target->next->prev = target->prev;
>    }

>    free(target);
>    return 1;
>  }

>  return 1;
>}

>int main () {
>  char n[30];
>  strcpy(n, "D H Lawrence");

>  if (newAuthor(curr, n)) {

>    printf("Author successfully added\n");

>    if (curr != NULL) {
>      printf("Author's Name is: %s\n", curr->name);
>    }

>    if (removeAuthor(curr)) {
>      printf("Author successfully deleted from memory\n");
>    }

>  }
>}
>---

>The Error is this: After the newAuthor function is called, curr is still
>NULL. Why is this ???

The local variable 'target in newAuthor is a copy of 'curr' because curr
is passed by value. Thus, although newAuthor changes 'target' it does
not change 'curr'.

To fix this, pass in a pointer to the pointer itself and work with that
as in:

int newAuthor(struct author **target, char *authorname) {
  /*A new author will have NULL books*/
  /*Tip: Transparent activity: If a non-empty target is passed,
overwrite it*/

  if (*target == NULL) {
    struct author *tmp; /* moved to keep scope as local as possible */

    tmp = malloc(sizeof(struct author));

    if (tmp == NULL) {
      return;
    }

    /* I'm continuing to use tmp in order to avoid repeated
       dereferencing of target - probably does not make much difference
       to performance as a good compiler will look after this for you
       but it looks neater*/

    tmp->name = authorname; /*Pointing, not copying*/
    tmp->b = NULL;
    tmp->prev = NULL;
    tmp->next = NULL;

    *target = tmp;

    return 1;
  }
  else {
    return 0;
  }

Quote:
}

and call it from main() like this:

int main () {
  char n[30];
  strcpy(n, "D H Lawrence");

  if (newAuthor(&curr, n)) {

    printf("Author successfully added\n");

    if (curr != NULL) {
      printf("Author's Name is: %s\n", curr->name);
    }

    /* do remaining stuff here
    ...
    ...
    */
  }

Quote:
}

A similar problem exists with removeAuthor.

--
Wade Oram



Wed, 02 Feb 2005 20:40:38 GMT  
 EbookManager program: Struct & Pointers

[The following lines were not contiguous originally.]

Quote:
> struct author {
> } *curr, *first;
> int newAuthor(struct author *target, char *authorname) {
>       target = (struct author *)tmp;
> }
> int main () {
>   if (newAuthor(curr, n)) {
>   }
> }
> The Error is this: After the newAuthor function is called, curr is still
> NULL. Why is this ???

When main calls newAuthor(curr, n), C effectively copies the
value of the curr pointer to the local variable target in
newAuthor.  Changes made to target do not affect curr.

The usual fix is to pass the address of the variable instead.
This requires three changes:

1. Define the parameters of newAuthor like this:

  int newAuthor(struct author **ptarget, char *authorname)

2. In the body of newAuthor, use *ptarget instead of target.

  *ptarget = (struct author *)tmp;
  /* The cast is actually not necessary, as tmp has the correct
     type already.  That is not related to your problem, though.  */

  (*ptarget)->name = authorname; /*Pointing, not copying*/
  (*ptarget)->b = NULL;
  (*ptarget)->prev = NULL;
  (*ptarget)->next = NULL;
  /* You could use tmp-> instead.  */

3. Call newAuthor like this:

  newAuthor(&curr, n)



Wed, 02 Feb 2005 20:27:30 GMT  
 EbookManager program: Struct & Pointers


Quote:
> Hi.

> I'm writing a ebook manager for Linux. There's problem, though. For the
> following code:
> -----------
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <ctype.h>

> struct author {
>   char *name;

>   struct book *b;
>   struct author *prev;
>   struct author *next;
> } *curr, *first;

> struct book {
>   char *title;
>   int noOfVersions;
>   short int frontcover;
>   short int backcover;
>   FILE *rawbook;

>   struct author *a;
>   struct book *prev;
>   struct book *next;
> };

> int scanBookList();
> int newBook();
> int removeBook();
> int newAuthor(struct author *target, char *authorname);
> int removeAuthor(struct author *target);

> int newAuthor(struct author *target, char *authorname) {
>   /*A new author will have NULL books*/
>   /*Tip: Transparent activity: If a non-empty target is passed,
> overwrite it*/

>   struct author *tmp;

>   if (target == NULL) {
>     tmp = malloc(sizeof(struct author));

>     if (tmp == NULL) {
>       return;

Other people have answered your other question, but I noticed this.  You
should return 0 here since this function returns an int.

Also, let me present another solution to your problem.  Instead of passing
in the pointer to the pointer as other people suggested, why not use the
return value of the function to return the pointer value?

So you would "return NULL;" if something went wrong.  But if memory was
allocated and everything went right, just "return tmp;", instead of "return
1;"  And the check you make on the return of the function call remains the
same!  Any non-zero pointer value will be considered a logical TRUE.  And if
you return NULL as a failure, it will be considered a logical FALSE.

In my opinion, it looks alot cleaner to do it this way.  But it's all a
question of personal preference.

- Show quoted text -

Quote:
>     }
>     else {
>       target = (struct author *)tmp;
>     }

>     target->name = authorname; /*Pointing, not copying*/
>     target->b = NULL;
>     target->prev = NULL;
>     target->next = NULL;

>     return 1;
>   }
>   else {
>     return 0;
>   }
> }



Wed, 02 Feb 2005 23:36:21 GMT  
 EbookManager program: Struct & Pointers


Quote:



> > Hi.

> > I'm writing a ebook manager for Linux. There's problem, though. For the
> > following code:
> > -----------
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <string.h>
> > #include <ctype.h>

> > struct author {
> >   char *name;

> >   struct book *b;
> >   struct author *prev;
> >   struct author *next;
> > } *curr, *first;

> > struct book {
> >   char *title;
> >   int noOfVersions;
> >   short int frontcover;
> >   short int backcover;
> >   FILE *rawbook;

> >   struct author *a;
> >   struct book *prev;
> >   struct book *next;
> > };

> > int scanBookList();
> > int newBook();
> > int removeBook();
> > int newAuthor(struct author *target, char *authorname);
> > int removeAuthor(struct author *target);

> > int newAuthor(struct author *target, char *authorname) {
> >   /*A new author will have NULL books*/
> >   /*Tip: Transparent activity: If a non-empty target is passed,
> > overwrite it*/

> >   struct author *tmp;

> >   if (target == NULL) {
> >     tmp = malloc(sizeof(struct author));

> >     if (tmp == NULL) {
> >       return;

> Other people have answered your other question, but I noticed this.  You
> should return 0 here since this function returns an int.

> Also, let me present another solution to your problem.  Instead of passing
> in the pointer to the pointer as other people suggested, why not use the
> return value of the function to return the pointer value?

> So you would "return NULL;" if something went wrong.  But if memory was
> allocated and everything went right, just "return tmp;", instead of
"return
> 1;"  And the check you make on the return of the function call remains the
> same!  Any non-zero pointer value will be considered a logical TRUE.  And
if
> you return NULL as a failure, it will be considered a logical FALSE.

> In my opinion, it looks alot cleaner to do it this way.  But it's all a
> question of personal preference.

Just a small addition.  Of course if you follow my suggestion, you'll have
to change the return type of the function from "int" to "struct author *".
And your function cal l will look like:

curr=newAuthor(n)

                    Dan



Wed, 02 Feb 2005 23:39:13 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. cast pointer to struct to pointer to type of first member of struct

2. pointers to functions in structs which take a pointer to that struct as an arg

3. More help with structs & pointers

4. pointers & structs

5. Struct & pointer problem

6. pointer & struct

7. qsorting & managing struct arrays, pointer arrays

8. Pointer & struct

9. ary of pointer to structs & functions

10. Struct & malloc problem : pointer expected

11. switch & pointers to structs

12. Help with structs & pointers

 

 
Powered by phpBB® Forum Software