CPerlString - A Class to Utilize Perl String Functions



Click here for larger image

Environment: VC++ 5.0-6.0, NT 4.0, Win2000, WinXP, Win95/98

String manipulation and regular expressions have always been a strength of Perl. The C language is powerful, but doing string manipulation and regular expressions is difficult. Although there are libraries such as PCRE that simulate Perl regular expressions in C, I have found them difficult to use. So, I thought, the best way is to embel Perl inside C.

With the help of Perl's documentation, I have successfully created two classes to encapsulate some of Perl's most useful functions. One class is for MFC users (CPerlString.h), and one class is for non-MFC users (PerlString.h). The functions encapsulated are:

  1. Pattern matching
  2. String substitution
  3. Joining of an array into a string
  4. Splitting of a string into an array
  5. Sort (forward or reverse)
  6. Chop
  7. Chomp

I will discuss the usage of the MFC class. The non-MFC class is similar but it uses STL string and vector<string> instead of CString and CStringArray.

I32 CPerlString::Match (CString inputString, CString pattern)
I32 CPerlString::Matches (CString inputString, CString pattern, CStringArray &matchList)

Match and Matches are two functions that make use of Perl's pattern-matching ability. Basically, Match sends a Perl statement: inputString =~ pattern and Matches sends a Perl statement: matchList = (inputString =~ pattern). Match will return 1 if the pattern is found and 0 if the pattern is not found. Matches will return the number of matches.

CPerlString perl;
CString inputString = "Hello World!";
CString pattern1 = "/Hello/";
CString pattern2 = "/(.o)/g";
CStringArray matchList;

if (perl.Match(inputString, pattern1))
  printf("Pattern found\n");
else
  printf("Pattern not found\n");

int num_matches = perl.Matches(inputString, pattern2, matchList);

