R G B element array swap - c++

I'm trying to create this c++ program to perform the description below. I am pretty certain the issue is in the recursive, but uncertain how to fix it. I'm guessing it just keeps iterating through to infinity and crashes. I do not even get an output. I figured I could just compare the previous and current pointer and perform a 3-piece temp swap based on lexicography. I would use a pointer to iterate through the array and decrement it after each swap, then recursively call with that ptr as the parameter. Didn't work, I'm here, help me please :). If there is a simpler solution that would work too, but prefer to understand where I went wrong with this code.
#include <string>
#include <iostream>
using namespace std;
// Given an array of strictly the characters 'R', 'G', and
// 'B', segregate the values of the array so that all the
// Rs come first, the Gs come second, and the Bs come last.
// You can only swap elements of the array.
char* RGBorder(char* c_a)
{
size_t sz = sizeof(c_a)/sizeof(*c_a);
char* ptr_ca = c_a;
char* prv_ptr = ptr_ca;
ptr_ca++;
char temp;
while(*ptr_ca)
{
switch(*ptr_ca)
{
case 'R' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
case 'G' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
default:
ptr_ca++;
continue;
}
ptr_ca++;
cout << *ptr_ca;
}
return c_a;
}
int main()
{
char ca[] = {'G', 'B', 'R', 'R', 'B', 'R', 'G'};
char *oca =RGBorder(ca);
char *pca = oca;
while(*pca)
{
cout << *pca << endl;
pca++;
}
}

There are many issues with your code.
1) You call the function RGBorder with a character pointer, and then attempt to get the number of characters using this:
size_t sz = sizeof(c_a)/sizeof(*c_a);
This will not get you the number of characters. Instead this will simply get you the
sizeof(char *) / sizeof(char)
which is usually 4 or 8. The only way to call your function using a char array is either provide a null-terminated array (thus you can use strlen), or you have to pass the number of characters in the array as a separate argument:
char *RGBorder(char *c_a, int size)
2) I didn't go through your code, but there are easier ways to do a 3-way partition in an array. One popular algorithm to do this is one based on the Dutch National Flag problem.
Since you want the array in RGB order, you know that the series of G will always come in the middle (somewhere) of the sequence, with R on the left of the sequence, and B always on the right of the sequence.
So the goal is to simply swap R to the left of the middle, and B to the right of the middle. So basically you want a loop that incrementally changes the "middle" when needed, while swapping R's and B's to their appropriate position when they're detected.
The following code illustrates this:
#include <algorithm>
char *RGBorder(char *c_a, int num)
{
int middle = 0; // assume we only want the middle element
int low = 0; // before the G's
int high = num - 1; // after the G's
while (middle <= high)
{
if ( c_a[middle] == 'R' ) // if we see an 'R' in the middle, it needs to go before the middle
{
std::swap(c_a[middle], c_a[low]); // swap it to a place before middle
++middle; // middle has creeped up one spot
++low; // so has the point where we will swap when we do this again
}
else
if (c_a[middle] == 'B') // if we see a 'B' as the middle element, it needs to go after the middle
{
std::swap(c_a[middle], c_a[high]); // place it as far back as you can
--high; // decrease the back position for next swap that comes here
}
else
++middle; // it is a 'G', do nothing
}
return c_a;
}
Live Example
Here is another solution that uses std::partition.
#include <algorithm>
#include <iostream>
char *RGBorder(char *c_a, int num)
{
auto iter = std::partition(c_a, c_a + num, [](char ch) {return ch == 'R';});
std::partition(iter, c_a + num, [](char ch) {return ch == 'G';});
return c_a;
}
Live Example
Basically, the first call to std::partition places the R's to the front of the array. Since std::partition returns an iterator (in this case, a char *) to the end of where the partition occurs, we use that as a starting position in the second call to std::partition, where we partition the G values.
Note that std::partition also accomplishes its goal by swapping.
Given this solution, we can generalize this for an n-way partition by using a loop. Assume we want to place things in RGBA order (4 values instead of 3).
#include <algorithm>
#include <iostream>
#include <cstring>
char *RGBorder(char *c_a, int num, char *order, int num2)
{
auto iter = c_a;
for (int i = 0; i < num2 - 1; ++i)
iter = std::partition(iter, c_a + num, [&](char ch) {return ch == order[i];});
return c_a;
}
int main()
{
char ca[] = "AGBRRBARGGARRBGAGRARAA";
std::cout << RGBorder(ca, strlen(ca), "RGBA", 4);
}
Output:
RRRRRRRGGGGGBBBAAAAAAA

