Quantcast

Maximum PC

It is currently Fri Oct 31, 2014 9:05 am

All times are UTC - 8 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Formating Output
PostPosted: Fri Aug 29, 2008 6:13 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
I have some data in a data structure that I want to print out in a nice looking format. Below is an example of the data:

Code:
:ARTIST "Metallica" :TITLE "The Black Album" :RATING 8
:ARTIST "van halen" :TITLE "van halen 2" :RATING 10
:ARTIST "van halen" :TITLE "van halen 1" :RATING 10
:ARTIST "GNR" :TITLE "Welcome" :RATING 10
:ARTIST "GNR" :TITLE "Patience" :RATING 8


Here is an example of the output:
Code:
  ARTIST: Metallica
  TITLE:  The Black Album
  RATING: 8

  ARTIST: van halen
  TITLE:  van halen 2
  RATING: 10

  ARTIST: van halen
  TITLE:  van halen 1
  RATING: 10

  ARTIST: GNR
  TITLE:  Welcome
  RATING: 10

  ARTIST: GNR
  TITLE:  Patience
  RATING: 8


And I don't want to write a lot of formatting code, so I didn't. Just one line of code... and nothing stupid like one super long hard-coded printf().

Do you know how I did it? Hopefully, it will cause you to think a bit about the print features that are available in your favorite language. I'll tell everyone a little later -- you can use any data structure that seems appropriate... array, 2dim array, list, stack, hash table, tree, whatever.


Top
  Profile  
 
 Post subject:
PostPosted: Sat Aug 30, 2008 11:05 am 
Team Member Top 100
Team Member Top 100

Joined: Fri Sep 17, 2004 5:35 pm
Posts: 1176
std::cout << "\tARTIST\t" << artist << "\nTITLE\t" << title << "\nRATING\t" << rating << std::endl << std::endl;

How about one fairly long cout?


Top
  Profile  
 
 Post subject:
PostPosted: Mon Sep 01, 2008 10:08 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
Hey Kybo-Ren,

Sure, the cout will print a single record, but what I was getting at was printing an entire list of records (or whatever ADT you choose to contain the records). Lisp happens to have a very powerful print statement that can do this type of thing... I've stolen the example from the 3rd chapter of Practical Common Lisp by Peter Seibel which you can find online. Here is the line of code...

Code:
(format t "~{~{~a:~10t~a~%~}~%~}" *db*))


The *db* is a list of lists where the outer list is a standard list and the inner lists are a Lisp data structure called a plist (property list). Each record is literally something like...

Code:
(:ARTIST "artist name" :TITLE "title" :RATING 10)


The format command is similiar to printf() -- see below for a simple example. The t arguement in the format command is short-hand for printing to standard output. The outer pair of curly braces in the qoute iterate over the outer list. The inner pair of curlies iterate over each record. The first ~a prints the property from the plist (ARTIST, TITLE OR RATING) and then the ~10t tells the command to add enough spaces to start the next ~a at the 10 column of output. The next ~a is the actual name of the artist, title or rating. The ~% are used for newlines.

Pretty cool, eh? =)

(format t "~4t~a~12t~a~%" var1 var2) ; prints var1 starting at col4 and var2 starting at col12


Top
  Profile  
 
 Post subject:
PostPosted: Tue Sep 02, 2008 1:57 pm 
Team Member Top 100
Team Member Top 100

Joined: Fri Sep 17, 2004 5:35 pm
Posts: 1176
Oh, OK. Yeah, that is pretty nifty, but I think it would just be too concise for me. As in, I'd like some easier-to-read code (i.e. not having to know immediately what a bunch of symbols strung together means)

Assuming we have a std::vector of Record objects:
Code:
struct Record{
std::string artist;
std::string title;
std::string rating;};


then we can say
Code:
for(std::vector<Record>::size_type i = 0; i < my_records.size(); ++i)
std::cout << "\tARTIST\t" << my_records[i].artist << "\nTITLE\t" << my_records[i].title << "\nRATING\t" << my_records[i].rating << std::endl << std::endl;

Technically it will compile all on one line :o


Top
  Profile  
 
 Post subject:
PostPosted: Tue Sep 02, 2008 8:28 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
I think you may have bumped your head if you believe that is easier to read. =)


One of the nifty things about the collections in Common Lisp is that you're able to use the same functions for many of the types (ie vectors, strings -- a vector and lists are all sequences). So you can...