printf("%d matches\n", num_matches);
if (num_matches > 0)
{
  for (int i = 0; i < matchList.GetSize(); i++)
    printf("Match %d: %s\n", i+1, matchList.GetAt(i));

I32 Substitute(CString &inputOutputString, CString pattern)

Substitute is a function that makes use of Perl's string substitute ability. Basically it sends: inputOutputString =~ pattern. Substitute will return 1 if the substitution is done and 0 if it is not done.

CPerlString perl;
CString inputOutputString = "Hello World!";
CString pattern1 = "s/Hello/Hello Happy/";

perl.Substitute(inputOutputString, pattern1);
printf("%s\n", inputOutputString);

void Join(CStringArray &inputStringList, CString pattern, CString &outputString)

Join is a function that makes use of Perl's joining ability. It sends: outputString = join (pattern, inputStringList). Join does not return any value.

CPerlString perl;
CString outputString;
CString pattern1 = " ";
CStringArray inputStringList;
inputStringList.Add("Hello");
inputStringList.Add("Happy");
inputStringList.Add("World");

perl.Join(inputStringList, pattern1, outputString);
printf ("%s\n", outputString);

I32 Split(CString inputString, CString pattern, CStringArray &splitList)

Split performs the Perl statement: splitlist = split (pattern, inputString). It returns the number of split items.

CPerlString perl;
CString inputString = "Hello Happy World!";
CString pattern1 = "/\\s/";
CStringArray splitList;

int num_split = perl.Split(inputString, pattern1, splitList);

printf("%d split\n", num_split);
if (num_split > 0)
{
  for (int i = 0; i < splitList.GetSize(); i++)
    printf("Split %d: %s\n", i+1, splitList.GetAt(i));

void Sort(CStringArray &inputStringList, CStringArray &outputStringList, int Direction = 0)

Sort performs sorting on an array by sending: outputStringList = sort (inputStringList) if the direction is 0 and outputStringList = reverse sort (inputStringList) if the direction is not 0 (for example, 1). Sort does not return any value.

CPerlString perl;
CStringArray inputStringList, outputStringList;
inputStringList.Add("Hello");
inputStringList.Add("Happy");
inputStringList.Add("World");

perl.Sort(inputStringList, outputStringList);    // Forward sort

for (int i = 0; i < outputStringList.GetSize(); i++)
  printf("%s\n", outputStringList.GetAt(i));

perl.Sort(inputStringList, outputStringList, 1); // Reverse sort

for (int i = 0; i < outputStringList.GetSize(); i++)
  printf("%s\n", outputStringList.GetAt(i));

void Chomp(CString &inputOutputString)
void Chomp(CStringArray &inputOutputStringList)
void Chop(CString &inputOutputString)
void Chop(CStringArray &inputOutputStringList)

Chop and Chomp are two functions that perform Perl's chop and chomp. They are overloaded to handle a string and a string array. The corresponding Perl statement is: chomp (inputOutputString) or chomp (inputOutputStringList) or chop (inputOutputString) or chop (inputOutputStringList).

CPerlString perl;
CString inputOutputString = "Hello World!";
CStringArray inputOutputStringList;
inputOutputStringList.Add("Hello");
inputOutputStringList.Add("Happy");
inputOutputStringList.Add("World");

perl.Chop(inputOutputString);
printf("%s\n", inputOutputString);

perl.Chop(inputOutputStringList);
for (int i = 0; i < inputOutputStringList.GetSize(); i++)
  printf("%s\n", inputOutputStringList.GetAt(i));

Usage:

To use the two classes, you will need to include them in your project by adding the statement: #include "CPerlString.h" or #include "PerlString.h". You will also need to have the Perl core libraries. These will be found in the directory where you install Perl. For example, if you install Perl in C:\Perl, the core libraries will be found at C:\Perl\lib\CORE. You will need to set this directory as one of the default include and library directories for Visual C++. This can be done by choosing Tools->Options->Directories and adding C:\Perl\lib\CORE in the include files and library files section.

Demo

The demo program demonstrates the use of the above-mentioned functions except chomp and chop. It can be used to help test your regular expression patterns.

Downloads

Download demo project - 40 Kb
Download source - 4 Kb


Comments

  • bug in your evaluation routine

    Posted by Legacy on 04/06/2003 12:00am

    Originally posted by: Pan Aimin

    It is running but does not work on "Matching". A simple test shows that FREETMPS will overwrite *retval. I guess what retval holds is a temporary memory and can not be returned.

    A simple fix like the following makes the "Matching" work.

    inline SV* my_eval_sv(SV *sv, I32 croak_on_error)
    {
    dSP;

    static SV my_retval;

    SV* retval;
    STRLEN n_a;
    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    eval_sv(sv, G_SCALAR);
    SPAGAIN;
    retval = POPs;

    memcpy(&my_retval, retval, sizeof(SV));

    PUTBACK;
    FREETMPS;
    LEAVE;
    if (croak_on_error && SvTRUE(ERRSV))
    croak(SvPVx(ERRSV, n_a));

    return &my_retval;

    }

    Reply
  • Bug in destructor?

    Posted by Legacy on 03/02/2003 12:00am

    Originally posted by: Olivier G. Gaumond


    Consider the following program

    #include <iostream>
    #include <string>
    #include "PerlString.h"

    using namespace std;

    string trim(const string& str);

    int main(int argc, char* argv[])
    {
    PerlString perl;
    string s2;
    string s1(" blabla ");
    string pattern("/^bla/");

    s2 = trim(s1);
    perl.Match(s2, pattern);

    std::cout << s2 << endl;

    }

    string trim(const string& str)
    {
    string sTemp, sTemp2;
    string bgnPtrn("s/^[\\s\\t\\n]+//");
    string endPtrn("s/[\\s\\t\\n]+$//");
    PerlString* p = new PerlString();

    p->Substitute(str, bgnPtrn, sTemp);
    p->Substitute(sTemp, endPtrn, sTemp2);

    delete p;

    return sTemp2;

    }

    I get an Access Violation on line
    perl.Match(s2, pattern);

    However if I remove the line
    delete p;
    in function trim() I avoid the access violation, however I've got a memory leak. Can we use more than one instance of the PerlString class?

    Olivier

    Reply
  • Crashing on simple pattern match

    Posted by Legacy on 01/23/2003 12:00am

    Originally posted by: Vasche

    I compiled a Debug version of the sample project,
    
    it crashes as soon as I hit Test.
    Pattern I use /a, text "Test".

    Can't find a reason so far, help would be appreciated.
    use perl58.lib, perl58.dll

    Platform: Windows 2000 Pro

    Reply
  • problem of Matches() function

    Posted by Legacy on 10/29/2002 12:00am

    Originally posted by: smxiang

    if give input string of "345" (or any other string), and pattern of "/([0-9])/", Matches() returns 1, and matchList returns "3", okay, it works well.
    but, in the above case, if give the pattern of "/[0-9]/", Matches() still returns 1, and matchList returns "1", why?

    thanks for your hard work!
    Xiang Siming
    xiangsm@yahoo.com
    2002/10/30

    Reply
  • CPerlString and Multithreading

    Posted by Legacy on 04/15/2002 12:00am

    Originally posted by: Isaac COHEN

    Hi,

    I have tried to use CPerlString in a multi-thread application but I get a runtime error.

    Any suggestions?

    Isaac.

    Reply
  • Running in embedded visual c++

    Posted by Legacy on 03/17/2002 12:00am

    Originally posted by: Flavia

    I am trying to run the program in embedded visual c++. Does any one have a version that can run in embedded visual c++. Please do email me asap thanks . I downloaded the demo program but there is a fatal error C1083: Cannot open precompiled header file: 'Release/PerlStringTest.pch': No such file or directory. Can someone help me pls.........

    Reply
  • PerlString usage question.

    Posted by Legacy on 02/26/2002 12:00am

    Originally posted by: Dave Yasko

    Hello,

    PerlString is exactly what I've been looking for. Thanks. Could you please provide some example code to use PerlString::Matches() and PerlString::Split()?

    I have to use the non-MFC version, and I'm having problems with the matchList and splitList function arguments. The functions require "char *(listVar[])" types, but I can't assemble a variable of the right type.

    Thanx in advance,

    Dave

    Reply
  • Static Lib

    Posted by Legacy on 02/07/2002 12:00am

    Originally posted by: Med

    Hi,

    Is it possible to link the perl56.dll statically like it's possible to link the MFC dlls so that the exe file can be ported to machines that are not running PERL?

    Reply
  • Perl Version?

    Posted by Legacy on 01/26/2002 12:00am

    Originally posted by: Med

    What version of PERL did you use? Are you using Active State PERL? I tried to compile the demo program and have 55 errors.
    
    

    You mentioned that we need to modify the linker to access perl56.lib. Somehow, I did not manage to find this file inside my Perl/lib/CORE directory.

    Any idea what went wrong? Pls help. Thks

    Rgds

    Reply
  • Good work...

    Posted by Legacy on 01/19/2002 12:00am

    Originally posted by: Kevin Cazabon

    Nicely done, works slick, thanks!
    
    

    Kevin.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds