Solved

problem with strtok

Posted on 2001-07-16
9
487 Views
Last Modified: 2012-08-13
why dos this code not work?
I should just be able to
treeAddressParser *tap = new treeAddressParser("this.is.my.moment.my.");
cout << tap->next() << endl;
cout << tap->next() << endl;
and so on???

and are there any good tutorals about useing
strings in c++?


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

class treeAddressParser{
public:
  treeAddressParser(char *address);
  ~treeAddressParser(void);
  char* next(void);
private:
  char *firstToken;
  char *sep;
  bool firstItteration;
  char *token;
};

treeAddressParser::treeAddressParser(char *leafAddress){

  char leafAddressArray[strlen(leafAddress)];
  strcpy(leafAddressArray, leafAddress);

  sep = ".";

  token = (strtok(leafAddressArray, sep));

  firstItteration = true;
}

treeAddressParser::~treeAddressParser(void){
}

char* treeAddressParser::next(void){

  if(firstItteration){
    firstItteration = false;
    return token;
  }
  else{
    return strtok(NULL, sep);
  }

}
0
Comment
Question by:thedogeater
9 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
ID: 6285414
>> char leafAddressArray[strlen(leafAddress)];
In C++ you cannot define a global or local array using a variable length.  You must specify a constant length that is defined at compile time.

You could use new and delete to create a dynamic array of the necessary length, like

treeAddressParser::treeAddressParser(char *leafAddress){

    char *leafAddressArray = new char[strlen(leafAddress) + 1];
    strcpy(leafAddressArray, leafAddress);

    sep = ".";

    token = (strtok(leafAddressArray, sep));

    firstItteration = true;
    delete [] leafAddressArray;  // DANGER.
}
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 6285420
char leafAddressArray[strlen(leafAddress)];
this is error while compiling because it expected a constant value;

for example:

char array[12]; //good

int size=12;

char new_array[size]; //error while compile

must have constant unless using new and then u can set the size of the array:

char* parray = new char(size);

capish?
 
0
 
LVL 22

Expert Comment

by:nietod
ID: 6285435
Note that when I created the array with new, the length I used was not strlen(leafAddress), but instead 1 more than that.  You need to make the array 1 character larger in order to store the NUL character that terminates the string.

Note also the line at the end that deletes the memory used to store string.  Its marked with DANGER.  The line is necessary so you don't have a memory leak.   However your class stores a pointer into this memory (token) so token is left pointing to memory that is deleted  Any attempt to use that pointer vlaue will be in error and will potentially crash your program.  

Note that this is not a new problem.  You had the same problem originally.   you set token to be a pointer into that local variable array that you created ("leafAddressArray").  But when that function ended, the local variable was destropyed, however your "token" variable would still point into this.

You need to remember that "char *" pointers are not strings.  They are pointers to strngs.  When you use them, you need to be extremely careful to make sure they are valid pointers.   You need to make sure that the strings you are trying to work with actually exist.  And you need to make sure they do not overflow the arrays they are stored in.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 6285462
Note also that using strtok() in the way you are trying to do so is risky.  In fact using strtok() is somewhat risky and is often best avoided.   strtok() stores data in static memory somewhere to help it do its work.  That is why successive cals (to get the 2nd token or later tokens) don't need to be passed the pointer to the string to be parsed.  strtok's kept a pointer to it, or to part of it.  The problem is that it means that you cannot parse to different strings "at the same time".  i.e. you can't get token 1 from string A, token 1 from string B, token 2 from strign A, token 2 from string B and so on.  It won't work as strtok gets messed up.   Your class hides the fact that strtok is being used and will make it easy to make that sort of mistake.     You need to think about writting your own strtok().



Working with character arrays is very difficult.  There are lots of ways to make mistakes.  They are also very innefficinet.  Since you are usign C++, why not use C++.

C++ provides string objects so you don't have to work with C's NUL termianted character strings.  This are MUCH easier to use.   You don't have to worry about strings overflowwing their storage space since then expand their storage as needed.  You don't have to worryy about deleting the character arays as the string objects do this automatically.  You don't have to use strcpy to copy the string, you can use =.   You can pass the string to procedures by value and reurn it from a function (no way to do either with C).  You can compare string objects using == < > etc rather than using strcmp().    You can concatenate string objects using + or += rather than strcat()    etc etc etc

For the most part, You should not be using C style strings in C++.   Use string objects.



0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 22

Expert Comment

by:nietod
ID: 6285465
>> must have constant unless using new and then u can set the size of the array:
>>
>> char* parray = new char(size);
That creates a single character that is initailized with the value of the "size" variable..   You need

char* parray = new char[size];
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 6285584
nietod: right , my mistake
0
 

Expert Comment

by:sumansamanta
ID: 6292440
nietod is correct. I would just like to add a comment, that you should use STL strings. But if you are using C-style strings then also, you should not use strtok() call. Reason is that, if you are just doing this for the shake of learning then rather going for strtok() u your self should try and handle the functionalities of strtok(). How you do this is your logic (Hint: use strchr() for finding a char in a string, and ofcourse using the pointer arithmetic sensibly will make you job easier). If u are planning to use it in a real life situation, then also strtok() should be avoided as it uses static data, and hence not thread-safe, ie, unexpected result may appear if you are using strtok simultaneously from multiple threads w/o synchronization (if u do synchronization then your system slows down ...)
0
 
LVL 22

Expert Comment

by:nietod
ID: 6293602
>> strtok() should be avoided as it uses static data, and
>> hence not thread-safe
In any reasonable multi-threaded C++ implimentation, this is made thread safe by the implimentation.  How it is made thread safe is not defined of course since the standard does not deal with multi-threading directly.   Bit it is either done by syncronizing access to the static data or by allocating seprate copies of the data for each thread.
0
 

Author Comment

by:thedogeater
ID: 6293614
Thanks for all the help.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now