Code:
(let ((vec #(a b c a b c)) (lis '(a b c a b c)) (str "abcabc"))
           (print (remove 'a vec))
           (print (remove 'a lis))
           (print (remove #\a str)))
;notice that I used #\a for the string -- #\ indicates a character
;(a b c) is a list and #(a b c) is a vector

#(B C B C)
(B C B C)
"bcbc"



There are quite a few more possibilities. I suspect that writing foo (below) in C++ so that you can call it with an array, vector or string will take quite a few more SLOC. Of course, the same is probably going to be true of most other languages.

Code:
(defun foo (remove-this sub-this sub-for-this count-this start-subsq end-subsq search-for items)
           (print (remove remove-this items))
           (print (substitute sub-this sub-for-this items))
           (print (count count-this items))
           (print (subseq items start-subsq end-subsq))
           (print (search search-for items))
           (format t "~%"))

(let ((vec #(a b c a b c)) (lis '(a b c a b c)) (str "abcabc"))
           (foo 'a 'b 'c 'c 3 5 '(c a b) vec)
           (foo 'a 'b 'c 'c 3 5 #(c a b) lis)
           (foo #\a #\b #\c #\c 3 5 "cab" str))

#(B C B C)
#(A B B A B B)
2
#(A B)
2

(B C B C)
(A B B A B B)
2
(A B)
2

"bcbc"
"abbabb"
2
"ab"
2


Top
  Profile  
 
 Post subject:
PostPosted: Wed Sep 03, 2008 2:18 am 
Team Member Top 100
Team Member Top 100

Joined: Fri Sep 17, 2004 5:35 pm
Posts: 1176
*shrug* maybe it's because C is my second language :lol:

Well C++ does have similar abilities. In fact, that was one of the driving reasons for the development of the STL. I'm sure you're familiar with it, though, so I won't go into it.

I think there's a real trade-off between brevity and readability. At least to me, what I wrote is specific and lengthy in just such a way that makes it more readable than your (shorter) code.

Just for fun, I wrote the equivalent C++/STL code:
Code:

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <deque>

template <class Container>
void print(const Container &input){
   for(typename Container::size_type i = 0; i < input.size(); ++i)
      std::cout << input[i] << " ";
   std::cout << std::endl;
}

template <class Container, class Elem>
void foo(const Elem &remove_this, const Elem &sub_this, const Elem &sub_for_this, const Elem &count_this,
   typename Container::size_type const &start, typename Container::size_type const &end, const Container &sub, const Container &structure){

   Container copy;

   {
      copy = structure;
      typename Container::iterator it = std::remove(copy.begin(), copy.end(), remove_this);
      copy.erase(it, copy.end());//since remove only changes the end of the range, it doesn't actually erase them, so we erase them here
      print(copy);
   }

   {
      copy = structure;
      std::replace(copy.begin(), copy.end(), sub_for_this, sub_this);
      print(copy);
   }

   {
      copy = structure;
      unsigned int count = static_cast<unsigned int>(std::count(copy.begin(), copy.end(), count_this));
      std::cout << count << std::endl;
   }

   {
      copy = structure;
      Container sub(end-start, 0);
      std::copy(copy.begin() + start, copy.begin() + end, sub.begin());
      print(sub);
   }

   {
      copy = structure;
      unsigned int position = static_cast<unsigned int>(std::search(copy.begin(), copy.end(), sub.begin(), sub.end()) - copy.begin());
      std::cout << position << std::endl;
   }
}

int main(){
   char data[] = {'a', 'b', 'c', 'a', 'b', 'c', 0};
   char subsequence[] = {'c', 'a', 'b', 0};

   {
      std::vector<char> vec(data, data + 6);
      std::vector<char> sub(subsequence, subsequence + 3);
   
      foo('a', 'b', 'c', 'c', 3, 5, sub, vec);
   }

   std::cout << std::endl;

   {
      std::deque<char> lis(data, data + 6);
      std::deque<char> sub(subsequence, subsequence + 3);

      foo('a', 'b', 'c', 'c', 3, 5, sub, lis);
   }
   
   std::cout << std::endl;

   {
      std::string str = data;
      std::string sub = subsequence;

      foo('a', 'b', 'c', 'c', 3, 5, sub, str);
   }

}



Output:
Code:
b c b c
a b b a b b
2
a b
2

b c b c
a b b a b b
2
a b
2

b c b c
a b b a b b
2
a b
2


Of course, because of all the template trickery, this is nigh unreadable :lol:


Top
  Profile  
 
 Post subject:
PostPosted: Wed Sep 03, 2008 9:53 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
I think that the C++ code may be a little less compact (and I won't mention potential issues with your sanity). =)

I'll see if I can come up short, but more complex, over the weekend that'll give you some problems in C++. I'm thinking a program to find the complex hull of a set of points should be an interesting problem.


Top
  Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

© 2014 Future US, Inc. All rights reserved.