9

I have a structured a data type called bookStruct and books is the name of the variable associated with the bookStruct data type. book[10] is the array that is 10 characters long and has 4 characters of data, meaning book[0] to book [3] have datas in them when the rest are empty (o values). Now I want to print the datas that are availabe already in the array and not print the ones that are empty otherwise 0. I tried the below code, with no luck.What am I doing wrong here?

for (int i=0;i<MAX_BOOKS && books[i]!='\0';i++)
            {
                cout << "Book Title: " << books[i].bookTitle << endl;
                cout << "Total Pages: " << books[i].bookPageN << endl;
                cout << "Book Review: " << books[i].bookReview << endl;
                cout << "Book Price: " << books[i].bookPrice<< "\n\n" << endl;
            }

here is the declaration for book struct

struct bookStruct
{
    string bookTitle;
    int bookPageN;
    int bookReview;
    float bookPrice;
};

bookStruct books[10];
14
  • 1
    Can you add the code that declares the struct? Commented Feb 4, 2013 at 21:18
  • Can you also show your declaration of books? I'm having trouble understanding your description of it. Commented Feb 4, 2013 at 21:19
  • 4
    && books[i]!='\0' why do you have that in the condition? Commented Feb 4, 2013 at 21:19
  • 1
    Please explain what "with no luck" means. Does it compile? Does it print anything and, in that case, what? Commented Feb 4, 2013 at 21:23
  • 1
    A better way to loop through an array was posted below as answer, you should check that out Commented Feb 4, 2013 at 21:32

4 Answers 4

22

Overload the output operator. E.g:

struct Book {
    string title;
    int pageN;
    int review;
    float price;
};

ostream& operator<<(ostream& os, const Book& book) {
    return os << "Title: " << book.title << endl
              << "Pages: " << book.pageN << endl
              << "Review: " << book.review << endl
              << "Price:" << book.price << endl;
}

Then you can output to any stream:

Book book;
ostringstream oss;
oss << book;

To loop over all your books, copying to std::cout, only when a book has a title, you need std::copy_if:

bool bookHasTitle(const Book& book) {
    return book.title.empty() == false;
}

Book books[10];

copy_if(books, books+10, ostream_iterator<Book>(cout, "\n"),
        bookHasTitle);
Sign up to request clarification or add additional context in comments.

2 Comments

+1 But this might be a bit advanced for someone who is clearly coming to grips with the basics.
I don't know, often times seeing the right way to do things helps you see the bigger picture. I don't fiddle around with loops as I know I get them wrong. I try to compartmentalise my code so I can reuse it. These are simple lessons to learn, and to keep aggressively applying during your programming career. That's what I try to do in all my answers, rather than getting dragged back to my old ways of doing things.
4

It's a little hard to tell what's being asked here. You see, it's quite easy to just keep count of how many books you have stored:

int numBooks = 0;

When you add a book, you increment numBooks up until MAX_BOOKS.

for( int i=0; i<numBooks; i++ ) ...

If you don't want to do that, you certainly can't test books[i] != '\0' because that is testing the struct against a single character.

Instead, you might want to test books[i].bookTitle.size() != 0

(or indeed !books[i].bookTitle.empty()).

for( int i=0; i<MAX_BOOKS && !books[i].bookTitle.empty(); i++ ) ...

Another alternative is to store books in a vector instead of an array, so you don't have to worry about maximum counts and current counts. The vector can shrink and grow for you.

vector<bookStruct> books;

...

for( int i = 0; i < books.size(); i++ ) ...

3 Comments

Thank you, the second option is more convenient.
According to this : eli.thegreenplace.net/2003/12/26/… you can initialize all the structs in the array to 0.
@ravloony I don't believe that is relevant because this struct is not POD (there is a string). Utilizing the default constructor of a string should be sufficient.
0
#include <iostream>
using namespace std;
struct bookStruct
{
    string bookTitle;
    int bookPageN;
    int bookReview;
    float bookPrice;
    void set(string t,int pn,int r,float pr){
        bookTitle = t;
        bookPageN = pn;
        bookReview = r;
        bookPrice = pr;
    }
};



ostream& operator << (ostream& os, const bookStruct& book)
{
   return os << "Title: " << book.bookTitle <<
              " Pages: " << book.bookPageN << 
               " Review: " << book.bookReview 
              << " Price:" << book.bookPrice << endl;
}

int main() { 
     bookStruct books[10];
     for(int i =0;i<10;i++){
         books[i].set("Book " + to_string(i),i*20,i,(float) i*54);
     }
     for(int i=0;i<10;i++){
         cout << books[i];
     }
    return 0;
}

Output:::

Title: Book 0 Pages: 0 Review: 0 Price:0
Title: Book 1 Pages: 20 Review: 1 Price:54
Title: Book 2 Pages: 40 Review: 2 Price:108
Title: Book 3 Pages: 60 Review: 3 Price:162
Title: Book 4 Pages: 80 Review: 4 Price:216
Title: Book 5 Pages: 100 Review: 5 Price:270
Title: Book 6 Pages: 120 Review: 6 Price:324
Title: Book 7 Pages: 140 Review: 7 Price:378
Title: Book 8 Pages: 160 Review: 8 Price:432
Title: Book 9 Pages: 180 Review: 9 Price:486

Comments

0

Use a friend function to customize your print. Then just trigger a loop on your records. C++20 required for using ranges.

    struct bookStruct
    {
        std::string bookTitle;
        int bookPageN;
        int bookReview;
        float bookPrice;
    
        friend std::ostream& operator<<(std::ostream& os, const bookStruct& book)
        {
            if (!book.bookTitle.empty()) //Ensure title exists.
            {
                return os << std::endl << "Book Title: " << book.bookTitle << std::endl
                    << "Total Pages: " << book.bookPageN << std::endl
                    << "Book Review: " << book.bookReview << std::endl
                    << "Book Price: " << book.bookPrice << std::endl;
            }
            else
            {
                return os;
            }
        }
    };
    
    int main()
    {
        //Input - four records
        const std::vector<bookStruct> books{ {"book1",200,2,2000.00}, {"book2",400,4,4000.00},
                                             {"",0,0,0.0},{"",0,0,0.0} };
    
        std::ranges::for_each(books, [](auto book) {std::cout << book; });
    
        return 0;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.