I'm creating a program that gathers a char array of max 10 characters. It then asks the user to enter a character. If the character is found, it will delete all entries in the array of that character and move the remaining characters in the array forward to remove all gaps.
This is the code I have currently:
for (int n = 0; n == 10; n++)
{
int index(0);
**while (text[index] != EOT)
{
if (text[index] == letter)
{
while (text[index] != EOT)
{
text[index] = text[index + 1];
index++;
}
}
else
index++;
}**
}
the code in bold (or with the ** between it* is currently working, and removes the FIRST instance of the character the user enters. So I decided to put a for loop around the whole while loop to make it repeat that code 10 times. Therefore as the input is limited to 10 characters it will (or should) work?
However it doesn't do anything anymore. It won't even remove the FIRST instance of the character and it is really baffling me. Can anyone see where I am going wrong?
It's c++ and i'm using Visual Studios 2013 by the way.
Thanks!
This control statement of the loop
for (int n = 0; n == 10; n++)
means that the loop will be executed never. You assigned zero to n and then said: "Execute the loop while n is equal to 10". But n is answering: " I am not equal to 10".:)
You could perform the task simpler by using standard algorithm std::remove
For example
#include <algorithm>
#include <cstring>
//...
*std::remove( text, text + std::strlen( text ), letter ) = '\0';
Your problems are because you are using the same index variable to loop in two different places
for (int n = 0; n == 10; n++)
{
int index(0);
**while (text[index] != EOT) // loop 1
{
if (text[index] == letter) // loop 1
{
while (text[index] != EOT) // loop 2
{
text[index] = text[index + 1]; // loop 2
index++; // loop2
}
}
else
index++; // loop 1
}**
}
change your code to
for (int n = 0; n == 10; n++)
{
int index(0);
while (text[index] != EOT)
{
if (text[index] == letter)
{
int index2(index);
while (text[index2] != EOT)
{
text[index2] = text[index2 + 1];
index2++;
}
}
else
index++;
}
}
I'd suggest the following solution:
std::string text;
char charToBeRemoved;
text.erase (std::remove(text.begin(), text.end(), charToBeRemoved), text.end());
when you do your loop you check you variable n wrong.
for (int n = 0; n == 10; n++)
should be
for (int n = 0; n < 10; n++)
this will loop ten times.
You should use a std::vector, it's easier for you here.
for(std::vector<char>::iterator it = vect.begin() ; it != vect.end() ; it++)
{
if((*it) == letter)
{
vect.erase(it);
}
}
Related
*Sorry about my poor English. If there is anything that you don't understand, please tell me so that I can give you more information that 'make sence'.
**This is first time asking question in Stackoverflow. I've searched some rules for asking questions correctly here, but there should be something I missed. I welcome all feedback.
I'm currently solving algorithm problems to improve my skill, and I'm struggling with one question for three days. This question is from https://algospot.com/judge/problem/read/RESTORE , but since this page is in KOREAN, I tried to translate it in English.
Question
If there are 'k' pieces of partial strings given, calculate shortest string that includes all partial strings.
All strings consist only lowercase alphabets.
If there are more than 1 result strings that satisfy all conditions with same length, choose any string.
Input
In the first line of input, number of test case 'C'(C<=50) is given.
For each test case, number of partial string 'k'(1<=k<=15) is given in the first line, and in next k lines partial strings are given.
Length of partial string is between 1 to 40.
Output
For each testcase, print shortest string that includes all partial strings.
Sample Input
3
3
geo
oji
jing
2
world
hello
3
abrac
cadabra
dabr
Sample Output
geojing
helloworld
cadabrac
And here is my code. My code seems to work perfect with Sample Inputs, and when I made test inputs for my own and tested, everything worked fine. But when I submit this code, they say my code is 'wrong'.
Please tell me what is wrong with my code. You don't need to tell me whole fixed code, I just need sample inputs that causes error with my code. Added code description to make my code easier to understand.
Code Description
Saved all input partial strings in vector 'stringParts'.
Saved current shortest string result in global variable 'answer'.
Used 'cache' array for memoization - to skip repeated function call.
Algorithm I designed to solve this problem is divided into two function -
restore() & eraseOverlapped().
restore() function calculates shortest string that includes all partial strings in 'stringParts'.
Result of resotre() is saved in 'answer'.
For restore(), there are three parameters - 'curString', 'selected' and 'last'.
'curString' stands for currently selected and overlapped string result.
'selected' stands for currently selected elements of 'stringParts'. Used bitmask to make my algorithm concise.
'last' stands for last selected element of 'stringParts' for making 'curString'.
eraseOverlapped() function does preprocessing - it deletes elements of 'stringParts' that can be completly included to other elements before executing restore().
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
string answer; // save shortest result string
vector<string> stringParts;
bool cache[MAX + 1][(1 << MAX) + 1]; //[last selected string][set of selected strings in Bitmask]
void restore(string curString, int selected=0, int last=0) {
//base case 1
if (selected == (1 << k) - 1) {
if (answer.empty() || curString.length() < answer.length())
answer = curString;
return;
}
//base case 2 - memoization
bool& ret = cache[last][selected];
if (ret != false) return;
for (int next = 0; next < k; next++) {
string checkStr = stringParts[next];
if (selected & (1 << next)) continue;
if (curString.empty())
restore(checkStr, selected + (1 << next), next + 1);
else {
int check = false;
//count max overlapping area of two strings and overlap two strings.
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size()-i, i) == checkStr.substr(0, i)) {
restore(curString + checkStr.substr(i, checkStr.length()-i), selected + (1 << next), next + 1);
check = true;
break;
}
}
if (!check) { // if there aren't any overlapping area
restore(curString + checkStr, selected + (1 << next), next + 1);
}
}
}
ret = true;
}
//check if there are strings that can be completely included by other strings, and delete that string.
void eraseOverlapped() {
//arranging string vector in ascending order of string length
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
//deleting included strings
vector<string>::iterator iter;
for (int i = 0; i < vectorLen-1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C; // testcase
for (int testCase = 0; testCase < C; testCase++) {
cin >> k; // number of partial strings
memset(cache, false, sizeof(cache)); // initializing cache to false
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
eraseOverlapped();
k = stringParts.size();
restore("");
cout << answer << endl;
answer.clear();
stringParts.clear();
}
}
After determining which string-parts can be removed from the list since they are contained in other string-parts, one way to model this problem might be as the "taxicab ripoff problem" problem (or Max TSP), where each potential length reduction by overlap is given a positive weight. Considering that the input size in the question is very small, it seems likely that they expect a near brute-force solution, with possibly some heuristic and backtracking or other form of memoization.
Thanks Everyone who tried to help me solve this problem. I actually solved this problem with few changes on my previous algorithm. These are main changes.
In my previous algorithm I saved result of restore() in global variable 'answer' since restore() didn't return anything, but in new algorithm since restore() returns mid-process answer string I no longer need to use 'answer'.
Used string type cache instead of bool type cache. I found out using bool cache for memoization in this algorithm was useless.
Deleted 'curString' parameter from restore(). Since what we only need during recursive call is one previously selected partial string, 'last' can replace role of 'curString'.
CODE
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
vector<string> stringParts;
string cache[MAX + 1][(1 << MAX) + 1];
string restore(int selected = 0, int last = -1) {
if (selected == (1 << k) - 1) {
return stringParts[last];
}
if (last == -1) {
string ret = "";
for (int next = 0; next < k; next++) {
string resultStr = restore(selected + (1 << next), next);
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
string& ret = cache[last][selected];
if (!ret.empty()) {
cout << "cache used in [" << last << "][" << selected << "]" << endl;
return ret;
}
string curString = stringParts[last];
for (int next = 0; next < k; next++) {
if (selected & (1 << next)) continue;
string checkStr = restore(selected + (1 << next), next);
int check = false;
string resultStr;
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size() - i, i) == checkStr.substr(0, i)) {
resultStr = curString + checkStr.substr(i, checkStr.length() - i);
check = true;
break;
}
}
if (!check)
resultStr = curString + checkStr;
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
void EraseOverlapped() {
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
vector<string>::iterator iter;
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C;
for (int testCase = 0; testCase < C; testCase++) {
cin >> k;
for (int i = 0; i < MAX + 1; i++) {
for (int j = 0; j < (1 << MAX) + 1; j++)
cache[i][j] = "";
}
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
EraseOverlapped();
k = stringParts.size();
string resultStr = restore();
cout << resultStr << endl;
stringParts.clear();
}
}
This algorithm is much slower than the 'ideal' algorithm that the book I'm studying suggests, but it was fast enough to pass this question's time limit.
I need to insert symbol '+' into string after its each five symbol.
st - the member of class String of type string
int i = 1;
int original_size = st.size;
int count = 0;
int j;
for (j = 0; j < st.size; j++)
{
if (i % 5)
count++;
}
while (st.size < original_size + count)
{
if (i % 5)
{
st.insert(i + 1, 1, '+');
st.size++;
}
i++;
}
return st;
I got an error in this part of code. I think it is connected with conditions of of the while-cycle. Can you help me please how to do this right?
If I've understood you correctly then you want to insert a '+' character every 5 chars in the original string. One way to do this would be to create a temporary string and then reassign the original string:
std::string st("A test string with some chars");
std::string temp;
for (int i = 1; i <= st.size(); ++i)
{
temp += st[i - 1];
if (i % 5 == 0)
{
temp += '+';
}
}
st = temp;
You'll notice I've started the loop at 1, this is to avoid the '+' being inserted on the first iteration (0%5==0).
#AlexB's answer shows how to generate a new string with the resulting text.
That said, if your problem is to perform in-place insertions your code should look similar to this:
std::string st{ "abcdefghijk" };
for(auto i = 4; i != st.size(); i += 5)
st.insert(i+1, 1, '+'); // insert 1 character = '+' at position i
assert(st == "abcde+fghij+k");
std::string InsertEveryNSymbols(const std::string & st, size_t n, char c)
{
const size_t size(st.size());
std::string result;
result.reserve(size + size / n);
for (size_t i(0); i != size; ++i)
{
result.push_back(st[i]);
if (i % n == n - 1)
result.push_back(c);
}
return result;
}
You don't need a loop to calculate the length of the resulting string. It's going to be simply size + size / 5. And doing multiple inserts makes it a quadratic-complexity algorithm when you can just as easily keep it linear.
Nothing no one else has done, but eliminates the string resizing and the modulus and takes advantage of a few new and fun language features.
std::string temp(st.length() + st.length()/5, '\0');
// preallocate string to eliminate need for resizing.
auto loc = temp.begin(); // iterator for temp string
size_t count = 0;
for (char ch: st) // iterate through source string
{
*loc++ = ch;
if (--count == 0) // decrement and test for zero much faster than
// modulus and test for zero
{
*loc++ = '+';
count = 5; // even with this assignment
}
}
st = temp;
Given a string S.We need to tell if we can make it to palindrome by removing exactly one letter from it or not.
I have a O(N^2) approach by modifying Edit Distance method.Is their any better way ?
My Approach :
int ModifiedEditDistance(const string& a, const string& b, int k) {
int i, j, n = a.size();
int dp[MAX][MAX];
memset(dp, 0x3f, sizeof dp);
for (i = 0 ; i < n; i++)
dp[i][0] = dp[0][i] = i;
for (i = 1; i <= n; i++) {
int from = max(1, i-k), to = min(i+k, n);
for (j = from; j <= to; j++) {
if (a[i-1] == b[j-1]) // same character
dp[i][j] = dp[i-1][j-1];
// note that we don't allow letter substitutions
dp[i][j] = min(dp[i][j], 1 + dp[i][j-1]); // delete character j
dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]); // insert character i
}
}
return dp[n][n];
}
How to improve space complexity as max size of string can go upto 10^5.
Please help.
Example : Let String be abc then answer is "NO" and if string is "abbcbba then answer is "YES"
The key observation is that if the first and last characters are the same then you needn't remove either of them; which is to say that xSTRINGx can be turned into a palindrome by removing a single letter if and only if STRING can (as long as STRING is at least one character long).
You want to define a method (excuse the Java syntax--I'm not a C++ coder):
boolean canMakePalindrome(String s, int startIndex, int endIndex, int toRemove);
which determines whether the part of the string from startIndex to endIndex-1 can be made into a palindrome by removing toRemove characters.
When you consider canMakePalindrome(s, i, j, r), then you can define it in terms of smaller problems like this:
If j-i is 1 then return true; if it's 0 then return true if and only if r is 0. The point here is that a 1-character string is a palindrome regardless of whether you remove a character; a 0-length string is a palindrome, but can't be made into one by removing a character (because there aren't any to remove).
If s[i] and s[j-1] are the same, then it's the same answer as canMakePalindrome(s, i+1, j-1, r).
If they're different, then either s[i] or s[j-1] needs removing. If toRemove is zero, then return false, because you haven't got any characters left to remove. If toRemove is 1, then return true if either canMakePalindrome(s, i+1, j, 0) or canMakePalindrome(s, i, j-1, 0). This is because you're now testing whether it's already a palindrome if you remove one of those two characters.
Now this can be coded up pretty easily, I think.
If you wanted to allow for removal of more than one character, you'd use the same idea, but using dynamic programming. With only one character to remove, dynamic programming will reduce the constant factor, but won't reduce the asymptotic time complexity (linear in the length of the string).
Psudocode (Something like this I havn't tested it at all).
It is based on detecting the conditions that you CAN remove a character, ie
There is exactly 1 wrong character
It is a palendrome (0 mismatch)
O(n) in time, O(1) in space.
bool foo(const std::string& s)
{
int i = 0;
int j = s.size()-1;
int mismatch_count = 0;
while (i < j)
{
if (s[i]==s[j])
{
i++; j--;
}
else
{
mismatch_count++;
if (mismatch_count > 1) break;
//override first preference if cannot find match for next character
if (s[i+1] == s[j] && ((i+2 >= j-1)||s[i+2]==s[j-1]))
{
i++;
}
else if (s[j-1]==s[i])
{
j--;
}
else
{
mismatch_count++; break;
}
}
}
//can only be a palendrome if you remove a character if there is exactly one mismatch
//or if a palendrome
return (mismatch_count == 1) || (mismatch_count == 0);
}
Here's a (slightly incomplete) solution which takes O(n) time and O(1) space.
// returns index to remove to make a palindrome; string::npos if not possible
size_t willYouBeMyPal(const string& str)
{
size_t toRemove = string::npos;
size_t len = str.length();
for (size_t c1 = 0, c2 = len - 1; c1 < c2; ++c1, --c2) {
if (str[c1] != str[c2]) {
if (toRemove != string::npos) {
return string::npos;
}
bool canRemove1 = str[c1 + 1] == str[c2];
bool canRemove2 = str[c1] == str[c2 - 1];
if (canRemove1 && canRemove2) {
abort(); // TODO: handle the case where both conditions are true
} else if (canRemove1) {
toRemove = c1++;
} else if (canRemove2) {
toRemove = c2--;
} else {
return string::npos;
}
}
}
// if str is a palindrome already, remove the middle char and it still is
if (toRemove == string::npos) {
toRemove = len / 2;
}
return toRemove;
}
Left as an exercise is what to do if you get this:
abxyxcxyba
The correct solution is:
ab_yxcxyba
But you might be led down a bad path:
abxyxcx_ba
So when you find the "next" character on both sides is a possible solution, you need to evaluate both possibilities.
I wrote a sample with O(n) complexity that works for the tests I threw at it. Not many though :D
The idea behind it is to ignore the first and last letters if they are the same, deleting one of them if they are not, and reasoning what happens when the string is small enough. The same result could be archived with a loop instead of the recursion, which would save some space (making it O(1)), but it's harder to understand and more error prone IMO.
bool palindrome_by_1(const string& word, int start, int end, bool removed = false) // Start includes, end excludes
{
if (end - start == 2){
if (!removed)
return true;
return word[start] == word[end - 1];
}
if (end - start == 1)
return true;
if (word[start] == word[end - 1])
return palindrome_by_1(word, start + 1, end - 1, removed);
// After this point we need to remove a letter
if (removed)
return false;
// When two letters don't match, try to eliminate one of them
return palindrome_by_1(word, start + 1, end, true) || palindrome_by_1(word, start, end - 1, true);
}
Checking if a single string is palindrome is O(n). You can implement a similar algorithm than moves two pointers, one from the start and another from the end. Move each pointer as long as the chars are the same, and on the first mismatch try to match which char you can skip, and keep moving both pointers as long as the rest chars are the same. Keep track of the first mismatch. This is O(n).
I hope my algorithm will pass without providing code.
If a word a1a2....an can be made a palindrome by removing ak, we can search for k as following:
If a1 != an, then the only possible k would be 1 or n. Just check if a1a2....an-1 or a2a3....an is a palindrome.
If a1 == an, next step is solving the same problem for a2....an-1. So we have a recursion here.
public static boolean pal(String s,int start,int end){
if(end-start==1||end==start)
return true;
if(s.charAt(start)==s.charAt(end))
return pal(s.substring(start+1, end),0,end-2);
else{
StringBuilder sb=new StringBuilder(s);
sb.deleteCharAt(start);
String x=new String(sb);
if(x.equals(sb.reverse().toString()))
return true;
StringBuilder sb2=new StringBuilder(s);
sb2.deleteCharAt(end);
String x2=new String(sb2);
if(x2.equals(sb2.reverse().toString()))
return true;
}
return false;
}
I tried the following,f and b are the indices at which characters do not match
int canwemakepal(char *str)//str input string
{
long int f,b,len,i,j;
int retval=0;
len=strlen(str);
f=0;b=len-1;
while(str[f]==str[b] && f<b)//continue matching till we dont get a mismatch
{
f++;b--;
}
if(f>=b)//if the index variable cross over each other, str is palindrome,answer is yes
{
retval=1;//true
}
else if(str[f+1]==str[b])//we get a mismatch,so check if removing character at str[f] will give us a palindrome
{
i=f+2;j=b-1;
while(str[i]==str[j] && i<j)
{
i++;j--;
}
if(i>=j)
retval=1;
else
retval=0;
}
else if(str[f]==str[b-1])//else check the same for str[b]
{
i=f+1;j=b-2;
while(str[i]==str[j] && i<j)
{
i++;j--;
}
if(i>=j)
retval=1;
else
retval=0;
}
else
retval=0;
return retval;
}
I created this solution,i tried with various input giving correct result,still not accepted as correct solution,Check it n let me know if m doing anything wrong!! Thanks in advance.
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int t = s.nextInt();
String result[] = new String[t];
short i = 0;
while(i < t)
{
String str1 = s.next();
int length = str1.length();
String str2 = reverseString(str1);
if(str1.equals(str2))
{
result[i] = "Yes";
}
else
{
if(length == 2)
{
result[i] = "Yes";
}
else
{
int x = 0,y = length-1;
int counter = 0;
while(x<y)
{
if(str1.charAt(x) == str1.charAt(y))
{
x++;
y--;
}
else
{
counter ++;
if(str1.charAt(x) == str1.charAt(y-1))
{
y--;
}
else if(str1.charAt(x+1) == str1.charAt(y))
{
x++;
}
else
{
counter ++;
break;
}
}
}
if(counter >= 2)
{
result[i] = "No";
}
else
result[i]="Yes";
}
}
i++;
} // Loop over
for(int j=0; j<i;j++)
{
System.out.println(result[j]);
}
}
public static String reverseString(String original)
{
int length = original.length();
String reverse = "";
for ( int i = length - 1 ; i >= 0 ; i-- )
reverse = reverse + original.charAt(i);
return reverse;
}
I have a C++ function that splits a char array into multiple char arrays when it encounters a delimiter. For some reason, when saving the third split array the program just crashes and sometimes returns an std::bad_alloc exception.
char ** explode(const char * arr, const char delim) {
int start, end, curr=0, count=1;
char ** strings;
//Iegūst explodēto stringu skaitu
for (int i = 0; arr[i] != 0; i++) {
if (arr[i] == delim && i != 0 && arr[i+1] != 0 && arr[i+1] != delim ) { //Nav pirmais, nav pēdējais, nav pa labi vēlviens delimiters
count++;
}
}
strings = new char*[count];
start = 0;
for (int i = 0; arr[i] != 0; i++) {
if (arr[i] == delim || arr[i+1] == 0) {
if (arr[i] == delim) {
end = i;
} else {
end = i+1;
}
if (end-start < 1) {
start++;
} else {
copystring(arr,strings[curr++],start,end-start);
start = i+1;
}
}
}
for (int i = 0; i < count; i++) {
cout << strings[i] << endl;
}
return strings;
}
//Pārkopē daļu no pirmā char masīva uz otru, no START pozīcijas, līdz GARUMS garumā
void copystring(const char * from, char *& to, const int start, const int garums) {
int curr=0;
if (garums < 1 || start > charlen(from)) {
return;
}
to = new char[garums];
for (int i = start; i < start+garums && from[i] != 0; i++) {
to[curr++] = from[i];
}
to[curr] = 0;
}
It's hard to tell because it doesn't really tell me at which line everything goes wrong, but I think it happens at
to = new char[garums];
I've tried debugging this line within CodeBlocks, but for some reason when using breakpoints and tracking the variables the applications works fine and executes correctly. It only crashes when running it normally, without debugging...
Also note, that I can't use strings or pretty much any library except fstream and iostream.
EDIT: I tried changing the new char[garums] part to new char[100] and it magically started working. The problem is that I then changed it to new char[10] in which case everything still worked. I even outputted the saved text to the console and it saved everything properly. How could it have saved big words in a char array that is 10 character long (the words I'm testing are longer than 10 characters)? When I changed it to new char[1] however it started crashing again, but again only after the 3rd loop iteration. So it somehow saved the first 2 words in a 1 character long array?
EDIT2: And now it magically started working even with new char[garums]. Something is really wrong here, anyone have any ideas?
The bug you refer to in your question likely crops up when trying to use the pointer
to pointer being returned from the explode function.
Some pointers ; If you have to write C code, don't use a mishmash of C/C++,
Use the library functions rather than re-inventing the wheel (strncpy in copystring)
Your word count was off because you didn't take into account the word between
the last delimiter and EOL
Below are some minor changes to your code as a complete example :
#include <stdio.h>
#include <strings.h>
void copystring(const char *from, char **to, const int numchars)
{
if (numchars > 0) {
*to = new char[numchars];
strncpy(*to, from, numchars) ;
(*to)[numchars] = '\0' ;
}
}
char **explode(const char * buffer, const char delim)
{
int count = 0 ;
if (strlen(buffer) > 0) {
int inword = 0 ;
int idx = 0 ;
do {
if (buffer[idx] == delim || buffer[idx] == '\0') {
if (inword == 1) {
count++ ;
inword = 0 ;
}
} else {
inword = 1 ;
}
} while (buffer[idx++] != 0) ;
}
int start = 0;
int end = 0 ;
int curr = 0 ;
int idx = 0 ;
char **values = new char*[count+1];
do {
if (buffer[idx] == delim || buffer[idx] == '\0') {
end = idx;
if (end-start > 0) {
copystring(&buffer[start], &values[curr++], end - start) ;
}
start = ++end ;
}
} while (buffer[idx++] != 0) ;
values[curr] = NULL ;
for (int idx = 0; idx < count; idx++) {
fprintf(stdout, "'%s'\n", values[idx]) ;
}
return values;
}
int main(int argc, char *argv[])
{
char inputstr[] = "The, quick, brown, fox, jumped, over,,, ,,, ,,,,, ,,,, the, lazy, dog's, back" ;
char **values = explode(inputstr, ',') ;
while (*values != NULL) {
fprintf(stdout, "%s\n" , *values) ;
*values++ ;
}
return (0) ;
}
Since I don't know what input data you have I will have to guess:
Here you allocate your pointer array but please note that all the pointers are uninitialized.
strings = new char*[count]
then when you parse the code you use a variable curr which you let run freely so it is not certain that all strings[] have been set to some value or whether curr lands on a number larger than count.
If I were you I would put in a check to make sure that:
a) curr does not exceed count
b) that if curr lands on a value less than count, set the rest of the pointers to nullptr
This has probably to do with to being of type char*& instead of type char*.
On the other hand, I never programmed C++ like this (are you sure that this is not C?). Using explicit memory management (like ´new´) is as good as playing playing russian roulette.
Here is a more standard C++ way of doing this:
#include <vector>
#include <string>
#include <iostream>
std::vector<std::string> splitString(std::string& str, char c) {
std::vector<std::string> substrings;
while(true) {
unsigned pos = str.find(c);
substrings.push_back(str.substr(0,pos));
if(pos == std::string::npos) break;
str = str.substr(pos+1);
}
return substrings;
}
int main()
{
char c = '*';
std::string str = "Some*string*that we need to split*properly*";
std::vector<std::string> result = splitString(str,c);
for(unsigned i = 0; i < result.size(); ++i) {
std::cout << i << ": " << result[i] << "\n";
}
}
Output:
0: Some
1: string
2: that we need to split
3: properly
4:
Hi everyone I'm working on a function to manipulating any string in this following manner.
"abc" -> "cab"
"abcd" -> "dacb"
"abcdef" -> "faebdc"
"divergenta" -> "adtinveerg"
... and so on.
This is the code I've come up with so far. I think it does the job but I think the code and solution is kind of ugly and I'm not sure if it's fail proof and if it is working properly for every given case. I would highly appreciate any input on this code or any examples on how you would write this function. I beg you to bear in mind that I'm very much a n00b so don't go too hard on me.
string transformer(string input) {
string temp;
int n = 0;
int m = (input.length() -1);
for( int i = 0; i < input.length(); i++) {
temp += input[m];
if (input[m] == input[n]) {
break;
}
else {
temp += input[n];
}
n += 1;
m -= 1;
if ( temp.length() == input.length() ) {
break;
}
}
return temp; }
You have three problems.
Try it with "abbba". If the result isn't what you want, then this conditional:
if (input[m] == input[n]) {
break;
}
is just plain wrong.
Look at the other conditional:
if ( temp.length() == input.length() ) {
break;
}
You're adding two characters at a time to temp. What if input has odd length?
Suppose that works correctly. Consider the loop:
for( int i = 0; i < input.length(); i++) {
...
if ( temp.length() == input.length() ) {
break;
}
}
That loop will never terminate in the for statement. You might as well do it this way:
while( temp.length() < input.length() ) {
...
}
Once that's all working correctly, you should look into iterators.
This function just walks two indices toward the center until they meet or pass each other. The last if block handles the case of an odd length input string. It works for all your test cases on ideone.com
std::string transformer(const std::string& input)
{
std::string temp;
int i = 0;
int j = input.length() - 1;
while (i < j) {
temp += input[j--];
temp += input[i++];
}
if (i == j) {
temp += input[i];
}
return temp;
}
std::string transformer(const std::string& input) {
std::string res(input.length(), '0');
for (int i = 0; i < input.length(); ++i) {
res[i] = input[ i % 2 == 0 ? input.length() - (i/2) - 1 : (i/2) ];
}
return res;
}
Unfortunately if (input[m] == input[n]) will make sure that if the first and last characters are the same, it immediately quits after the first character is processed.
I'd do this with std::string::iterator and std::string::reverse_iterator:
auto it = input.begin();
auto rit = input.rbegin();
std::string temp;
for (size_t i = 0; i < input.length()/2; ++i) {
temp += *rit++;
temp += *it++;
}
The logic for handling empty and odd-length input is left for you to do, shouldn't be too hard. (Input of length 1 is also a special case)
I would use pointers instead of indexes to do this.
So you have a pointer the reading the edges and you keep swapping them with each iteration.
It will also make it faster.
I think this should work, but I can't remember how to make an array of const char pointers. Can anyone help me with that step?
string transformer(string input) {
std::string temp;
const char *front, *back;
for (*front = input.c_str(), *back = front + input.length() - 1; front < back ; front++, back--) {
temp += *back;
temp += *front;
}
if (front == back)
temp += *front;
return temp;
}
(using the same method as #Blastfurnace, but skipping unnecessary indexes.)