Hi, I need some help with sorting my string comparison. Bascially what I have to do is this:

To have numbers sorted properly even when they aren't justified with leading 0's:

1
2
...
9
10
Instead of:

1
10
2
...
9

Also to have numbers sorted properly even if they aren't in the lead of the string:

a1
a2
...
a9
a10
b1
b2
...
Instead of:

a1
a10
a2
...
a9
b1
b10
b2
...
Note how the lead part of the string is sorted and then the numeric part ...almost independently.

I would really appriciate some help in starting this code for my particular program. I tried many ways but I can't figure it out.

Here is my code:

#ifndef RP_STRINGS_H_INC
#define RP_STRINGS_H_INC

short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces = false,
bool skipPunctuation = false);

#endif

#include "rpstrings.h"

#include <cctype>
#include <cstddef>
#include <iostream>

using namespace std;

short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces,
               bool skipPunctuation)
{
    short x;

    if (Str1 == Str2)
        x = 0;

    else if (Str1 == NULL)
        x = -1;

    else if (Str2 == NULL)
        x = 1;

    else {
        while ((skipSpaces && isspace(*Str1)) ||
               (skipPunctuation && ispunct(*Str1)))
        {
            ++Str1;
        }
        while ((skipSpaces && isspace(*Str2)) ||
               (skipPunctuation && ispunct(*Str2)))
        {
            ++Str2;
        }
    // compare a and b case INsensitively

        while (tolower(*Str1) == tolower(*Str2) &&
               *Str1 != '\0' && *Str2 != '\0')
        {
            //size_t s1;
            //s1 = 0;
            do
            {
                ++Str1;
                //s1++;
            } while ((skipSpaces && isspace(*Str1)) ||
                     (skipPunctuation && ispunct(*Str1)));
            //cerr<<"Skipped "<<s1<<" chars in first string\n";
            //size_t s2;
            //s2 = 0;
            do
            {
                ++Str2;
                //s2++;
            } while ((skipSpaces && isspace(*Str2)) ||
                     (skipPunctuation && ispunct(*Str2)));
            //cerr<<"Skipped "<<s2<<" chars in second string\n";
        }

        if (tolower (*Str1) <  tolower (*Str2))
            x = -1;

        else if(tolower (*Str1) > tolower (*Str2))
            x = 1;

        else
            x = 0;
    }

    return x;
}

#include <iostream>
//#include <cstring>
#include <iomanip>
#include "rpstrings.h"

using namespace std;

