How to reversely strtok a C++ string from tail to head? - c++

I think I need a reverse version of strtok, like:
char* p = rstrtok(str, delimeters);
For example, sequentially get the position of '-', '_' and '+' in the string "hello+stack_over-flow" using a delimeter set of "+_-"
I only care about the delimeters, and their position, (not the content between), so I guess the boost::split_iterator is not appropriate here.
Is there any existing utility function I can leverage? or any solution to deal with this kind of situation?
Furthermore, since I am doing C++, is there any convenient approach to avoid this old fashion C?
(I searched "reverse strtok" but merely get "stack over flow" to "flow over stack" stuff...)

You could roll your own using strrchr.
If you use C++ style std::string you can leverage string::find_last_of.

You could do this with strpbrk:
char string[] = "hello+stack_over-flow";
char *pos = string;
while (*pos != '\0' && (pos = strpbrk(pos, "+-_")) != NULL)
{
/* Do something with `pos` */
pos++; /* To skip over the found character */
}

strtok is pretty simple in the most basic versions - a couple hundred lines at most.
If you google "strtok filetype:c" you can see how it's implemented in the various libraries.
A very naive solution would be to reverses the string first, and then do the strtok().
This is bad for long strings though, but if you need performance, go roll your own strtok().
Something like this:
void reverse(char* dest, const char* src)
{
int len = strlen(src);
int i;
for(i = 0; i < len; ++i)
dest[len-i-1] = src[i];
}
EDIT:
Coincidentally I have this Dr Dobbs page open in a tab from a google search yesterday: http://www.drdobbs.com/conversations-al-go-rithms/184403801

Related

How to reverse a user input without using array or any library function(any function for reversing)?

Let me clear you first that I'm not a college student and this is not my home assignment. I am just curious to know the solution of this question which was once asked to me. I think this is a nice and tricky question which I feel worth sharing.The question was--
How do you input a string(said in general sense, independent of programming) from a user and print reverse of it in C/C++ without using array or any library function for reversing the user input?
I am unable to break-into this. Help please
Note: Members are marking it as a duplicate for this question. But All answers to this are either using library functions or using a pointer to char array(char *). None of them is allowed in my case. Please review it once again
You can try recursion.
void print_reverse_str() {
int c = getchar();
if (c != EOF) {
print_reverse_str();
putchar(c);
}
}
Technically this is impossible because a string is a char array in c and an object representing a char array in c++.
I hope you meant not using arrays directly.
So try this pointer based solutions :
void strrev(char *str)
{
if( str == NULL )
return;
char *end_ptr = &str[strlen(str) - 1];
char temp;
while( end_ptr > str )
{
temp = *str;
*str++ = *end_ptr;
*end_ptr-- = temp;
}
}

Assigning chars to a char array with +=

Currently I'm writing a rather extensive homework assignment that - among other things - reads a file, builds a binary search tree and outputs it.
Somewhere inside all that I've written a recursive method to output the values of the binary search tree in order.
void output(node* n)
{
if(n->leftChild != NULL)
output(n->leftChild);
cout << n->keyAndValue << " || ";
outputString += n->keyAndValue << '|';
if(n->rightChild != NULL)
output(n->rightChild);
}
No problem with that, but you'll notice the line outputString += n->keyAndValue << '|';, because I also want to have all the values inside a char array (I am not allowed to use strings or other more current features of C++) that I can use later on in a different method (e.g. Main method).
The Char-Array is declared as follows:
char *outputString;
This being just one of the ways I've tried. I also tried using the const keyword and just regularly building an array char outputString[]. With the version I've shown you I encounter an error when - later on in the program in a different method - calling the following code:
cout << outputString;
I get the following error:
Unhandled exception at 0x008c2c2a in BST.exe: 0xC00000005: Access Violation reading location 0x5000000000.
Any clue as to how I'd be able to build a dynamic char array, assign values to it numerous times using += and outputting it without triggering an access violation? I am sorry for asking a rather basic question but I am entirely new to C++.
Thanks and Regards,
Dennis
I'm guessing that since you can't use std::string, you also can't use new[].
You can concatenate strings with a function like this:
char *concat(const char *s1, const char *s2)
{
size_t len = strlen(s1) + strlen(s2);
char *result = (char*)malloc(len+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
This can be done more efficiently, but that probably doesn't matter for homework. And you need to check for errors, etc. etc.
You also need to decide who is going to call free on s1 and s2.
For what it is worth, the efficient version looks like this:
char *concat(const char *s1, const char *s2)
{
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
char *result = (char*)malloc(len1+len2+1);
memcpy(result, s1, len1);
memcpy(result+len1, s2, len2);
result[len1+len2] = '\0';
return result;
}
It's more efficient because it only walks the input strings once.
+= on pointers does pointer arithmetic, not string concatenation. Eventually you get way beyond your array that outputString was pointing to, and trying to print it leads to a segfault.
Since you can't use std::string, you need to use strcat along with new[] and delete[] and make sure you allocated your original array with new[].

CString find the last entry

I have two CString s1 and CString s2. I need find the last entry s2 in s1.
I can find any metod in CString like in C# LastIndexOf.
I am nooby in c++. Thanks in advance.
CString has no such function. You have to write it yourself, e.g.
int LastIndexOf(const CString& s1, const CString& s2)
{
int found = -1;
int next_pos = 0;
for (;;)
{
next_pos = s1.Find(s2, next_pos);
if (next_pos == -1)
return found;
found = next_pos;
};
}
A more optimal algorithm would reverse the strings first, I'm leaving that as an exercise.
i adopted the answer from Andrey (to increment the next_pos, seems to cause an endless loop without it). aaand, since i don't have enough repu points yet (can't comment) i'll post it as a separate answer:
int LastIndexOf(const CString& s1, const CString& s2)
{
int start = s1.Find(s2, 0);
if (start >= 0)
{
while (start < s1.GetLength())
{
int idx = s1.Find(s2, start+1);
if (idx >= 0)
start = idx;
else
break;
}
}
return start;
}
There is no CString method to directly address your question. However, you can use a combination of CString::ReverseFind + _tcsncmp to first locate next occurrence of last character of substring and, if found, compare the whole substring from there.
CString is I think part of the "Microsoft Foundation Class Library" and is not Standard C++.
There is a reference including methods here:
http://msdn.microsoft.com/en-us/library/aa315043%28v=vs.60%29.aspx
I don't see anything to turn that directly into a std::string (which has a lot more methods), but it probably is not so hard, either (search for "CString to std::string" and you'll find some stuff).
Although they are presumably related, don't confuse this with a c-string, which is an array of chars from Standard C included in Standard C++.

