1

In my .h file, I have two functions:

String( const char * s = "");
String( const String & s );

My aim is to convert objects created by these two constructors into linked list. So I write a function for converting:

static ListNode * stringToList(const char *s)
 {
     ListNode * h = new ListNode(s[0], NULL);
     ListNode * c = h;
     for(int i = 0; s[i] != '\0'; ++i)
     {
         c->next = new ListNode(s[i], NULL);
         c = c->next;
     }
     return h;
 }

I am aware that maybe in the case of char*s, we can use

String::String( const char * s)
 {
       ListNode::stringToList(s);
 }

But in the case of a string object,

String::String( const String & s )

how can I possibly do that? I am a bit confused by linked list/ Besides, all the functions after this one are using ( const String & s ) parameter. It becomes harder to operate on link list, I am very confused on how to accomplish operations on data by link list while all the parameters called in are "const String & s ". a string object

My entire link.h file:

    #include <iostream>

using namespace std;

class String
{
public:
    /// Both constructors should construct
    /// from the parameter s
     String( const char * s = "");
     String( const String & s );
     String operator = ( const String & s );
     char & operator [] ( const int index );
     int length() const {return ListNode::length(head);}
     int indexOf( char c ) const;
     bool operator == ( const String & s ) const;
     bool operator < ( const String & s ) const;
     /// concatenates this and s
     String operator + ( const String & s ) const;
     /// concatenates s onto end of this
     String operator += ( const String & s );
     void print( ostream & out );
     void read( istream & in );
     ~String();

private:
     bool inBounds( int i )
     {
         return i >= 0 && i < length();
     }

     struct ListNode
     {
     char info;
     ListNode * next;
     ListNode(char newInfo, ListNode * newNext)
         :info( newInfo ), next( newNext )
     {
     }
     // HINT: some primitives you *must* write and use, recursion?
     static ListNode * stringToList(const char *s)
     {
         ListNode * h = new ListNode(s[0], NULL);
         ListNode * c = h;
         for(int i = 0; s[i] != '\0'; ++i){
             c->next = new ListNode(s[i], NULL);
             c = c->next;
         }
         return h;
     }
     static ListNode * copy(ListNode * L)
     {
         return !L ? nullptr : new ListNode(L->info, copy(L->next));
     }
     static bool equal(ListNode * L1, ListNode * L2)
     {
         return (L1->info != L2->info) ? false : equal(L1->next, L2->next);
     }
     static ListNode * concat(ListNode * L1, ListNode * L2)
     {
         return !L1 ? copy(L2) : new ListNode(L1->info, concat(L1->next, L2));
     }
     static int compare(ListNode * L1, ListNode * L2)
     {
         return (!L1 && !L2) ? 0 : (L1->info > L2->info) ? 1 : (L1->info < L2->info) ? -1 : compare(L1->next, L2->next) ;
     }
     static int length(ListNode * L) // O(N) so call rarely
     {
         return L == nullptr ? 0 : 1 + length(L->next);
     }
     };

     ListNode * head; // no other data members!! ­ especially no len!
};
Frank
  • 91
  • 7
  • Who wrote this comment ? // HINT: some primitives you *must* write and use, recursion? – Vlad from Moscow Oct 31 '15 at 22:43
  • My instructor. He meant the primitive functions should use recursion, which I did exactly in the implementation. – Frank Oct 31 '15 at 22:47
  • Mixing data types and the data structures you want to store them in is bad design. What if you want to store strings in vectors, maps, trees. Are you going to embed a version of every data structure you may ever want to use? What if you want to use many different types in lists, will you have near identical copies of the list code in every type? – Neil Kirk Oct 31 '15 at 22:50
  • @Dorothy In fact all the wark of the class you should delegate to the list. – Vlad from Moscow Oct 31 '15 at 22:52
  • `String operator =` and `String operator +=` should return references. Did your instructor provide those prototypes? – Neil Kirk Oct 31 '15 at 22:55
  • @VladfromMoscow Absolutely, that's exactly what I am confused right now. I just learned C++ two weeks and first to linked list. I can't figure out how an object created by constructor be converted into linked list, or the whole class delegated to the list. – Frank Oct 31 '15 at 22:58
  • @NeilKirk Not really... But I believe it should accomplish the work that combine two linked lists together. Putting in two parameters which are String objects, converted them into linked list and then combine them. – Frank Oct 31 '15 at 22:58

1 Answers1

0

First of all, your implementation of stringToList needs a little change.

static ListNode * stringToList(const char *s)
{
    // What happens when the `s` is an empty string?
    // You end up storing the null character.
    ListNode * h = new ListNode(s[0], NULL);
    ListNode * c = h;

    // And then, you add s[0] again to the linked list.
    for(int i = 0; s[i] != '\0'; ++i)
    {
        c->next = new ListNode(s[i], NULL);
        c = c->next;
    }
    return h;
}

Change it to:

static ListNode * stringToList(const char *s)
{
   ListNode * h = NULL;
   if ( s[0] != '\0' )
   {
      h = new ListNode(s[i], NULL);
      ListNode * c = h;

      // Use 1 as the starting index for the iteration
      for(int i = 1; s[i] != '\0'; ++i)
      {
         c->next = new ListNode(s[i], NULL);
         c = c->next;
      }
   }
   return h;
}

But in the case of a string object,

String::String( const String & s )

how can I possibly do that?

It's not too different from the other constructor.

String::String( const String & s ) : head(NULL)
{
   ListNode* hr = s.head;
   if ( hr != NULL )
   {
      head = new ListNode(hr->info, NULL);
      List* cl = head;
      ListNode* cr = hr->next;

      for( ; cr != NULL; cr = cr->next)
      {
         cl->next = new ListNode(cr->info, NULL);
         cl = cl->next;
      }
   }
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Can you please explain a little more about "String operator = ( const String & s );" this function? In this one, how can I convert Object String s into linked list using the current primitive functions I have? – Frank Nov 01 '15 at 04:10
  • @Dorothy, if you have some time, read up on the copy-swap idiom. Ex 1: http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom. Ex 2: http://stackoverflow.com/questions/276173/what-are-your-favorite-c-coding-style-idioms/2034447#2034447 – R Sahu Nov 01 '15 at 04:22
  • @R Sahu Thanks a million!! – Frank Nov 01 '15 at 06:45