Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

problem with strtok

Posted on 2001-07-16
9
Medium Priority
?
495 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
9 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 150 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

715 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