1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C: Printing specific elements of a structure

  1. Aug 19, 2015 #1
    1. The problem statement, all variables and given/known data
    I have the following code which manipulates with basics of structures.
    There are function like reading and sorting data from structures.

    Now, I don't know how to write a function that reads name and surname of an author of a book,
    and then prints data about books that are from read author.
    Prototype of a function is
    Code (Text):
    void print(BOOK *pb,int n,char *p_surname,char *p_name)
    2. Relevant equations
    -Structures
    -Pointers

    3. The attempt at a solution
    Code (Text):

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

    typedef struct
    {
      char surname[20];
      char name [20];
    }AUTHOR;

    typedef struct
    {
      char title[20];
      int year;
      int number_of_authors;
      AUTHOR *author;
    }BOOK;

    void read_author(AUTHOR *pa)
    {
      printf("surname:");
      scanf("%s",pa->surname);
      printf("name:");
      scanf("%s",pa->name);

    }

    void read_book(BOOK *pb)
    {
      printf("title:");
      scanf("%s",pb->title);
      printf("publish year:");
      scanf("%d",&pb->year);
      printf("number of authors:");
      scanf("%d",&pb->number_of_authors);
      pb->author=calloc(pb->number_of_authors,sizeof(*pb->author));
      int i;
      for(i=0;i<pb->number_of_authors;i++)
      {
      printf("%d. authors:\n",i+1);
      read_author(pb->author+i);
      }
    }

    int compare_authors(AUTHOR *a,AUTHOR *b)
    {
      int i;
      for(i=0;a->surname[i] && a->surname[i] == b->surname[i];i++);
      return a->surname[i]-b->surname[i];
    }

    void sort_authors(AUTHOR *array,int n)
    {
      int i,j;
      for(i=0;i<n-1;i++)
      for(j=i+1;j<n;j++)
      if(compare_authors(array+i,array+j)>0)
      {
      AUTHOR temp=array[i];
      array[i]=array[j];
      array[j]=temp;
      }
    }

    int compare_books(BOOK *a,BOOK *b)
    {
      int i;
      for(i=0;a->title[i] && a->title[i] == b->title[i];i++);
      return a->title[i]-b->title[i];
    }

    void sort_books(BOOK *array,int n)
    {
      int i,j;
      for(i=0;i<n-1;i++)
      for(j=i+1;j<n;j++)
      {
      if(compare_books(array+i,array+j)>0)
      {
      BOOK temp=array[i];
      array[i]=array[j];
      array[j]=temp;
      }
      else
      if((compare_books(array+i,array+j) == 0) )
      {
      BOOK temp=array[i];
      array[i]=array[j];
      array[j]=temp;
      }

      }
    }

    int main()
    {
      int i,n;
      BOOK *array;
      char psurname[101],pname[101];
      do
      {
      printf("n=");
      scanf("%d",&n);
      }
      while(n<1);
      array=(BOOK *)malloc(n*sizeof(BOOK));
      printf("enter books:\n");
      for(i=0;i<n;i++)
      {
      printf("%d. book:\n",i+1);
      read_book(array+i);
      }
      sort_books(array,n);
      free(array);
      return 0;
    }
     
    I don't know how to write a function for printing data about books that are from input author:
    Code (Text):

    void print(BOOK *pb,int n,char *psurname,char *pname)
    {
      int i,j;
      scanf("%s",psurname);
      scanf("%s",pname);
      for(i=0;i<n;i++)
      {
      for(j=0;j<pb->number_of_authors;j++)
      {
      if((compare_authors(pb->author[j].surname,psurname)== 0) &&
      (compare_authors(pb->author[j].name,pname)==0))
      printf("%s %d %d %s %s",pb->title,pb->year,pb->number_of_authors,
      pb->author[j].surname,pb->author[j].name);
      }
      }
    }
     
    Could someone help with this function?
    Thanks for replies.
     
  2. jcsd
  3. Aug 19, 2015 #2

    SteamKing

    User Avatar
    Staff Emeritus
    Science Advisor
    Homework Helper

    You'll have to make an attempt at writing your own function. Those are the rules for the HW forums at PF, even for programmers.

    It's not clear what is the problem here. Are you trying to list the works by an author having a certain name?

    It seems that if you have a particular name to search for, you should search through your database, and every time a hit is made on the author's name, you extract and print the corresponding book title.
     
  4. Aug 19, 2015 #3

    Zondrina

    User Avatar
    Homework Helper

    I notice there are several errors in the functions you have wrote.

    --------------------

    First, the read_book function is not written properly:

    Code (Text):

    void read_book(BOOK *pb)
    {
      printf("title:");
      scanf("%s",pb->title);
      printf("publish year:");
      scanf("%d",&pb->year);
      printf("number of authors:");
      scanf("%d",&pb->number_of_authors);

      pb->author=calloc(pb->number_of_authors,sizeof(*pb->author));
      int i;
      for(i=0;i<pb->number_of_authors;i++)
      {
      printf("%d. authors:\n",i+1);
      read_author(pb->author+i);
      }
    }
     
    1. Why do you compute so many unnecessary pointers when reading in the year and number of authors?

    2. When setting up the author(s), why not use a simple malloc call to allocate the appropriate amount of authors, i.e malloc(sizeof(AUTHOR)*pb->number_of_authors). It is simpler than a calloc call, and avoids typecasting altogether. The only problem is the way the elements are initialized, so you have to be careful. Then you can use your loop and read_author function to assign a name and surname to each author.

    --------------------

    Second, the function you wrote that compares two authors is wrong:

    Code (Text):

    int compare_authors(AUTHOR *a,AUTHOR *b)
    {
      int i;
      for(i=0;a->surname[i] && a->surname[i] == b->surname[i];i++);
      return a->surname[i]-b->surname[i];
    }
     
    1. Should you not compare the name and the surname? Try returning 1 if the name and surname are equal for both authors, and 0 otherwise. You could also import <stdbool.h> and return a _Bool instead.

    2. While it may be inefficient, the 'easiest' way think about this is to compare each name and surname char by char using a loop. If the loop executes fully, then return true. If one of the chars don't match, return false.

    --------------------

    Third, I think some improvements can be made to the bubble sort you used for the sort_authors function:

    Code (Text):

    void sort_authors(AUTHOR *array,int n)
    {
      int i,j;
      for(i=0;i<n-1;i++)
      for(j=i+1;j<n;j++)
      if(compare_authors(array+i,array+j)>0)
      {
      AUTHOR temp=array[i];
      array[i]=array[j];
      array[j]=temp;
      }
    }
     
    1. See this link for details: https://en.wikipedia.org/wiki/Bubble_sort#Optimizing_bubble_sort

    --------------------

    Fourth, your compare_books function has the same problem as the compare_authors function:

    Code (Text):

    int compare_books(BOOK *a,BOOK *b)
    {
      int i;
      for(i=0;a->title[i] && a->title[i] == b->title[i];i++);
      return a->title[i]-b->title[i];
    }
     
    1. See the advice I gave you for compare_authors because the solution is similar.

    --------------------

    Fifth, you are using bubble sort for sort_books again and improvements can be made:

    Code (Text):

    void sort_books(BOOK *array,int n)
    {
      int i,j;
      for(i=0;i<n-1;i++)
      for(j=i+1;j<n;j++)
      {
      if(compare_books(array+i,array+j)>0)
      {
      BOOK temp=array[i];
      array[i]=array[j];
      array[j]=temp;
      }
      else
      if((compare_books(array+i,array+j) == 0) )
      {
      BOOK temp=array[i];
      array[i]=array[j];
      array[j]=temp;
      }

      }
    }
     
    1. Once again, see this link for details: https://en.wikipedia.org/wiki/Bubble_sort#Optimizing_bubble_sort

    --------------------

    So you want to read in the name and a surname of an author. Then you want to loop through an array of books. If the name and surname entered match the name and surname of the author of the book, then you want to print information about the book.

    Is that correct?

    If so, then I don't see the reason to use this prototype:

    Code (Text):
    void print(BOOK *pb, int n, char *psurname, char *pname)
    Why do you need the char pointers? If you are reading in the name and surname inside the function, then all you have to do is compare the name and surname you read in to the name and surname of the author of the book. Instead the prototype should be:

    Code (Text):
    void print(BOOK *pb, int n)
    Where the parameter ##n## is the size of the book array. You have to loop over all the books, and make sure to check all of the authors for each book.

    Whew, that's quite a bit of coding to do, but feel free to ask questions if you get stuck.
     
    Last edited: Aug 19, 2015
  5. Aug 19, 2015 #4

    Mark44

    Staff: Mentor

    Because scanf() requires the address of an input buffer for all of the variables it is used to read.
    No. The returned value from both calloc() and malloc() is a void pointer, so C code should cast the returned value to the appropriate type. Also, the main difference between these two functions is that calloc() returns a block of memory that is initialized to zero.
    Zondrina apparently didn't notice, but whatever strings you're comparing, you can't use == to compare them. In C, a string (i.e., a char * type) evaluates to the location in memory of the first character, so the comparisons above are comparing addresses, not the contents of two strings.

    Although it is fairly easy to write a loop and compare the two strings character by character, it's probably safer to use the standard library function strcmp() or one of its variants.
    Again, that's not how to compare strings.
     
  6. Aug 19, 2015 #5

    Zondrina

    User Avatar
    Homework Helper

    I've been coding in java too often. I forgot scanf() requires a pointer to be computed. I wonder if they will ever write a version where you don't have to pass an address.

    I forgot the return types of those as well, gosh its been a while since I've done C. I do remember the main difference was the way the memory is initialized though.

    I know you can't use '==' to compare strings since it compares by reference. For example, in java we use equals() in class String to compare two String objects. The OP is the person unaware I believe.

    I assumed the OP has no knowledge of standard library functions considering the code I've seen so far. So I provided the OP with a relatively simple thought process instead.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: C: Printing specific elements of a structure
Loading...