Results 1 to 29 of 29

Thread: string manipulations

  1. #1

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500

    string manipulations

    what would the equivalent of Left, Right, Mid(Mid$) be in C++?
    Len is strlen right?
    thanks
    Amon Ra
    The Power of Learning.

  2. #2
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    You use strncpy() to get out a part of a string, into another.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  3. #3
    jim mcnamara
    Guest
    I'll post C versions of this when I get to work. The stdlib & string operations in C are rudimentary. You have to implement your own versions of this stuff.

    The CString class supports

    ::Left, ::Right, and ::Mid operations

    Go into help- CString class members there's loads of them.

  4. #4
    jim mcnamara
    Guest
    Here are some vanilla c versions of string things:

    Code:
    void trim(char *t){
    	rtrim(t);
    	if (strlen(t))
    	     ltrim(t);
    }
    
    void rtrim(char *t){
         char *buf;
         if (!strlen(t) ) return;
         buf = t;
         buf += strlen(t) -1;
         while (*buf == ' ' && strlen(t) )
                *buf-- = '\0';
    }
    void ltrim(char *t){
         char tmp[128];
         char *buf;
         if (!strlen(t) ) return;
         strcpy(tmp,t);
         buf=tmp;
         while (*buf == ' ' && strlen(buf))	*buf++;
         strcpy(t,buf);
    }
    
    char *right(char *t,int len){
          char *buf;
          int i;
          if (strlen(t) <=len)
                   return t;
          buf = t;
          buf +=strlen(t);
          for (i=0;i<len;i++) buf--;
          return buf;
    }
    
    char *left(char *t,int len){
            char *buf;
            if (strlen(t)<=len)
                      return t;
            buf = t;
            buf += len;
            *buf = '\0';
            return t;
    }
    char *mid(char *t,int start, int len){
    	char *buf;
    	int i;
    	if (!strlen(t) )
    	         return t;
            buf = t;
            buf +=start;
            buf = left(buf,len);
            return buf;
    }

  5. #5

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    great thanks =)
    Amon Ra
    The Power of Learning.

  6. #6
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    PS: If you don't want to do it in C, then I would suggest using string unless it absolutely has to work with MFC.
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  7. #7

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    nono, everything is pure API..=)
    are there such functions with the string class?
    thanks
    Amon Ra
    The Power of Learning.

  8. #8
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    Yes. string::substr
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  9. #9

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    how would i translate this to c++

    Code:
    Dim sBuf As String
    Dim iSize As String
    Dim iRetCode As Integer
    
        sBuf = Space$(8192)
        iSize = Len(sBuf)
    thanks
    Amon Ra
    The Power of Learning.

  10. #10

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    jim, the "left" function gives me an illegal operation =(
    Amon Ra
    The Power of Learning.

  11. #11

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    where do i find the "substr" function??
    Amon Ra
    The Power of Learning.

  12. #12
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    Code:
    string sBuf;
    
    // Couldn't think of another way off the top of my head
    for(int i = 0; i < 8192) sBuf += " ";
    
    int iSize = sBuf.length();
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  13. #13
    jim mcnamara
    Guest
    Oh. Strings aren't initialized, you have to do that yourself. All of these functions depend on there being a terminating NULL char.
    If fact, good programming practice is to init everything

    int blah = 0;
    struct z mystruct;
    zout(mystruct);
    char tmp[100];
    zout(tmp); etc.

    I don't do a lot of standard good stuff in examples because I'm lazy.

    Code:
    #define zout(x) memset(&x,'\0',sizeof(x) )
    char tmp[20];
    printf("%s\n",left(tmp,3));   <<<< may give error
    zout(tmp);
    printf("%s\n",left(tmp,3) );  <<< okay
    You do realize that the version you used of "left" actually changes the original string? BASIC doesn't change the original string. What is done a lot of languages is to create so-called string space kinda like this (with a lot of details left out):
    Code:
    char stringspace[BIG];  << global area - BIG is some big number
                                                BIG is often set to BUFSIZ + 1
    
    // non-destructive left
    char *left(char *t,int len){
            char *buf;
            strcpy(stringspace,t);
            if (strlen(t)<=len)
                      return t;
            buf = stringspace;
            buf += len;
            *buf = '\0';
            return stringspace;
    }
    You may want to do something like that, so you need worry about fewer things.

  14. #14

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    thanks jim =)
    parksie, i tried doing the space thing like that:

    Code:
    char *buf;
    
    for(int i=0; i<5; i++)
    {
        strcat(boom, " ");
    }
    
    void main()
    {
    cout << boom << endl;
    }
    it doesn't work...i wanna try not using the string class, cuz for the other functions i haven't..its good to know though...
    it gives me an illegal operation.
    thanks
    Amon Ra
    The Power of Learning.

  15. #15

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    how would i write an equivalent to Space in VB, without using the string class..i mean:

    Code:
    string s;                //not using string
    char *str;              //but using char *
    thanks
    Amon Ra
    The Power of Learning.

  16. #16

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    please? when i do it i get an illegal operation..=(
    Amon Ra
    The Power of Learning.

  17. #17
    jim mcnamara
    Guest
    Kedaman -

    you're right - what I"m trying to show is that standard C strings
    have to have a terminating NULL. They are not created that way.

    You shouldn't just randomly init variables. Init them once in the module that declares them (constructor), and leave it at that.
    For global variables, specifically call a function like glob_init:

    Code:
    void glob_init(void){
           stringspace = (char *)calloc(BUFSIZ+1);
           atexit(glob_free);
    }
    void glob_free(void){
           free(stringspace);  // or whatever else is global
    }
    I use calloc as it does the "zout" thing as well as allocate memory. Most folks starting out seem to want to use

    char stringapce[BIG];

    -instead of calloc; that's the reason for the zout macro.

    Amon -

    spaces

    Code:
    // note: this does not check for the validity of len
    void spaces(char *t, int len){
               char *buf;
               int i=0;
               buf=t;
               for(i=0;i<len;i++){
                          *buf = ' ';
                           buf++;      
               }
               *buf='\0';        // add terminal NULL
    }
    Since I got you in trouble before - suppose you have:

    Code:
     char tmp[100];
     int i;
    
     spaces(tmp,100);
    Looks good, right? Wrong.

    tmp only holds 99 chars. The first byte of i will be overwritten.

    C usually allocates memory for local function variables contiguously. That means if you ask the stupid spaces function to blank out 105 chars in spaces() it will try to do that as well. And it will nuke anything declared after tmp. This is usually what causes those illegal operations you are getting. You can overwrite code, file buffers, and other stuff the same way too.

    safe use of spaces:

    spaces(sizeof(tmp) - 1);

  18. #18
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    Jim -
    Originally posted by jim mcnamara
    You shouldn't just randomly init variables. Init them once in the module that declares them (constructor), and leave it at that.
    For global variables, specifically call a function like glob_init:
    I have local variables, member variables, but seldom global variables, so seldom i could almost say never. If I init my variables, I do it where they are needed.

    Instead of global variables, have them in your main proc. That won't expose them unnessesarily.
    I use calloc as it does the "zout" thing as well as allocate memory. Most folks starting out seem to want to use

    char stringapce[BIG];

    -instead of calloc; that's the reason for the zout macro.
    calloc allocates on the heap right? If that's the case then you probably use zout on stack variables, more specifically those that obviously won't initialize themselves. I haven't used calloc before so do you mean it fills the memory with 0es after it's allocation?



    Amon - You could use memset as well, I replied to your other thread.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  19. #19

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    thank you very much guys..i appreciate..=)
    just one question, is it just me, or is the space function in VB suppoesed to overwrite the string with ' ' ?
    thanks again =)
    Amon Ra
    The Power of Learning.

  20. #20

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    when i do this

    PHP Code:
    void main()
    {
        
    char buf[10];
        
    int i;

        
    spaces(bufsizeof(buf));
        
    cout << buf << endl;

    i dont get an erro though..it works fine...should i still do

    Code:
    sizeof(buf) - 1
    or is it not necessary?
    thanks
    Amon Ra
    The Power of Learning.

  21. #21
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    space in vb returns a string with the spaces, in most cases that's not too usefull. More generic is to fill something with spaces, or better any character like memset does. If you want separate strings, you use strncopy, and then memset.

    you should use sizeof(buf) - 1 because it puts the terminating null after the last char.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  22. #22

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    great thanks =)
    Amon Ra
    The Power of Learning.

  23. #23
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    btw if you write past the end of an array, it is a bug, because you might overwrite something else (the compiler is unable to detect these, it's runtime specific). If you're lucky the app just crashes, if not, it could change other variables causing unexpected results, like your harddrive getting formatted
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  24. #24

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    lol thanks for the tip...=)
    one more thing

    Code:
    iPos = InStr(sValue, Chr$(0))
    is the equivalent to InStr in VB -> strchr in C++?
    thanks
    Amon Ra
    The Power of Learning.

  25. #25
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    Yep, you would do for instance

    char* p = strchr(mycstring,0);

    but the c strings always terminate with 0 so strlen(mycstring); will also work.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  26. #26
    jim mcnamara
    Guest
    strchr() is the generic version of looking in a string-

    but note - you wanted the first occurrence of \0 - which
    in C is really strlen()

    memset is easier to use - however the version spaces I gave you is specific version of how memset is implemented in gcc.

    FYI -

    strstr() is the C version of instr, it will work with single chars as well.

















    The examples I gave you are all pointer based. If you don't understand 'em Kedaman suggested memset(), which is just fine.

  27. #27

    Thread Starter
    Hyperactive Member Amon Ra's Avatar
    Join Date
    Feb 2001
    Location
    In some cave on Uranus...
    Posts
    500
    nono thanks..i do understand how they work with pointers..i just wanted to make sure which was the equivalent of InStr..so it is strstr?
    thanks
    Amon Ra
    The Power of Learning.

  28. #28
    jim mcnamara
    Guest
    Oh. PS: Kedaman's suggestion about memset() is a good one, especially if you are uncomfortable with pointers. In C you need to realize there are VERY FEW functions compared to VB. Probably about 10%. Everything else you do yourself. I've got a library of routines that I've had for... too long. I just re-use them.


    Ked -

    calloc() is like malloc() and then memset() with 0's.

    Global variables are more efficient, but they do tend to screw up
    data abstraction. I just finshed a 20K line program the other day. Virtually all the production code I've seen makes use of globals. This one has about 20 global variables.

    Dont' believe me (about the speed part)?

    Try timing like GetTickCount() on these two code hunks:

    Code:
    char *a="ABCDEFGHIJKMLNOPRSTUVXWYX1234567890";
    char *b= "0987654321";
    char tmp[500];
    
    void test(){
            long i,start;
            char *t;
            start = GetTickCount();
            for (i=0;i<200000;i++){
                 testbed(t);
            }
            printf("%ld\n", GetTickCount() - start);
    }
    
    void testbed(char *t){
             memset(tmp,'\0',sizeof(tmp) );
             strcat(tmp,a);
             strcat(tmp,b);
             *t= tmp[1];
    }
    Versus this block without globals....

    Code:
    void test(){
            long i,start;
            char *t;
            start = GetTickCount();
            for (i=0;i<200000;i++){
                 testbed(t);
            }
             printf("%ld\n", GetTickCount() - start);
    }
    
    void testbed(char *t){
     
            char *a="ABCDEFGHIJKMLNOPRSTUVXWYX1234567890";
            char *b= "0987654321";
            char tmp[500];
            memset(tmp,'\0',sizeof(tmp) );
            strcat(tmp,a);
            strcat(tmp,b);
            *t= tmp[1];
    }

    Please let me know what you find on your machine....

  29. #29
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221

    Global VS Local

    Jim - I had to do some modifications of your code. First off the wild pointer t made it crash, it's now a local variable and i pass it's address. Next unlike the global version, the strings are initialized each time in the testbed method, totally unnessesarily. Make them const and you'll see the time gap between is eliminated. You may be right that access of nonstatic member variables of classes can be slower, but insignificantly, local and global variable should not be different, and member access should be restricted by using local buffers at time critical processes.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width