Talk About Network

Google


Register and Login
Nick
Password
Register create new account Sign up is FREE and you can post replies, new topics, bookmark posts and more!
Recover lost password


Programming > C++ Moderated > Re: Dynamically...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 4 of 8 Topic 9582 of 9831
Post > Topic >>

Re: Dynamically read string

by Oncaphillis <oncaphillis@[EMAIL PROTECTED] > May 9, 2008 at 09:24 AM

howa wrote:

> Hi,
> 
> Are there any simple method to read string into dynamic array of
> string, e.g. char**

Juggling with char* or char** isn't very C++'ish. Normally you
would solve these kind of stuff with
std::(vector|list|any other container of your liking)<std::string>.
But since you insist and since it's a C++ group I would suggest
the following C++'ish approach.

To keep the number of calls to new char[] as small as possible you might
maintain a list of char chunks of a appropriate size. Ideally enough
space to hold all chars of all expected strings.

Write characters into these chunks until they are filled up and
allocate a new chunk whenever there isn't enough space left.

If you happen to read a string with a length exceeding  the default
chunk size you have to allocate a private chunk for this one
string.

In an array of char * you also have to remember the starting position
of the current string. This array may have to be re-sized before
overflowing.

<snip>

#include <iostream>
#include <list>
#include <boost/shared_ptr.hpp>
#include <memory>

class charBucket {
public:
   enum {
     stdChunkSize = 1000,
     stdPtrSize   = 1000
   };

   charBucket() : size(0),
     max_size(stdPtrSize),ptrs(new const char *[stdPtrSize]) {
     ptrs[0]=NULL;
   }

   void put(const std::string &s) {

     boost::shared_ptr<chunk>  c;

     if(s.length()+1 > stdChunkSize ) {
       chunks.push_front(
            boost::shared_ptr<chunk>( new chunk(s.length()+1) ) );
       c = chunks.front();

     } else {
       if(chunks.empty() ||
         (size_t)(chunks.back()->e-chunks.back()->p) < (s.length()+1) ) {
         chunks.push_back( boost::shared_ptr<chunk>(new
chunk(stdChunkSize)) );
       }
       c = chunks.back();
     }
     put_ptr(c->p);
     ::strncpy(c->p,s.c_str(),s.length()+1);
     c->p+=s.length()+1;
   }

   const char ** get() const {
     return ptrs;
   }

private:

   charBucket(const charBucket &);

   // Add a char * to ptrs. Resize if necessary

   void put_ptr(const char *p) {
     if(size == max_size-1) {
       max_size+=stdPtrSize;
       const char ** np = new const char *[max_size];
       for(int i=0;i<size;i++) {
         np[i]=ptrs[i];
       }
       delete[] ptrs;
       ptrs=np;
     }
     ptrs[size++]=p;
     ptrs[size]=NULL;
   }

   // A inner class represents a chunk of
   // char. b == beginning, e==end, p==current put pointer
   class chunk {
   public:
     chunk(int s) : b(new char[s]),p(b),e(b+s) {
     }
     ~chunk() {
       delete[] b;
     }
     char *b;
     char *p;
     char *e;
   private:
     chunk(const chunk &);
     chunk();
   };

   // List of shared_ptr to chunk
   // automatically deleted on destruction of charBucket
   std::list< boost::shared_ptr<chunk> > chunks;
   int                size;
   int                max_size;
   // represents the result i.e. char** returned by the
   // get() method
   const char **      ptrs;

   // debugging
   friend
   std::ostream & operator<<(std::ostream &, const charBucket &);
};

std::ostream & operator<<(std::ostream & os,const charBucket & cb) {
   os
    << "CB:: chunks="
    << cb.chunks.size()
    << "; ptrMaxSize="
    << cb.max_size
    << "; ptrSize=" << cb.size;
   return os;
}

int main() {
   std::string s;
   charBucket c;
   int i=0;
   std::cerr << "Reading and storing strings from std::cin" << std::endl;
   while(std::cin >> s) {
     std::cerr << ++i << " '" << s << "'" << std::endl;
     c.put(s);
   }
   std::cerr << "Dumping stored char**" << std::endl;
   for(int i=0;c.get()[i]!=NULL;i++) {
     std::cerr << i+1 << " '" << c.get()[i] << "'" << std::endl;
   }
   std::cerr << "CharBucket Info" << std::endl;
   std::cerr << c << std::endl;
}
</snip>

All this might be overkill if you just expect a handfull of strings coming
in. Then you might just allocate the chars dynamically for each
string coming in and re-size an associated char* array as needed.

Also note that my proposition only checks in the last chunk of the
chunklist if there is enough space for the current string. It could
traverse the whole list to identify the chunk with enough space left
for the current string.

Hope that helps

O.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm
for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
 




 8 Posts in Topic:
Dynamically read string
howa <howachen@[EMAIL   2008-05-08 21:29:23 
Re: Dynamically read string
Marcin Swiderski <sfid  2008-05-09 09:15:18 
Re: Dynamically read string
Maciej Sobczak <see.my  2008-05-09 09:16:01 
Re: Dynamically read string
Oncaphillis <oncaphill  2008-05-09 09:24:35 
Re: Dynamically read string
Bob Lied <lied@[EMAIL   2008-05-09 09:28:53 
Re: Dynamically read string
"Jim Langston"   2008-05-09 09:22:45 
Re: Dynamically read string
"Martin T." <  2008-05-09 09:21:07 
Re: Dynamically read string
Ulrich Eckhardt <dooms  2008-05-09 09:27:41 

Post A Reply:
  Go here to Signup

AddThis Feed Button


About - Advertising - Contact - Frequently Asked Questions - Privacy Policy - Terms of Use - Signup

Contact
tan12V112 Fri Jul 25 21:51:27 CDT 2008.