int main ()
{

    char Str1[200], Str2[200];
    short result;

    cout << "Please enter the first string:" << endl;
    cin.getline(Str1, 200);

    cout << "Please enter the second string:" << endl;
    cin.getline(Str2, 200);

    //cerr<<"\nReceived '"<<Str1<<"' and '"<<Str2<<"'\n";

    cout << "Skipping nothing...\n";
    result = rpstrcmp(Str1, Str2);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Skipping spaces...\n";
    result = rpstrcmp(Str1, Str2, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Not skipping spaces and skipping punctuation...\n";
    result = rpstrcmp(Str1, Str2, false, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }


    cout << "Skipping spaces and punctuation...\n";
    result = rpstrcmp(Str1, Str2, true, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    return 0;
}

Thanks

If your input data is close to what you show above ...

something like the following could do ...

/* sortAlphaNum.cpp */  /* 2020-02-24 */


/*
Here is what I have to do:

To have numbers sorted properly even when they aren't justified with leading 0's:

1
2
...
9
10
Instead of:

1
10
2
...
9

Also to have numbers sorted properly even if they aren't in the lead of the string:

a1
a2
...
a9
a10
b1
b2
...
Instead of:

a1
a10
a2
...
a9
b1
b10
b2
...
*/


#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include <algorithm> // sort
#include <cctype>    // re. isdigit

using namespace std;

#define FNAME "alphaNum.txt"

typedef vector< string > VecStr;

bool loadFromFile( VecStr& vs )
{
    ifstream fin( FNAME );
    if( fin )
    {
        string line;
        while( getline(fin, line) )
            vs.push_back( line );
        fin.close();
        return true;
    }
    return false;
}

void print( const VecStr& vs )
{
    for( size_t i = 0; i < vs.size(); ++i ) cout << vs[i] << endl;
}

void pause( const char* msg )
{
    cout << msg << flush;
    while( cin.get()  != '\n' ) ;
}

int toInt( const string& s )
{
    istringstream iss(s);
    int tmp;
    iss >> tmp;
    return tmp;
}

struct Item
{
    string s;
    int val;
} ;

bool myCmp( const string& a, const string& b )
{
    Item a_itm, b_itm;
    istringstream iss_a(a), iss_b(b);
    char c;
    string tmp;

    while( iss_a >> c )
    {
        if( isdigit(c) ) tmp += c;
        else a_itm.s += c;
        a_itm.val = toInt( tmp );
    }

    tmp.clear();
    while( iss_b >> c )
    {
        if( isdigit(c) ) tmp += c;
        else b_itm.s += c;
        b_itm.val = toInt( tmp );
    }

    if( a_itm.s == b_itm.s ) return a_itm.val < b_itm.val;
    return a_itm.s < b_itm.s;
}



int main()
{
    VecStr vs; // construct empty vector ...

    if( loadFromFile( vs ) )
    {
        cout << "Before sorting ... \n";
        print( vs );
        sort( vs.begin(), vs.end(), myCmp );
        cout << "After sorting ... \n";
        print( vs );
    }
    else cout << "Error opening file " << FNAME << cout;

    pause( "Press 'Enter' to continue/exit ... " );
}

Edited 2 Years Ago by David W: fix code formatting

thanks for the quick reply, but quick question, why are you opening a file? I am confused. So if I were to use and modify your example above would it compile the way I need it to above?

How do I implement this code into mine?

Sorry for the dumb questions, but new to programming and want to understand what I am doing.

Thanks

Try it with this small test 'text file', and name the file to match the file name used in the program ...

"alphaNum.txt"

It is easy (easier sometimes) to test out a program using file data ... that is 'known to be valid data'

1
10
2
9
a1
b10
a10
a2
a9
b1
b2

Edited 2 Years Ago by David W: added comments

The above was just an example of what my code has to accomplish if we input that type of data. Sorry for the confusion.

My output, for the test file above, as input, was:
(matches your request ...yes?)

Before sorting ...
1
10
2
9
a1
b10
a10
a2
a9
b1
b2
After sorting ...
1
2
9
10
a1
a2
a9
a10
b1
b2
b10
Press 'Enter' to continue/exit ...

Edited 2 Years Ago by David W: edit formatting

ok thanks I will try it out. So once the code is working fine with the test file, how can I remove it so it doesn't ask for a file rather than the input that the user enters?

These may help ... (edit out the file stuff, also, of course.)

typedef vector< string > VecStr;


char takeInChar( const string& msg )
{
    cout << msg << flush;
    string reply;
    getline( cin, reply );
    if( reply.size() )
        return reply[0];
    // else ...
    return 0;
}
bool more()
{
    if( tolower( takeInChar( "\nMore (y/n) ? " )) == 'n' )
        return false;
    // else ...
    return true;
}

void loadFromUser( VecStr& vs )
{
    do
    {
        string line;
        cout << "Enter next line: " << flush;
        getline( cin, line );
        vs.push_back( line );
    }
    while( more() );
}

Edited 2 Years Ago by David W: edit formatting

So I am trying to implement the code above, but confused on where to put it exactly.

What do you want to have in your main function ...

Maybe ... something like this:

int main()
{
    VecStr vs; // construct empty vector ...

    loadFromUser( vs );

    cout << "Before sorting ... \n";
    print( vs );
    sort( vs.begin(), vs.end(), myCmp );
    cout << "After sorting ... \n";
    print( vs );


    pause( "Press 'Enter' to continue/exit ... " );
}

ok I have tried to put the code but there are some errors I get.

This is my code:

Header:

#ifndef RP_STRINGS_H_INC
#define RP_STRINGS_H_INC

short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces = false,
bool skipPunctuation = false);

#endif


Implementation file:

#include "rpstrings.h"

#include <cctype>
#include <cstddef>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

#define FNAME "alphaNum.txt"
typedef vector<string> VecStr;

bool loadFromFile(VecStr& vs)
{
    ifstream fin(FNAME);
    if(fin)
    {
        string line; 
        while(getline(fin, line))
            vs.push_back(line);
        fin.close();
        return true;
    }
    return false;
}

void print(const VecStr& vs)
{
    for(size_t i=0; i < v.size(); ++i)
        cout << vs[i] << endl;
}

void pause(const char* msg)
{
    cout << msg << flush;
    while(cin.get() !='\n');
}

int toInt(const string& s)
{
    istringstream iss(s);
    int tmp;
    iss >> tmp;
    return tmp;
}

struct Item
{
    string s;
    int val;
};

bool myCmp(const string& a, const string& b)
{
    Item a_itm, b_itm;
    istringstream iss_a(a), iss_b(b);
    char c;
    string tmp;
    while(iss_a >> c)
    {
        if(isdigit(c)) tmp += c;
        else a_itm.s += c;
        a_itm.val = toInt(tmp);
    }
    tmp.clear();

    while(iss_b >> c)
    {
        if(isdigit(c)) tmp += c;
        else b_itm.s += c;
        b_itm.val = toInt(tmp);
    }

    if(a_itm.s == b_itm.s)
        return a_itm.val < b_itm.val;
    return a_itm.s < b_itm.s;


short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces,
               bool skipPunctuation)
{
    short x;

    if (Str1 == Str2)
        x = 0;

    else if (Str1 == NULL)
        x = -1;

    else if (Str2 == NULL)
        x = 1;

    else {
        while ((skipSpaces && isspace(*Str1)) ||
               (skipPunctuation && ispunct(*Str1)))
        {
            ++Str1;
        }
        while ((skipSpaces && isspace(*Str2)) ||
               (skipPunctuation && ispunct(*Str2)))
        {
            ++Str2;
        }
    // compare a and b case INsensitively

        while (tolower(*Str1) == tolower(*Str2) &&
               *Str1 != '\0' && *Str2 != '\0')
        {
            //size_t s1;
            //s1 = 0;
            do
            {
                ++Str1;
                //s1++;
            } while ((skipSpaces && isspace(*Str1)) ||
                     (skipPunctuation && ispunct(*Str1)));
            //cerr<<"Skipped "<<s1<<" chars in first string\n";
            //size_t s2;
            //s2 = 0;
            do
            {
                ++Str2;
                //s2++;
            } while ((skipSpaces && isspace(*Str2)) ||
                     (skipPunctuation && ispunct(*Str2)));
            //cerr<<"Skipped "<<s2<<" chars in second string\n";
        }

        if (tolower (*Str1) <  tolower (*Str2))
            x = -1;

        else if(tolower (*Str1) > tolower (*Str2))
            x = 1;

        else
            x = 0;
    }

    return x;
}


Main file:

#include <iostream>
//#include <cstring>
#include <iomanip>
#include "rpstrings.h"

using namespace std;

int main ()
{

    VecStr vs;
    if(loadFromFile(vs))
    {
        cout << "Before sorting... \n";
        print(vs);
        sort(vs.begin(), vs.end(), myCmp());
        cout << "After sorting... \n";
        print(vs);
    }
    else cout << "error opening file" << FNAME << cout;
    pause("Press 'Enter' to continue/exit...");

    char Str1[200], Str2[200];
    short result;

    cout << "Please enter the first string:" << endl;
    cin.getline(Str1, 200);

    cout << "Please enter the second string:" << endl;
    cin.getline(Str2, 200);

    //cerr<<"\nReceived '"<<Str1<<"' and '"<<Str2<<"'\n";

    cout << "Skipping nothing...\n";
    result = rpstrcmp(Str1, Str2);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Skipping spaces...\n";
    result = rpstrcmp(Str1, Str2, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Not skipping spaces and skipping punctuation...\n";
    result = rpstrcmp(Str1, Str2, false, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }


    cout << "Skipping spaces and punctuation...\n";
    result = rpstrcmp(Str1, Str2, true, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    return 0;
}

The errors I get are:

rpstrings.cpp:24: instantiated from here
rpstrings.cpp:24: instantiated from here
rpstrings.cpp:24: instantiated from here
rpstrings.cpp: In function void print(const VecStr&)': rpstrings.cpp:33: error:v' was not declared in this scope
rpstrings.cpp:33: warning: unused variable 'v'
rpstrings.cpp: In constructor Item::Item()': rpstrings.cpp:59: warning:Item::s' should be initialized in the
member initialization list
rpstrings.cpp:59: warning: Item::val' should be initialized in the member initialization list rpstrings.cpp: In functionbool myCmp(const std::string&, const
std::string&)':
rpstrings.cpp:85: error: a function-definition is not allowed here
before '{' token
rpstrings.cpp:144: error: expected }' at end of input rpstrings.cpp:24: instantiated from here rpstrings.cpp:34: instantiated from here strcmp.cpp: In functionint main()':
strcmp.cpp:11: error: VecStr' was not declared in this scope strcmp.cpp:11: error: expected;' before "vs"
strcmp.cpp:12: error: vs' was not declared in this scope strcmp.cpp:12: error:loadFromFile' was not declared in this scope
strcmp.cpp:15: error: print' was not declared in this scope strcmp.cpp:16: error:myCmp' was not declared in this scope
strcmp.cpp:16: warning: unused variable 'myCmp'
strcmp.cpp:20: error: `FNAME' was not declared in this scope
strcmp.cpp:20: warning: unused variable 'FNAME'
strcmp.cpp:12: warning: unused variable 'loadFromFile'
strcmp.cpp:21: error: at this point in file
strcmp.cpp:11: warning: unused variable 'VecStr'

Thanks

Since you are using C++ ...

Why not just easily USE C++ string ...

Then ...

your program to input strings into a vector of strings ...

and to sort them, as you wish ...
(code and use your own compare function for the sort
... see or use the example compare function used above)

can easily all be done in just ONE short file.

Using the C++ STL ... for vector and sort, etc...
IS THE WAY to go !

Please review the examples and functions provided above.
You really do have all that you need there, using C++ string and the C++ STL ...

Edited 2 Years Ago by David W

Also ... it would be best to accept ONLY valid input from the user ... (if you are NOT using input from a valid data file) ...

You could do that, coding for your user input function, something like below:

bool isAllDigit( const string& s )
{
    for( int i = s.size()-1; i >= 0; -- i )
    {
        if( !isdigit(s[i]) ) return false;
    }
    return true;
}

bool isAllAlpha( const string& s )
{
    for( int i = s.size()-1; i >= 0; -- i )
    {
        if( !isalpha(s[i]) ) return false;
    }
    return true;
}

bool isValid( const string& s )
{
    if( isAllDigit(s) ) return true;
    if( isAllAlpha(s) ) return true;

    size_t pos = s.find_first_of( "0123456789" );
    bool valid = true;
    if( pos == string::npos ) valid = false; // not likely ... just in case
    else if( isAllAlpha( s.substr( 0, pos )) && isAllDigit( s.substr( pos )) )
        return true;
    else valid = false;

    cout << "\nInvalid input ... please try again ...\n";

    return valid;
}

// valid line entry only ...
// 1. a valid int (only one valid int on line)
// 2. a string (no embedded digits 0..9)
// 3. a string (as in 2.) immediately followed by one valid int
void loadFromUser( VecStr& vs )
{
    cout << "Valid input here is:\n"
         << "1. a valid integer (only one valid int on line ... or\n"
         << "2. a string (no embedded digits 0..9) ... or\n"
         << "3. a string (as in 2.) "
         << "immediately followed by one valid integer.\n\n";
    do
    {
        string line;
        cout << "Enter next line like one of following "
             << "( 1, 31, b1, a21, c3, 22, ... ): " << flush;
        getline( cin, line );
        if( isValid( line ) ) vs.push_back( line );
    }
    while( more() );
}

If you are NOT using a C++ compiler that supports C++ string and STL vector, etc...

IT IS time to get an updated C++ compiler !

Anyways ... there are lots of C++ class String and template class Vector ... all over the web. If you need help finding some ... I could give you a link.

Edited 2 Years Ago by David W: fixed spelling

so I can use the above code in my program and it will work by comparing the strings just like the the alphaNum.txt file?

Yes ... but here, you seem to NOT want (or need) any code to handle file input ...

since you are getting input from the keyboard to fill up a test vector of strings to sort, etc.

So ... just use code that does that job ... input test strings into an (initially empty) vector of strings, from the keyboard ... as per user input function example(s).

Edited 2 Years Ago by David W: added words to clear up ...

Hi, so I put the code in my program but for the while(more) function, what should I include in its definition?

You could use the above example (copied now here below):

char takeInChar( const string& msg )
{
    cout << msg << flush;
    string reply;
    getline( cin, reply );
    if( reply.size() )
        return reply[0];
    // else ...
    return 0;
}

bool more() // defaults to yes (more) ...
{
    if( tolower( takeInChar( "\nMore (y/n) ? " )) == 'n' )
        return false;
    // else ...
    return true;
}

Edited 2 Years Ago by David W: fixed format indents

here is my code with the above implemented. So should I put the above code in my code or just replace the bool more() with the while(more) loop at the end.

Do I need to add anything else to the header or the main file?

So I tried putting in the code in my code but still having problems. It is giving me the following errors:

rpstrings.cpp:10: error: expected initializer before '<' token
rpstrings.cpp:15: error: variable or field loadFromUser' declared void rpstrings.cpp:15: error:VecStr' was not declared in this scope
rpstrings.cpp:15: error: vs' was not declared in this scope rpstrings.cpp:120: error: variable or fieldloadFromUser' declared
void
rpstrings.cpp:120: error: redefinition of int loadFromUser' rpstrings.cpp:15: error:int loadFromUser' previously defined here
rpstrings.cpp:120: error: VecStr' was not declared in this scope rpstrings.cpp:120: error:vs' was not declared in this scope
rpstrings.cpp:121: confused by earlier errors, bailing out

My code is as follows:

Header file:

#ifndef RP_STRINGS_H_INC
#define RP_STRINGS_H_INC

short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces = false,
bool skipPunctuation = false);

#endif


Implementation file:

#include "rpstrings.h"

#include <cctype>
#include <cstddef>
#include <iostream>
#include <string>

using namespace std;

typedef vector<string> VecStr;

bool isAllDigit(const string& s);
bool isAllAlpha(const string& s);
bool isValid(const string& s);
void loadFromUser(VecStr& vs);
bool more();


short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces,
               bool skipPunctuation)
{
    short x;

    if (Str1 == Str2)
        x = 0;

    else if (Str1 == NULL)
        x = -1;

    else if (Str2 == NULL)
        x = 1;

    else {
        while ((skipSpaces && isspace(*Str1)) ||
               (skipPunctuation && ispunct(*Str1)))
        {
            ++Str1;
        }
        while ((skipSpaces && isspace(*Str2)) ||
               (skipPunctuation && ispunct(*Str2)))
        {
            ++Str2;
        }
    // compare a and b case INsensitively

        while (tolower(*Str1) == tolower(*Str2) &&
               *Str1 != '\0' && *Str2 != '\0')
        {
            //size_t s1;
            //s1 = 0;
            do
            {
                ++Str1;
                //s1++;
            } while ((skipSpaces && isspace(*Str1)) ||
                     (skipPunctuation && ispunct(*Str1)));
            //cerr<<"Skipped "<<s1<<" chars in first string\n";
            //size_t s2;
            //s2 = 0;
            do
            {
                ++Str2;
                //s2++;
            } while ((skipSpaces && isspace(*Str2)) ||
                     (skipPunctuation && ispunct(*Str2)));
            //cerr<<"Skipped "<<s2<<" chars in second string\n";
        }

        if (tolower (*Str1) <  tolower (*Str2))
            x = -1;

        else if(tolower (*Str1) > tolower (*Str2))
            x = 1;

        else
            x = 0;
    }

    return x;
}

bool isAllDigit(const string& s)
{
    for(int i=s.size()-1; i >=0; --i)
    {
        if(!isdigit(s[i])) 
            return false;
    }
    return true;
}

bool isAllAlpha(const string& s)
{
    for(int i=s.size()-1; i >=0; --i)
    {
        if(!isalpha(s[i]))
            return false;
    }
    return true;
}

bool isValid(const string& s)
{
    if(isAllDigit(s)) return true;
    if(isAllAlpha(s)) return true;

    size_t pos = s.find_first_of("0123456789");
    bool valid=true;
    if(pos == string::npos)
        valid=false; //not likely...just in case
    else if(isAllAlpha(s.substr(0, pos)) && isAllDigit(s.substr(pos)))
        return true;
    else valid=false;

    cout << "\nInvalid input...please try again...\n";

    return valid;
}

void loadFromUser(VecStr& vs)
{
    cout << "Valid input here is:\n"
         << "1. a valid integer (only one valid int on line...or\n"
         << "2. a string (no embedded digits 0..9)...or\n"
         << "3. a string (as in 2.) "
         << "immediately followed by one valid integer.\n\n";

    do
    {
        string line;
        cout << "Enter the next line like one of the following"
             << "(1, 31, b1, a21, c3, 22, ...):" << flush;
        getline(cin, line);
        if(isValid(line)) vs.push_back(line);
    } while (more());
}


Main file:

#include <iostream>
//#include <cstring>
#include <iomanip>
#include "rpstrings.h"

using namespace std;

int main ()
{


    char Str1[200], Str2[200];
    short result;

    cout << "Please enter the first string:" << endl;
    cin.getline(Str1, 200);

    cout << "Please enter the second string:" << endl;
    cin.getline(Str2, 200);

    //cerr<<"\nReceived '"<<Str1<<"' and '"<<Str2<<"'\n";

    cout << "Skipping nothing...\n";
    result = rpstrcmp(Str1, Str2);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Skipping spaces...\n";
    result = rpstrcmp(Str1, Str2, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Not skipping spaces and skipping punctuation...\n";
    result = rpstrcmp(Str1, Str2, false, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }


    cout << "Skipping spaces and punctuation...\n";
    result = rpstrcmp(Str1, Str2, true, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    return 0;
}

Am confused what code I need to add still to get it working like how you did for the test file.

Thanks in advance

It seeems you don't have C++ string
Try using the class String I linked to, on your other post.

Where is the class string? I don't see the post. I will try putting it into the program and hopefully it works.

Thanks

here is the link for the assignment, I did look over the string class but I can't use it for this assignment.

http://home.earthlink.net/~craie/122/labs/strcasecomp.html

As far as my code goes, can you check where I need to insert code (what code to insert), I am confused on why the program is not working in comparison like the alphaNum.txt file you showed me.

This is what I have:

#include <iostream>
//#include <cstring>
#include <iomanip>
#include "rpstrings.h"

using namespace std;

int main ()
{
    VecStr vs;
    loadFromUser(vs);


    char Str1[200], Str2[200];
    short result;

    cout << "Please enter the first string:" << endl;
    cin.getline(Str1, 200);

    cout << "Please enter the second string:" << endl;
    cin.getline(Str2, 200);

    //cerr<<"\nReceived '"<<Str1<<"' and '"<<Str2<<"'\n";

    cout << "Skipping nothing...\n";
    result = rpstrcmp(Str1, Str2);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Skipping spaces...\n";
    result = rpstrcmp(Str1, Str2, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    cout << "Not skipping spaces and skipping punctuation...\n";
    result = rpstrcmp(Str1, Str2, false, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }


    cout << "Skipping spaces and punctuation...\n";
    result = rpstrcmp(Str1, Str2, true, true);

    if (result > 0)
    {
       cout << "First string is greater than second string" << endl;
    }

    else if (result == 0)
    {
       cout << "First string is equal to second string" << endl;
    }

    else 
    {
       cout << "First string is less than second string" << endl;
    }

    return 0;
}

#include "rpstrings.h"

#include <cctype>
#include <cstddef>
#include <iostream>
#include <string>

using namespace std;

typedef vector<string> VecStr;

bool isAllDigit(const string& s);
bool isAllAlpha(const string& s);
bool isValid(const string& s);
void loadFromUser(VecStr& vs);
bool more();


short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces,
               bool skipPunctuation)
{
    short x;

    if (Str1 == Str2)
        x = 0;

    else if (Str1 == NULL)
        x = -1;

    else if (Str2 == NULL)
        x = 1;

    else {
        while ((skipSpaces && isspace(*Str1)) ||
               (skipPunctuation && ispunct(*Str1)))
        {
            ++Str1;
        }
        while ((skipSpaces && isspace(*Str2)) ||
               (skipPunctuation && ispunct(*Str2)))
        {
            ++Str2;
        }
    // compare a and b case INsensitively

        while (tolower(*Str1) == tolower(*Str2) &&
               *Str1 != '\0' && *Str2 != '\0')
        {
            //size_t s1;
            //s1 = 0;
            do
            {
                ++Str1;
                //s1++;
            } while ((skipSpaces && isspace(*Str1)) ||
                     (skipPunctuation && ispunct(*Str1)));
            //cerr<<"Skipped "<<s1<<" chars in first string\n";
            //size_t s2;
            //s2 = 0;
            do
            {
                ++Str2;
                //s2++;
            } while ((skipSpaces && isspace(*Str2)) ||
                     (skipPunctuation && ispunct(*Str2)));
            //cerr<<"Skipped "<<s2<<" chars in second string\n";
        }

        if (tolower (*Str1) <  tolower (*Str2))
            x = -1;

        else if(tolower (*Str1) > tolower (*Str2))
            x = 1;

        else
            x = 0;
    }

    return x;
}

bool isAllDigit(const string& s)
{
    for(int i=s.size()-1; i >=0; --i)
    {
        if(!isdigit(s[i])) 
            return false;
    }
    return true;
}

bool isAllAlpha(const string& s)
{
    for(int i=s.size()-1; i >=0; --i)
    {
        if(!isalpha(s[i]))
            return false;
    }
    return true;
}

bool isValid(const string& s)
{
    if(isAllDigit(s)) return true;
    if(isAllAlpha(s)) return true;

    size_t pos = s.find_first_of("0123456789");
    bool valid=true;
    if(pos == string::npos)
        valid=false; //not likely...just in case
    else if(isAllAlpha(s.substr(0, pos)) && isAllDigit(s.substr(pos)))
        return true;
    else valid=false;

    cout << "\nInvalid input...please try again...\n";

    return valid;
}

void loadFromUser(VecStr& vs)
{
    cout << "Valid input here is:\n"
         << "1. a valid integer (only one valid int on line...or\n"
         << "2. a string (no embedded digits 0..9)...or\n"
         << "3. a string (as in 2.) "
         << "immediately followed by one valid integer.\n\n";

    do
    {
        string line;
        cout << "Enter the next line like one of the following"
             << "(1, 31, b1, a21, c3, 22, ...):" << flush;
        getline(cin, line);
        if(isValid(line)) vs.push_back(line);
    } while (more());
}


My code above is not compiling for some reason.



#ifndef RP_STRINGS_H_INC
#define RP_STRINGS_H_INC

short rpstrcmp(const char Str1[], const char Str2[], bool skipSpaces = false,
bool skipPunctuation = false);

#endif

Thank you for all your help

I do not have access to your string type ... (nor do I care to have access to it.)

I sent you a link to a string class ... so that we can both work 'on the same basis' ... I am willing to help you, if I can ... with that.

It IS really way over-due for you to get updated to the present version of a C++ compiler ... (and several are free !!!)

If you want to use C type (dynamic) strings ... I have a free student C utilities library that easily handles that (with utilities for Cvec and Clist with insert and merge sorts, etc...) :

#include "readLine.h"

/* readLine.h */ /* this version: 2013-07-10 */

/* http://developers-heaven.net/forum/index.php/topic,46.0.html */

/*
Safe string data entry from file ... to replace gets and fgets
BUT free new memory ... when done! Don't forget that C strings are
pointers to a block of char, with a '\0' char at the terminal end ...

Call like this:

    char* line = readLine( stdin );

    or ...

    while( (line = readLine( FILEp )) )
    {
        // process line ...
    }
*/



#include "readWord.h"

/* readWord.h */ /* this ver 2013-07-11 */

/* http://developers-heaven.net/forum/index.php/topic,46.0.html */

/*
Safe string data entry from file or keyboard ...
BUT ... free new memory when done with it!
Don't forget that C strings are pointers to a block of char,
with a '\0' char at the terminal end ... Call like this:

char* word = readWord(stdin, 31, "\n\t ,.;:", &lastChr);//note delimiter str

or ...

while((word = readWord(FILEp, startChunkSize, delimiterStr, &lastCharRead)))
{
    // do stuff ...
}

Note 1: select your initial word chunk size to minimize calls to realloc
Note 2: address of last char passed in/out so can flush stdin or file line
*/

Edited 2 Years Ago by David W: fixed spelling ... added stuff

thanks, sorry but the questions I asked my professor are for this assisgnment not the cities.

here they are:

Here is some questions I asked regarding the sort:

"Hi, I am in your csc 122 class and had a question regarding the lab
where you are supposed to compare 2 strings. For the 2 and 3 extra
points, the program is supposed to sort the letter/numbers.
>
Not truly sort, but compare such that the sort would work as desired. Recall that during any sort algorithm we've ever studied (or probably conceived of), two elements are compared to determine their appropriate order relative to one another. You are trying to fix your string comparison function so that it will not only be insensitive to case, but also intuitively order strings with aligned numeric sub-sequences. That way, your function could be used from within a sort to order such number-containing strings in a manner amenable to human desires.

Regarding
this, am I supposed to include a txt file (which the program is calling)
in which the program reads and sorts it for you (like your example in
this lab) or does this sorting suppose to only work when the user inputs
data?

Your driver could use a sort to test your function, but that is not required. You just have to make sure your function works. Similarly you could use a file to house many test string pairs, but this is not required. Just make sure your program can test as many pairs of strings as deemed necessary by the person doing the testing."

So it seems like I could have use something like the alphaNum.txt file but have to make sure my function works.

Please advise

If this is another problem ...

(i.e. a new assignment you are working on),

please start a new thread, and state clearly what the problem is, what your quide lines are, if any,

(for example: use C strings only? sort a certain type of formated file ? ... etc.),

and show what code you have ... and where you are having problems coding ... or not getting the expected results.

the post is for this assignment, just misplaced it on the other thread. I am going to try using the alphaNum.txt file in the program to to test it.

When I attempted it before, it was giving me errors in the code.

Need some help ASAP, so I emailed my teacher to verify my code and this is what he said:

"There is so much wrong, it is hard to know where to start.

You had a functioning library and driver and then went to add more levels. But, along the way, you got confused about terminology used in the new options. I thought we'd clarified that in our email discussion, but I see now I was wrong.

But, there are things wrong on so many levels that I'm not sure what angle to approach. You have fundamental coding issues as well as high-level design issues.

You try to define a type nickname for a vector of strings, but you haven't #include'd the vector library.

You place this as well as functions dealing with what appear to be a program-level user interface in a library that is for Cstring support functions.

You also have problems within the functions themselves. Like in the else of the more() function you try to assign the tolower function to have the value true. Then, in the else of the takeInChar function you return an integer 0 rather than a char. Plus, the takeInChar function is actually taking in an entire line as a string and then just taking off the first character (in the if branch). The if decision here is based not, however, on a bool condition, but an integer value!?

In isAllDigit as well as isAllAlpha you use a raw int rather than the string::size_type chosen especially for indexing and sizing string class data. You also in both these functions have a for loop that might die mid-repeat. Shouldn't that be a while loop?

Neither of these functions, however, nor their use in the isValid function, has anything to do with the program/library at hand in this lab. The goal in the option under consideration was to notice that the two chars at a particular comparison point during our comparison function were both digits and, under those circumstances, compare the strings from that point until the end of their digit sequences as if they were numbers rather than digit sequences. If that still doesn't differentiate the strings, we should keep going with our normal comparison attempt from the ends of the digit sequences within the original strings. That way we can tell that file10.cpp was [probably] produced after file1.cpp but we can also tell that file001.cpp is not a [usefully] different filename from file1.cpp.

loadFromUser is similarly not a Cstring support function and is not part of solving these options.

I hope that helped. If not, keep in mind that I'd recommend throwing out all the new functions and the typedef as unnecessary/unuseful. I'd focus on the situation where the two chars you are about to compare turn out to be digits at the exact same time. When that happens, look into converting that digit sequence (unless they are both a single digit and not multiple digits in a row) into numeric form -- perhaps from the "String Translation It Does A Body Good" lab -- and comparing at that point based on their numeric values. If they are still equal, then go back to char-by-char comparison, otherwise you have your answer!"

So I need your help in fixing this.

Thanks

Need some help ASAP, so I emailed my teacher to verify my code and this is what he said:

"There is so much wrong, it is hard to know where to start.

Yes ... and the place to start is with an up-to-date C++ compiler and an up-to-date C++ course that uses present day C++ standard code.

You had a functioning library and driver and then went to add more levels. But, along the way, you got confused about terminology used in the new options. I thought we'd clarified that in our email discussion, but I see now I was wrong.

I do not have your non-standard version of C++ string...
So how can I help you with it?

But, there are things wrong on so many levels that I'm not sure what angle to approach. You have fundamental coding issues as well as high-level design issues.

Yes ... that seems a fair evaluation ... but your outdated course and compiler ... the root problem!

You try to define a type nickname for a vector of strings, but you haven't #include'd the vector library.

But ... ANY modern version of C++ has the STL

#include <vector> // this is how to do it in std C++

If you are using any non-standard C++ stuff ... recall you must always first include the definition(s) of any code ... before you try to call it.

Edited 2 Years Ago by David W: changed text

This question has already been answered. Start a new discussion instead.