Sorry to put it blunt, but that code is a mess. And I don't mean the mistakes, those are forgivable for beginners. I mean the formatting. Multiple statements in one line make it super hard to read and debug the code. Short variable names that carry no immediate intrinsic meaning make it hard to understand what the code is supposed to do. using namespace std; is very bad practise as well, but I can imagine you were taught to do this by whoever gives that course.
1st problem
Your cases don't break, thus you execute all cases for R, and both G and default for G. Also your code will never reach the last 2 lines of your loop, as you continue out before in every case.
2nd problem
You have an endless loop. In both cases you have two situations where you'll end up in an endless loop:
In the else if( *prv_ptr == *ptr_ca ) branch you simply continue; without changing the pointer.
In the else branch you do ptr_ca--;, but then in default you call ptr_ca++; again.(Note that even with breaks you would still call ptr_ca++; at the end of the loop.)
In both cases the pointer doesn't change, so once you end up in any of those conditions your loop will never exit.
Possible 3rd problem
I can only guess, because it is not apparent from the name, but it seems that prv_ptr is supposed to hold whatever was the last pointer in the loop? If so, it seems wrong that you don't update that pointer, ever. Either way, proper variable names would've made it more clear what the purpose of this pointer is exactly. (On a side note, consistent usage of const can help identify such issues. If you have a variable that is not const, but never gets updated, you either forgot to add const or forgot to update it.)
How to fix
Format your code:
Don't use using namespace std;.
One statement per line.
Give your variables proper names, so it's easy to identify what is what. (This is not 1993, really, I'd rather have a thisIsThePointerHoldingTheCharacterThatDoesTheThing than ptr_xy.)
Fix the aforementioned issues (add breaks, make sure your loop actually exits).
Then debug your code. With a debugger. While it runs. With breakpoints and stepping through line by line, inspecting the values of your pointers as the code executes. Fancy stuff.
Good luck!

just count the number of 'R', 'G' and 'B' letters and fill the array from scratch.
much easier, no recursions.

Related

C++ moving characters from one vector to another

