Service: C/C++ Tipps: Die Klasse CVectorOfCStrings


Viele Programmiersprachen bieten Standardfunktionen, um in einer Zeichenkette nach bestimmten (Trenn-) Zeichen zu suchen und eine Liste von Zeichenketten zurückzugeben. Die entsprechenden Funktionen heißen oft 'Split()' oder ähnlich.

Meist existiert dann auch die umgekehrte Funktion: Aus einer Liste von Zeichenketten in Verbindung mit einem angegebenen Trennzeichen wird eine einzige neue Zeichenkette. Die entsprechenden Funktionen heißen oft 'Join()' oder ähnlich.

Beispiel:
    Split("abc;efg;klm;xyz")

liefert

    "abc"
    "efg"
    "klm"
    "xyz"

ein Join(nListe, ",") liefert dementsprechend "abc,efg,klm,xyz" (dabei ist 'nListe' ein Array mit Zeichenketten).

Entsprechende Funktionen konnte ich jedoch in keiner der C++ Standardbibliotheken finden.

Deswegen habe ich die Miniklasse CVectorOfCStrings definiert. Die Klasse verwendet die Template-Klasse 'vector' aus der C++ StandardTemplateLibrary (STL). Damit kann man folgende nette Dinge tun:

    CVectorOfCStrings vec;
    vec.Split(_T("abc;efg;xyz"), _T(";"));
    VectorOfCStrings v = vec.get();
    for (VectorOfCStrings::iterator it = v.begin(); it != v.end(); it++)
        ATLTRACE(_T("it: %s\n"), it->GetString());
    vec.Append(_T("klm"));
    ATLTRACE(_T("vec.Join: \n%s\n"), vec.Join(_T("\n")));
Debug-Ausgaben:
it: abc
it: efg
it: xyz
vec.Join:
abc
efg
xyz
klm
Deklarationen:
/**
 * Class which implements Split() and Join() on CStrings.
 * @author Ralf Kunsmann (www.kunsmann.de) @date 2007 03 14 (yyyy mm dd)
 */
#pragma once

#ifndef VECTOR_OF_CSTRINGS_08554358_97B6_4DEF_B9A8_3F84E1474613_H
#define VECTOR_OF_CSTRINGS_08554358_97B6_4DEF_B9A8_3F84E1474613_H

#include <atlstr.h>
#include <vector>

namespace StringSupport
{
    typedef std::vector VectorOfCStrings;

    class CVectorOfCStrings
    {
    public:
        CVectorOfCStrings(void);

        CVectorOfCStrings(const CString& StringToSplit, const CString& Separator);

        ~CVectorOfCStrings();

        VectorOfCStrings& get();

        size_t Split(const CString& StringToSplit, const CString& Separator);

        CString Join(const CString& Separator);

        void Append(const CString& NewItem);

    private:
#pragma warning(disable:4251)
        VectorOfCStrings mvec;
#pragma warning (default:4251)
    };

} //namespace StringSupport
using namespace StringSupport;
#endif // VECTOR_OF_CSTRINGS_08554358_97B6_4DEF_B9A8_3F84E1474613_H
Definitionen:
#include "stdafx.h"
#include "VectorOfCStrings.h"

namespace StringSupport
{
    CVectorOfCStrings::CVectorOfCStrings()
    {
    }

    CVectorOfCStrings::CVectorOfCStrings(const CString& StringToSplit,
                                         const CString& Separator)
    {
        Split(StringToSplit, Separator);
    }

    CVectorOfCStrings::~CVectorOfCStrings()
    {
    }

    VectorOfCStrings& CVectorOfCStrings::get()
    {
        return mvec;
    }

    size_t CVectorOfCStrings::Split(const CString& StringToSplit, 
                                    const CString& Separator)
    {
        mvec.clear();
        int iPos = 0;
        CString str = StringToSplit.Tokenize(Separator, iPos);
        while(str.GetLength())
        {
            mvec.push_back(str);
            str = StringToSplit.Tokenize(Separator, iPos);
        }

        return mvec.size();
    }

    CString CVectorOfCStrings::Join(const CString& Separator)
    {
        CString strRet, strSeparator;
        for (VectorOfCStrings::const_iterator it = mvec.begin(); it != mvec.end(); it++)
        {
            strRet += strSeparator + it->GetString();
            strSeparator = Separator;
        }
        return strRet;
    }

    void CVectorOfCStrings::Append(const CString& NewItem)
    {
        mvec.push_back(NewItem);
    }
} //namespace StringSupport

Ein paar Worte zur Namespace-Anweisung

Falls Sie mit Namespaces nicht vertraut sind: Sie bieten die Möglichkeit, beliebige Elemente eindeutig zu qualifizieren.

Wenn Sie beispielsweise in Ihrem Projekt bereits eine andere Klasse mit der Bezeichnung 'CVectorOfCStrings' definiert hätten, könnten Sie beide Klassen problemlos nebeneinander verwenden, indem Sie Ihre Klasse um eine Namespace-Anweisung ergänzen und bei allen Zugriffen auf Elemente der Klassen die Namespace-Bezeichner voranstellen.

Bezogen auf das obige Beispiel könnten Sie dann wie folgt schreiben:

    StringSupport::CVectorOfCStrings vec;
    vec.Split(_T("abc;efg;xyz"), _T(";"));
    StringSupport::VectorOfCStrings v = vec.get();

Beachten Sie in diesem Zusammenhang bitte auch: Durch die Anweisung using namespace StringSupport; am Ende der obigen Deklaration können Sie auf die Verwendung des Namespace-Bezeichners 'StringSupport' verzichten, solange für den Kompiler eindeutig erkennbar ist, dass Sie auf Elemente aus 'StringSupport' zugreifen möchten.


Die Erlaubnis, den Quellcode zeitlich, räumlich und inhaltlich unbegrenzt zu verwenden wird hiermit erteilt unter der Auflage, dass die Nennung von Ralf Kunsmann als Autor unter Angabe der Web-Adresse www.kunsmann.de im Quellcode erfolgt.

Seitenanfang

Kontaktaufnahme- und Terminvereinbarung:

Bei Fragen und für Terminvereinbarungen erreichen Sie uns unter:

0 63 49 99 07 38

0 151 51 95 34 00

Oder nutzen Sie das Kontaktformular




Ihr Ansprechpartner:


Hier sollte das Fahnungsfoto zu sehen sein.

Ralf Kunsmann

Spezialist für VBA-Programmierung
(alle Office-Anwendungen)
Entwickler der
VBA-Extension-Tools