MFC Programmer's SourceBook : Thinking in C++
Bruce Eckel's Thinking in C++, 2nd Ed Contents | Prev | Next

Sstring & integer

To facilitate the examples in the rest of this chapter, a more powerful string class is necessary, along with an integer object that guarantees its initialization

A string on the stack

This is a more complete string class than has been used before in this book. In addition, this class uses templates to add a special feature: you can decide, when you instantiate the SString, whether it lives on the stack or the heap.

//: C16:Sstring.h
// Stack-based string
#ifndef SSTRING_H
#define SSTRING_H
#include <cstring>
#include <iostream>

template<int bsz = 0>
class SString {
  char buf[bsz + 1];
  char* s;
public:
  SString(const char* S = "") : s(buf) {
    if(!bsz) { // Make on heap
      s = new char[strlen(S) + 1];
      std::strcpy(s, S);
    } else { // Make on stack
      buf[bsz] = 0; // Ensure 0 termination
      std::strncpy(s, S, bsz);
    }
  }
  SString(const SString& rv) : s(buf) {
    if(!bsz) { // Make on heap
      s = new char[strlen(rv.s) + 1];
      std::strcpy(s, rv.s);
    } else { // Make on stack
      buf[bsz] = 0;
      std::strncpy(s, rv.s, bsz);
    }
  }
  SString& operator=(const SString& rv) {
    // Check for self-assignment:
    if(&rv == this) return *this;
    if(!bsz) { // Manage heap:
      delete s;
      s = new char[strlen(rv.s) + 1];
    }
    // Constructor guarantees length < bsz:
    std::strcpy(s, rv.s);
    return *this;
  }
  ~SString() {
    if(!bsz) delete []s;
  }
  int operator==(const SString& rv) const {
    return ! stricmp(s, rv.s);  // nonstandard
  }
  int operator!=(const SString& rv) const {
    return stricmp(s, rv.s);
  }
  int operator>(const SString& rv) const {
    return stricmp(s, rv.s) > 0;
  }
  int operator<(const SString& rv) const {
    return stricmp(s, rv.s) < 0;
  }
  char* str() const { return s; }
  friend std::ostream&
    operator<<(std::ostream& os,
               const SString<bsz>& S) {
      return os << S.s;
  }
};

typedef SString<> Hstring; // Heap string
#endif // SSTRING_H ///:~ 

By using the typedef Hstring, you get an ordinary heap-based string (a typedef was used here instead of inheritance because inheritance requires the new creation of the constructors and operator=). But if you’re concerned about the efficiency of creating and destroying a lot of strings, you can take a chance and assume the largest word size possible for the solution of your problem. When you give the template a size argument, it automatically creates the object totally on the stack rather than on the heap, which means the overhead of one new and one delete per object is eliminated. You can see that operator= is also speeded up.

The comparison operators for the string use a function called stricmp( ), which is not Standard C but which nonetheless is available with most compiler libraries. It performs a string compare while ignoring the case of the letters.

integer

The constructor for class integer zeroes the value, and it contains an automatic type conversion operator to an int so you can easily extract the value:

//: C16:Integer.h
// An int wrapped in a class
#ifndef INTEGER_H
#define INTEGER_H
#include <iostream>

class Integer {
  int i;
public:
  // Guaranteed zeroing:
  Integer(int ii = 0) : i(ii) {}
  operator int() const { return i; }
  const Integer& operator++() {
    i++;
    return *this;
  }
  const Integer operator++(int) {
    Integer returnval(i);
    i++;
    return returnval;
  }
  Integer& operator+=(const Integer& x) {
    i += x.i;
    return *this;
  }
  friend std::ostream&
  operator<<(std::ostream& os, const Integer& x){
      return os << x.i;
  }
};
#endif // INTEGER_H ///:~ 

Although this class is quite minimal (it only satisfies the needs of this chapter), you can easily add as many operations as you need by following the examples in Chapter 10.

Contents | Prev | Next


Go to CodeGuru.com
Contact: webmaster@codeguru.com
© Copyright 1997-1999 CodeGuru