I'm new to C++. I am trying to create a program that reads a file named symbols.txt, fill a vector with the symbols, then take chars that are in the range [d;p] and move them to the second vector while erasing them from the first vector.
int main(){
vector<char> sym1;
vector<char> sym2;
int p = 100, d = 80;
char x;
ifstream symbols("symbols.txt");
while (symbols >> x )
{
sym1.push_back(x);
}
for(int i = 0; i < sym1.size(); i++){
if (sym1[i] < p && sym1[i] > d){
sym2.push_back(sym1[i]);
sym1.erase(sym1.begin()+i);
}
}
}
When I do this, the program works if there are no characters the same, otherwise it only moves half of the characters and leaves the other half untouched.
In your implementation, the first thing you need to notice is that in your for loop, sym1.size() changes if you call sym1.erase(). Second, since your variable i increments every time, you skip some elements in the vector.
For example, the element at index 5 is erased, then the element at index 6 will move down to replace it. In the mean time, your loops does i++, so you skip the element that moved to index 5.
I think you should use iterators with C++ containers, below is an example:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<char> sym1;
vector<char> sym2;
int p = 100, d = 80;
char x;
// ifstream symbols("symbols.txt");
// while (symbols >> x)
// {
// sym1.push_back(x);
// }
for(int i = 0; i < 200; i++) {
sym1.push_back(i);
}
int size = sym1.size();
for(vector<char>::iterator it = sym1.begin(); it != sym1.end(); ){
if (*it < p && *it > d){
sym2.push_back(*it);
it = sym1.erase(it);
}
else
it++;
}
for(vector<char>::iterator it = sym2.begin(); it != sym2.end(); it++) {
cout << (int)*it << " ";
}
}
std::vector is good for a lot of things. However, it's terribly inefficient when it comes to insertion or erasing at any other position than the end.
When an element is inserted somewhere (not at end), then the following happens:
The internally managed size is increased by 1. (This may cause a re-allocation of the internal buffer.)
The last element is moved to next position, the second last element is moved to the now "free" position, and so on until the element at insertion index is moved.
Similar happens when an element is erased:
The successor of the element to erase is moved to its previous position, the next is moved to its previous position, and so on until the last element is moved.
Finally, the internally managed size is decreased by 1. (No re-allocation. – The buffer is kept as reserved.)
In OPs case, it's the repeated erasing which makes me concerns. And, when I had this problem in production I used a way to reduce all the moves to the absolutely minimal required.
For this, I use two indices:
one to read and check the characters
one to write the characters which have to be kept in the vector (sym1 in OPs sample).
While the read index is simply incremented for each loop iteration (as usual) the write index is incremented only after an element has been moved (because it should be kept).
As long as nothing is erased, both indices will have identical values. In this case, it's a bit annoying that elements are moved to the position where they already are. However, I consider this as the lesser evil. (Checking whether indices are still identical will probably buy nothing if the move is simple enough.) As soon as something is erased the write index starts to lag behind the read index.
So finally, for a vector of length N there are exactly N write operations to perform (and this for granted). This sounds reliable and not too terrible.
(Erasing elements individually one by one could be in worst case result in
N - 1 + N - 2 + … + 1 moves of elements which are roughly N * (N - 1) / 2 or (N² - N) / 2.)
For the demonstration, the modified sample of OP:
#include <fstream>
#include <iostream>
#include <vector>
int main()
{
std::vector<char> sym1, sym2;
const char p = 'z', d = 'a';
// read sample data
std::ifstream symbols("symbols.txt");
for (char x; symbols >> x;) sym1.push_back(x);
// move all characters in [d, p] to sym2
size_t iWrite = 0;
for (size_t iRead = 0, n = sym1.size(); iRead < n; ++iRead) {
const char c = sym1[iRead];
if (c >= d && c <= p) sym2.push_back(c);
else sym1[iWrite++] = sym1[iRead];
}
// The difference between iWrite - iRead is the number of obsolete elements.
// (It must be equal to sym2.size().)
sym1.resize(iWrite);
// could've been altermatively: sym1.erase(sym1.begin() + iWrite, sym1.end());
// show results:
std::cout << "sym1: '";
for (const char c : sym1) std::cout << c;
std::cout << "'\nsym2: '";
for (const char c : sym2) std::cout << c;
std::cout << "'\n";
}
Input:
I used the above source code as input (as the OP didn't expose the symbols.txt file).
Output:
sym1: '#<>#<>#<>(){::<>1,2;='',='';//::(".");(;>>;)1._();//[,]2_W=0;(_R=0,=1.();R<;++R){=1[R];(>=&&<=)2._();1[W++]=1[R];}//TW-R.//(I2.().)1.(1.()+W,1.());//:::<<"1:'";(:1)::<<;::<<"'\2:'";(:2)::<<;::<<"'\";}'
sym2: 'includefstreamincludeiostreamincludevectorintmainstdvectorcharsymsymconstcharpadzreadsampledatastdifstreamsymbolssymbolstxtforcharxsymbolsxsympushbackxmoveallcharactersindptosymsizetiriteforsizetieadnsymsizeieadnieadconstcharcsymieadifcpcdsympushbackcelsesymiritesymieadhedifferencebetweeniriteieadisthenumberofobsoleteelementstmustbeequaltosymsizesymerasesymbeginiritesymendshowresultsstdcoutsymforconstcharcsymstdcoutcstdcoutnsymforconstcharcsymstdcoutcstdcoutn'
Live Demo on coliru
So, for the range ['a', 'z'], (I used in my demo for better illustration) sym2 ends up containing all lower case characters while sym1 keeps everything else (except the white spaces).
Concerning the missing white spaces I wondered a bit until I realized that the white spaces are filtered out by the read loop:
for (char x; symbols >> x;) sym1.push_back(x);
which used formatted input.
This could be changed using symbols.get(x) instead of symbols >> x but the filtering of white space might be even intended.
Nitpicking:
OP described the range [d;p] (for the characters to move) as requirement.
AFAIK, it's usual that square brackets (or angle brackets) describe ranges with closed ends (i.e. with inclusive border values) while for open ends (exclusive border values) round brackets are used.
Thus, either the requirement has to be (d;p)
or the implementation of the range check
if (sym1[i] < p && sym1[i] > d){ // check for range (d;p)
is not according to the requirement but should be
if (sym1[i] <= p && sym1[i] >= d){ // check for range [d;p]

Logical error. Elements in std::string not replaced properly with for loop

I'm currently doing a programming exercise from a C++ book for beginners. The task reads as follows: "Write a function that reverses the characters in a text string by using two pointers. The only function parameter shall be a pointer to the string."
My issue is that I haven't been able to make the characters swap properly, see the output below. (And I also made the assumption that the function parameter doesn't count, hence why I'm technically using three pointers).
I am almost certain that the problem has to do with the for loop. I wrote this pseudocode:
Assign value of element number i in at_front to the 1st element in transfer_back.
Assign value of element number elem in at_back to element number i in at_front.
Assign value of the 1st element in transfer_back to element number elem in at_back.
Increment i, decrement elem. Repeat loop until !(i < elem)
I wasn't sure whether of not I was supposed to take the null terminator into account. I tried writing (elem - 1) but that messed up with the characters even more so I've currently left it as it is.
#include <iostream>
#include <string>
using namespace std;
void strrev(string *at_front) {
string *transfer_back = at_front, *at_back = transfer_back;
int elem = 0;
while(at_back->operator[](elem) != '\0') {
elem++;
}
for(int i = 0; i < elem; i++) {
transfer_back->operator[](0) = at_front->operator[](i);
at_front->operator[](i) = at_back->operator[](elem);
at_back->operator[](elem) = transfer_back->operator[](0);
elem--;
}
}
int main() {
string str = "ereh txet yna";
string *point_str = &str;
strrev(point_str);
cout << *point_str << endl;
return 0;
}
Expected output: "any text here"
Terminal window: "xany text her"
The fact that the 'x' has been assigned to the first element is something I haven't been able to grasp.
Here is the correct answer
void strrev(string *at_front) {
string *at_back = at_front;
char transfer_back;
int elem = 0;
while(at_back->operator[](elem) != '\0') {
elem++;
}
for(int i = 0; i <elem; i++) {
transfer_back = at_front->operator[](i);
at_front->operator[](i) = at_back->operator[](elem);
at_back->operator[](elem) = transfer_back;
elem--;
}
}
Let me explain why you have that error. string *transfer_back = at_front those two are pointed to the same reference, that is why when you change transfer_back->operator[](0) = at_front->operator[](i);this change will reflect in at_front string as well.
"Write a function that reverses the characters in a text string by using two pointers. The only function parameter shall be a pointer to the string."
This sounds to me like the question addresses C strings but not std::string.
Assuming my feeling is right, this could look like:
#include <iostream>
#include <string>
void strrev(char *at_front) {
char *at_back = at_front;
if (!*at_back) return; // early out in edge case
// move at_back to end (last char before 0-terminator)
while (at_back[1]) ++at_back;
// reverse by swapping contents of front and back
while (at_front < at_back) {
std::swap(*at_front++, *at_back--);
}
}
int main() {
char str[] = "ereh txet yna";
strrev(str);
std::cout << str << '\n';
return 0;
}
Output:
any text here
Live Demo on coliru
Note:
I stored the original string in a char str[].
If I had used char *str = "ereh txet yna"; I had assigned an address of a constant string to str. This feels very wrong as I want to modify the contents of str which must not be done on constants.
strrev():
The at_back[1] reads the next char after address in at_back. For a valid C string, this should be always possible as I excluded the empty string (consisting of 0-terminator only) before.
The swapping loop moves at_front as well as at_back. As the pointer is given as value, this has no "destructive" effect outside of strrev().
Concerning std::swap(*at_front++, *at_back--);:
The swapping combines access to pointer contents with pointer increment/decrement, using postfix-increment/-decrement. IMHO, one of the rare cases where the postfix operators are useful somehow.
Alternatively, I could have written:
std::swap(*at_front, *at_back); ++at_front; --at_back;
Please, note that std::string is a container class. A pointer to the container cannot be used to address its contained raw string directly. For this, std::string provides various access methods like e.g.
std::string::operator[]()
std::string::at()
std::string::data()
etc.

Find all paths of length L in 2 D grid in C++

I'm trying to find all paths of length L in a 2-D grid(forgetting boundaries for the moment) by calling route(string s) recursively and appending to the stringth.
'l' stands for left
'r' stands for right
'd' stands for down
and
'u' stands for up
My logic is correct I think. I need to call route(string s) recursively with each of these values and append to s.
I can see the flaw in my code but cannot think of a way to correct it. I am changing the value of string s by appending to it 'r','l','u' or 'd' at each call but since successive calls are in the same scope, i get garbage answers and not the permutations of u,l,d,r that I am expecting.
#include <iostream>
#include <vector>
using namespace std;
void route(string s, int k);
int main(void){
string result="";
route("",5);
}
void route(string initial, int k){
if(initial.length()>5){
cout<<initial<<endl;
cout<<"Length of initial:"<<initial.length();
return;
}
for(int i=0;i<4;i++){
switch(i){
case 0:
{
initial.append("r");
route(initial);
}
case 1:
{
initial.append("l");
route(initial);
}
case 2:
{
initial.append("u");
route(initial);
}
case 3:
{
initial.append("d");
route(initial);
}
}
}
}
There is no need to change initial, just pass the new string to route. e.g.
route(initial + "u",k-1);
Note that you aren't using the k value currently, and you also aren't recursing for the r and l cases.
One more thing - a for loop with a switch in it for each different case, is a strange construction. Why not just call the 4 different options one after the other?
route(initial + "l",k-1);
route(initial + "r",k-1);
route(initial + "u",k-1);
route(initial + "d",k-1);

Is recursion a bad thing, and is there a clearer or more efficient way of solving problems where recursion seems most useful?

(This problem is taken from IEEE Xtreme 2013 problem AS)
The problem I have to solve is as follows:
I am given a series of letters, consisting of pairs of joined crossroads, such as the below
F G
F H
H I
H J
I K
J K
G H
G I
The task is to navigate from one given letter to another, such as from F to K. In this case the optimum path would be F, H, I, K (i.e. the shortest path (or one of them)).
Part of the task is to find all possible paths. As the length of the path is variable, along with the number of crossroads and the number of crossroads joined to each crossroad, I reasoned I would need a variable level of nested loops - a new nested level of loop for each step along the path, along with the ability to step back along the path and go in a different direction.
the only way I could think of solving this was by creating a function, passing it an incomplete path, search for a joined letter, and have the function call itself until it reaches the end of the path, whereupon it steps back to a previous crossroads and goes in a different direction.
Is the recursion here a bad idea, or inefficient? is there a better/simpler/clearer way of solving this problem?
Code: (It doesn't quite run yet, I'm not finished with it)
(The recursive function is pathfind)
// Problem_AS (ice cream route finder).cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//typdefs
typedef vector<char> route;
//each route when found will be put into a vector of routes
//function declarations
bool checkChar(vector<char>& chars, const char& c);
vector<char> create_turnings(vector<string>& pairs);
vector<char> find_joined(const char& a, vector<string>& routes);
void pathfind(const vector< vector<char> >& joined, const char& current, const char& dest, vector<char>& non_option,
vector<route>& routes, const vector<char>& turnings, route& current_route);
int _tmain(int argc, _TCHAR* argv[])
{
char dest;
cin >> dest;
char start = 'f';
vector<string> joined;
const string a_a = "a a";
char input[4];
do
{
cin.getline(input, sizeof(input));
if (input != a_a)
joined.push_back(input);
} while (input != a_a);
vector<char> turnings = create_turnings(joined);
//alpabetic list of all the turns
/*vector<char>::iterator iter;
for (iter = turnings.begin(); iter < turnings.end(); iter++)
{
cout << *iter << endl;
}*/
//dir is a vector of string vectors - for each letter, there will be a vector, containing all the
//letters that can be reached from the current letter
vector < vector<char> > dir;
for (unsigned int i = 0; i < turnings.size(); i++)
{
dir.push_back(find_joined(turnings[i], joined));
cout << turnings[i] << ": ";
for (unsigned int j = 0; j < dir[i].size(); j++)
{
cout << dir[i][j] << ", ";
}
cout << endl;
}
vector<char> non_option;
//will be passed to functions, contains all the letters that have been used or should not be
route current_route; //contains the current path
vector< route > routes; //vector of all valid paths
pathfind(dir,start, dest, non_option, routes, turnings, current_route);
getchar();
return 0;
}
//checks if char c is present in the character array chars
bool checkChar(vector<char>& chars, const char& c)
{
vector<char>::iterator iter;
for (iter = chars.begin(); iter < chars.end(); iter++)
{
if (*iter == c)
return true;
}
return false;
}
//converts a string vector of pattern:
//"g t"
//"t y"
//"d t"
//etc into a char vector in alphabetic order (containing no repeated characters)
//the first entry in pairs is skipped, as it is empty
vector<char> create_turnings(vector<string>& pairs)
{
vector<char> a;
a.push_back(pairs[1][0]);
if (!checkChar(a, pairs[1][2]))
a.push_back(pairs[1][2]);
vector<string>::iterator iter;
//do first action so that check char in loop has something to check against
for (iter = pairs.begin() + 2; iter < pairs.end(); iter++)
{
if (!checkChar(a, (*iter)[0]))
a.push_back((*iter)[0]);
if (!checkChar(a, (*iter)[2]))
a.push_back((*iter)[2]);
}
sort(a.begin(), a.end());
return a;
}
//takes a letter in the map, and finds all the letters associated with it, and outputs them in a char vector
//(alpthabetcially)
vector<char> find_joined(const char& a, vector<string>& pairs)
{
vector<char> joined;
vector<string>::iterator iter;
for (iter = pairs.begin()+1; iter < pairs.end(); iter++) // must skip first element as it is an empty string
{
if ((*iter)[0] == a)
joined.push_back((*iter)[2]);
if ((*iter)[2] == a)
joined.push_back((*iter)[0]);
//must check is the letter we are finding associations for on the left or right of the route - the opposite
//side of the joined letters will be added
}
sort(joined.begin(), joined.end());
return joined;
}
void pathfind(const vector< vector<char> >& joined, const char& current, const char& dest, vector<char>& non_option,
vector<route>& routes, const vector<char>& turnings, route& current_route)
{
current_route.push_back(current);
non_option.push_back(current);
//find the index of current in turnings
unsigned int index;
for (index = 0; index < turnings.size(); index++)
{
if (turnings[index] == current)
break;
}
int x = joined[index].size();
for (int i = 0; i < x; i++)
{
if (checkChar(non_option, joined[index][i]))
continue;
//check if the character being checked has been makred as a non option already
if (joined[index][i] == dest)
{
current_route.push_back(joined[index][i]);
routes.push_back(current_route);
continue;
}
//check if the character being checked is the destination, in which case mark a route
pathfind(joined, joined[index][i], dest, non_option, routes, turnings, current_route);
while (non_option.size() != current_route.size())
{
non_option.pop_back();
}
}
while (non_option.size() != current_route.size())
{
non_option.pop_back();
}
current_route.pop_back();
}
In answer to the question, but without specific reference to the code given:
Is recursion a bad thing?
In general, No.
What are the trade-offs?
Often using recursion boils down to simplicity of implementation versus simpicity of debugging and flexibility of changing implementations.
General factors around recursive / non-recursive implementations:
Judging by the number of questions that crop-up on StackOverflow regarding recursion, it's pretty clear that recursive code is harder to follow for many developers, partly because the code-path isn't always obvious. A non-recursive function is often easier to debug... you can step through the code and examine your stack easily without having to track which invocation of the method you're at.
However, removing recursion can sometimes make code more complex... often you have to introduce your own stack and do a bit of housekeeping that isn't necessary with recursive code.
I frequently see posters on Stack Overflow using recursion when a simple iteration would suffice such as traversing a list (no stack needed). In these trivial cases recursion should definitely be avoided (unless its a requirement of your assignment). In more comlex cases, the performance differences between a recursive solution and a non-recursive one usually aren't significant.
And although recursion itself isn't bad, one consideration is that because the size of the stack is limited by your environment you have an arbitrary limit imposed on you for the amount of recursive calls. If you know that the termination condition for your calls is met quickly then by all means recurse. If you're working with very large data sets, and potentially deep recursion, exercise caution and favour a non-recursive implementation.
Whenever you are thinking about a recursive solution (or any algorithm for that matter), favour clarity, readability and easy debugging first, only optimise when performance profiling shows there's a problem. Try to keep code encapsulated so implementations can be easily swapped out.
The recursion in not always a bad idea, however there's a problem with using a recursion which is the stack depth. If your recursion goes too deep - you run out of stack and your program will not work properly. Stack depth can change from system to system, may or may not be adjustable, and stack overruns may or may not lead to an immediate crash.
If you're considering a recursion of bounded depth that you know is within the limits of your stack - go for it, it is the easier way to write code.
If you're considering recursion with unbounded depth (i.e.: you don't know how big the input can be and how many calls you're going to make) - you better implement it iteratively (i.e.: without using the OS stack, use your own structures to manage the state).
There are also ways to make recursions more efficient wrt the stack usage (for example - tail recursion).
In this particular case, the input doesn't seem to be too large, and I'd expect the recursion to work. If it doesn't - it is more likely to be a bug in your algorithm/implementation, rather than an inherent "recursion problem".

extracting data between having { } any other method with good run time

I have this piece of code where am extracting the data between the { }, and this takes me around O(n) is there any other method which is more effcient
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
const char *blah = "[{post:banb {bbbbbbbb}: ananmsdb},{dsgdf{9090909090}fdgsdfg}";
std::string op;
unsigned int i = 0;
int im = 0;
int found = 0;
while(strlen(blah) != i){
if(blah[i] == '{'){
found = 1;
// copy what ever u got
op+=blah[i];
im++;
}
else if(blah[i] == '}'){
//copy wat ever u got
op+=blah[i];
im--;
}
if(found ==1){
//copy wat ever u got.
op+=blah[i];
}
if(found ==1 && im == 0) {
found = 0;
cout << op <<endl;
op.clear() ;
// u have found the full one post so send it for processing.
}
i++;
}
}
output :post:banb {bbbbbbbb}: ananmsdb
dsgdf{9090909090}fdgsdfg
No. You can use library functions to make this code shorter, but it will never be more efficient than O(n) where n is the length of the input string, since you need to examine each character at least once because each one could potentially be a token that you need to extract.
I don't think you can improve on O(n) for the underlying algorithm, but you can probably improve your implementation.
Currently your implementation may well be O(n^2) rather than O(n), as strlen() could be called on every iteration (unless your compiler is particularly smart). You should probably cache the call to strlen() explicitly, e.g. change:
while(strlen(blah) != i){
...
to:
const int len = strlen(blah);
while(len != i){
...
As everybody else has said there is no way to make this faster as you have to check every character incase you miss one.
But, this being said if perhaps you already knew some information about the data aka how many pairs of '{' and'}' then I can onlythink of one way(besides sorting but that brings it back to O(n) + etc).
This would be to choose indexes between 0 - x and randomly check at spots if you can find the '{' or '}'. Just to be clear this will only work if you know how many '{' and '}'s are already in the set of data.
Edit: Addtionally the copy you provided (just from using notepad) when it hits the first cout<< it should output "{{post:banb {{bbbbbbbb}}: ananmsdb}}", as its creating additional {'s and }'s.