std string vs char performance, best technique to delete parts from the beginning

well i have to process a large chunk of text, analysing it linear from begin to end. And i wonder what is the better approach for this: using char* or std::string.
while using char* i can alter the pointer to a position further in the string eg.
//EDIT later: mallocing some space for text
char str[] = "text to analyse";
char * orig = str;
//process
str += processed_chars; //quite fast
//process again
// later: free(orig);
but using string i might have to use std::string::erase - but it create a copy, or move bytes or something (i don't know the actual implementation)
string str = "text to analyse";
//process
str = str.erase(0,processed_chars);
or is there a way to alter the std::string's hidden pointer?
EDIT: as Sylvain Defresne requested here more code:
class tag {
public:
tag(char ** pch) {
*pch = strstr(*pch,"<");
if(pch == NULL) return;
char *orig = *pch+1;
*pch = strstr(*pch,">");
if(pch == NULL) return;
*pch+=sizeof(char); //moving behind the >
//process inner tag data
if(*(*pch-2)!='/'){// not selfclose
while (!(**pch == '<' && *(*pch+1) == '/')){ //sarch for closing tag
tag* kid = new tag(pch);
sublings.push_back(*kid);
}
*pch = strstr(*pch,">");
if(pch == NULL) return;
*pch+=sizeof(char); //moving behind the >
//add check if the clothing tag is matching
}
}
}
i use it for recursive xml-like notation parsing
char str[] ="<father><kid /></fatherr>";
char * pch = str;
tag *root = new tag(&pch);
this code is ugly as hell, i am just starting with low-level pointer arithmetic and stuff, used visual components till now so don't judge too hard
With std::string, you would probably use std::string::iterator. Your code would be:
std::string str = "text to analyse";
std::string::iterator iter = str.begin();
// process
iter += processed_chars;
Anything you can do with a char*, you can do with an std::string::iterator.
You can use std::string::iterator (look here).
std::string is not neccassary in such task (but such classes as std::string are very useful in other situations).

Please suggest what is wrong with this string reversal function?

This code is compiling clean. But when I run this, it gives exception "Access violation writing location" at line 9.
void reverse(char *word)
{
int len = strlen(word);
len = len-1;
char * temp= word;
int i =0;
while (len >=0)
{
word[i] = temp[len]; //line9
++i;--len;
}
word[i] = '\0';
}
Have you stepped through this code in a debugger?
If not, what happens when i (increasing from 0) passes len (decreasing towards 0)?
Note that your two pointers word and temp have the same value - they are pointing to the same string.
Be careful: not all strings in a C++ program are writable. Even if your code is good it can still crash when someone calls it with a string literal.
When len gets to 0, you access the location before the start of the string (temp[0-1]).
Try this:
void reverse(char *word)
{
size_t len = strlen(word);
size_t i;
for (i = 0; i < len / 2; i++)
{
char temp = word[i];
word[i] = word[len - i - 1];
word[len - i - 1] = temp;
}
}
The function looks like it would not crash, but it won't work correctly and it will read from word[-1], which is not likely to cause a crash, but it is a problem. Your crashing problem is probably that you passed in a string literal that the compiler had put into a read-only data segment.
Something like this would crash on many operating systems.
char * word = "test";
reverse(word); // this will crash if "test" isn't in writable memory
There are also several problems with your algorithm. You have len = len-1 and later temp[len-1] which means that the last character will never be read, and when len==0, you will be reading from the first character before the word. Also, temp and word are both pointers, so they both point to the same memory, I think you meant to make a copy of word rather than just a copy of the pointer to word. You can make a copy of word with strdup. If you do that, and fix your off-by-one problem with len, then your function should work,
But that still won't fix the write crash, which is caused by code that you have not shown us.
Oh, and if you do use strdup be sure to call free to free temp before you leave the function.
Well, for one, when len == 0 len-1 will be a negative number. And that's pretty illegal. Second, it's quite possible that your pointer is pointing at an unreserved area of memory.
If you called that function as followed:
reverse("this is a test");
then with at least one compiler will pass in a read only string due to backwards compatibility with C where you can
pass string literals as non-const char*.