Insert symbol into string C++ - c++

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;

Related

Smallest Binary String not Contained in Another String

The question description is relatively simple, an example is given
input: 10100011
output: 110
I have tried using BFS but I don't think this is an efficient enough solution (maybe some sort of bitmap + sliding window solution?)
string IntToString(int a)
{
ostringstream temp;
temp << a;
return temp.str();
}
bool is_subsequence(string& s, string& sub) {
if(sub.length() > s.length()) return false;
int pos = 0;
for(char c : sub)
{
pos = s.find(c, pos);
if(pos == string::npos) return false;
++pos;
}
return true;
}
string shortestNotSubsequence(string& s) {
Queue q(16777216);
q.push(0);
q.push(1);
while(!q.empty())
{
string str;
int num = q.front; q.pop();
str = IntToString(num);
if(!is_subsequence(s, str)) return str;
string z = str + '0';
string o = str + '1';
q.push(stoi(str+'0'));
q.push(stoi(str+'1'));
}
return "";
}
int main() {
string N;
cin >> N;
cout << shortestNotSubsequence(N) << endl;
return 0;
}
You can do this pretty easily in O(N) time.
Let W = ceiling(log2(N+1)), where N is the length of the input string S.
There are 2W possible strings of length W. S must have less than N of them as substrings, and that's less than 2W, so at least one string of length W must not be present in S.
W is also less than the number of bits in a size_t, and it only takes O(N) space to store a mask of all possible strings of length W. Initialize such a mask to 0s, and then iterate through S using the lowest W bits in a size_t as a sliding window of the substrings you encounter. Set the mask bit for each substring you encounter to 1.
When you're done, scan the mask to find the first 0, and that will be a string of length W that's missing.
There may also be shorter missing strings, though, so merge the mask bits in pairs to make a mask for the strings of length W-1, and then also set the mask bit for the last W-1 bits in S, since those might not be included in any W-length string. Then scan the mask for 0s to see if you can find a shorter missing string.
As long as you keep finding shorter strings, keep merging the mask for smaller strings until you get to length 1. Since each such operation divides the mask size in 2, that doesn't affect the overall O(N) time for the whole algorithm.
Here's an implementation in C++
#include <string>
#include <vector>
#include <algorithm>
std::string shortestMissingBinaryString(const std::string instr) {
const size_t len = instr.size();
if (len < 2) {
if (!len || instr[0] != '0') {
return std::string("0");
}
return std::string("1");
}
// Find a string size guaranteed to be missing
size_t W_mask = 0x3;
unsigned W = 2;
while(W_mask < len) {
W_mask |= W_mask<<1;
W+=1;
}
// Make a mask of all the W-length substrings that are present
std::vector<bool> mask(W_mask+1, false);
size_t lastSubstr=0;
for (size_t i=0; i<len; ++i) {
lastSubstr = (lastSubstr<<1) & W_mask;
if (instr[i] != '0') {
lastSubstr |= 1;
}
if (i+1 >= W) {
mask[lastSubstr] = true;
}
}
//Find missing substring of length W
size_t found = std::find(mask.begin(), mask.end(), false) - mask.begin();
// try to find a shorter missing substring
while(W > 1) {
unsigned testW = W - 1;
W_mask >>= 1;
// calculate masks for length testW
for (size_t i=0; i<=W_mask; i++) {
mask[i] = mask[i*2] || mask[i*2+1];
}
mask.resize(W_mask+1);
// don't forget the missing substring at the end
mask[lastSubstr & W_mask] = true;
size_t newFound = std::find(mask.begin(), mask.end(), false) - mask.begin();
if (newFound > W_mask) {
// no shorter string
break;
}
W = testW;
found = newFound;
}
// build the output string
std::string ret;
for (size_t bit = ((size_t)1) << (W-1); bit; bit>>=1) {
ret.push_back((found & bit) ? '1': '0');
}
return ret;
}

Function to shift array elements not working

I have a null terminated array of chars. Also known as a c-string. I have written a function that will shift the elements at each index left, <---- by a given number of indexes. For example, when the char array of "hello world" is passed to the function, with a shiftBy value of 3, it should transform the char array to be: "lo worldhel".
Currently, this function works for all strings that <= 11 elelements. Anything over that and the last three spots in the array don't get shifted. Keep in mind, the very last index is holding the null terminator!
This is a tricky one and I have been stuck for hours. I also can't use any standard functions or vectors, I am stuck with these deprecated arrays and simple loops. So please don't troll with "Why don;t you use blank function"....because trust me, if I could I wouldn't be here.
Here is the code, have at at:
void shiftLeft (char szString[], int size, int shiftBy)
{
if(shiftBy > size){
shiftBy = shiftBy - size;
}
if(size == 1){
//do nothing, do nothing, exit function with no change made to myarray
}
else{
char temp;
//for loop to print the array with indexes moved up (to the left) <-- by 2
for (int i = 0; i <= size-shiftBy; i++)//size = 11
{//EXAMPLE shift by 3 for a c-string of `hello world`
if(i < size-shiftBy){
temp = szString[shiftBy + i];//temp = h
szString[shiftBy + i] = szString[i];//d becomes l
szString[i] = temp;//h becomes l
}
else{//it will run once while i=8
temp = szString[i];//temp = l
szString[i] = szString[i+1];//8th element becomes h
szString[i+1] = szString[size-1];//9th element becomes e
szString[size-1] = temp;//last element becomes l
}
}
}
}
If the only purpose you're trying to accomplish is shifting chars in a terminated string left with rotation (and judging by your sample of "helloworld" resulting in "loworldhel" after a 3-shift, that seems to be the case), you're making this much harder than it needs to be.
The traditional algorithm to do this in O(N) time with no temporary space requirements is to reverse the left-side of the shift, then the entire sequence, then the right side of the shift, all based from the beginning of the sequence. For example, suppose we want to left-shift the following string 3 slots:
1234567890
First, reverse the first shiftBy slots
1234567890
^-^
3214567890
Second, reverse the entire sequence
3214567890
^--------^
0987654123
Finally, reverse the (length-shiftBy) slots:
0987654123
^-----^
4567890123
Using the standard library would make this trivial, but apparently you're prof considers that... cheating. Without using any library apis the above algorithm isn't very hard regardless:
#include <iostream>
void shiftLeft(char sz[], size_t shiftBy)
{
const char *p = sz;
while (*p) ++p;
std::size_t len = p - sz;
if (len > 1 && (shiftBy %= len))
{
char *ends[] = { sz+shiftBy, sz+len, sz+(len - shiftBy) };
for (std::size_t i=0; i<3; ++i)
{
char *start = sz, *end = ends[i];
while (start < --end)
{
char ch = *start;
*start++ = *end;
*end = ch;
}
}
}
}
int main()
{
char sz[] = "1234567890";
std::cout << sz << '\n';
shiftLeft(sz, 11);
std::cout << sz << '\n';
shiftLeft(sz, 4);
std::cout << sz << '\n';
shiftLeft(sz, 1);
std::cout << sz << '\n';
shiftLeft(sz, 20);
std::cout << sz << '\n';
}
Output
1234567890
2345678901
6789012345
7890123456
7890123456
If you're really set on doing this in temp space, so be it, but I cannot possibly fathom why you would do so.
Best of luck.
From azillionmonkeys.com/qed/case8.html
void shiftLeft(char szString[], int size, int shiftBy) {
int c, tmp, v;
if (size <= 0) return;
if (shiftBy < 0 || shiftBy >= size) {
shiftBy %= size;
if (shiftBy < 0) shiftBy += size;
}
if (shiftBy == 0) return;
c = 0;
for (v = 0; c < size; v++) {
int t = v, tp = v + shiftBy;
char tmp = szString[v];
c++;
while (tp != v) {
szString[t] = szString[tp];
t = tp;
tp += shiftBy;
if (tp >= size) tp -= size;
c++;
}
szString[t] = tmp;
}
}

C++ Split String Every X Characters

I am trying to write a function that takes a string, and splits every X number of characters:
std::vector<std::string> DIFSplitStringByNumber(std::string s, int l)
{
const char *c = s.c_str();
char buffer[l];
std::vector<std::string> entries;
entries.reserve(int(s.length() / l) + 1);
int d = 0;
for(int i = 0; i < s.length() - 1;)
{
if(d != l)
{
buffer[d] = c[i];
d++;
i++;
}
else
{
entries.push_back(std::string(buffer, l));
//Clear array
memset(buffer, 0, l);
d = 0;
}
}
return entries;
}
For example, If I called DIFSplitStringByNumber("hello!", 2), I should get a vector containing:
[0] he
[1] ll
[2] o!
However, it only seems to get the first two results (the vector size is 2), and when I do something like DIFSplitStringByNumber("hello", 2), it crashes, presumably because its trying to access an array index that doesn't exist (it expects 6 characters, but there are only 5). Is there a simpler way to do this?
The heart of the algorithm really comes down to the following two lines.
for (size_t i = 0; i < s.size(); i += l)
res.push_back(s.substr(i, l));
Also, you should pass the string by const reference.
This will split a string into a vector. If there aren't an even number of splits, it will add the extra characters to the end.
std::vector<std::string> Split(const std::string& str, int splitLength)
{
int NumSubstrings = str.length() / splitLength;
std::vector<std::string> ret;
for (auto i = 0; i < NumSubstrings; i++)
{
ret.push_back(str.substr(i * splitLength, splitLength));
}
// If there are leftover characters, create a shorter item at the end.
if (str.length() % splitLength != 0)
{
ret.push_back(str.substr(splitLength * NumSubstrings));
}
return ret;
}
Using that std::string is a collection of char, a simple implementation could be :
std::vector<std::string> DIFSplitStringByNumber(const std::string & str, int len)
{
std::vector<std::string> entries;
for(std::string::const_iterator it(str.begin()); it != str.end();)
{
int nbChar = std::min(len,(int)std::distance(it,str.end()));
entries.push_back(std::string(it,it+nbChar));
it=it+nbChar;
};
return entries;
}
Live sample
Change the way that you are calculating the vector size:
int size = (s.length() - 1) / l + 1;
This is equivalent to the ceiling of the input string length divided by the input length.
BTW, the int(s.length() / l) casting is useless, since both operands are integers.
Finally, use this size inside the loop:
for (int i=0; i<size; i++)

Function to manipulate a string ("abcdef" -> "faebdc")

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

remove commas from string

I created a program in C++ that remove commas (,) from a given integer. i.e. 2,00,00 would return 20000. I am not using any new space. Here is the program I created:
void removeCommas(string& str1, int len)
{
int j = 0;
for (int i = 0; i < len; i++)
{
if (str1[i] == ',')
{
continue;
}
else
{
str1[j] = str1[i];
j++;
}
}
str1[j] = '\0';
}
void main()
{
string str1;
getline(cin, str1);
int i = str1.length();
removeCommas(str1, i);
cout << "the new string " << str1 << endl;
}
Here is the result I get:
Input : 2,000,00
String length =8
Output = 200000 0
Length = 8
My question is that why does it show the length has 8 in output and shows the rest of string when I did put a null character. It should show output as 200000 and length has 6.
Let the standard library do the work for you:
#include <algorithm>
str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end());
If you don't want to modify the original string, that's easy too:
std::string str2(str1.size(), '0');
str2.erase(std::remove_copy(str1.begin(), str1.end(), str2.begin(), ','), str2.end());
You need to do a resize instead at the end.
Contrary to popular belief an std::string CAN contain binary data including 0s. An std::string 's .size() is not related to the string containing a NULL termination.
std::string s("\0\0", 2);
assert(s.size() == 2);
The answer is probably that std::strings aren't NUL-terminated. Instead of setting the end+1'th character to '\0', you should use str.resize(new_length);.
Edit: Also consider that, if your source string has no commas in it, then your '\0' will be written one past the end of the string (which will probably just happen to work, but is incorrect).
The std::srting does not terminate with \0, you are mixing this with char* in C. So you should use resize.
The solution has already been posted by Fred L.
In a "procedural fashion" (without "algorithm")
your program would look like:
void removeStuff(string& str, char character)
{
size_t pos;
while( (pos=str.find(character)) != string::npos )
str.erase(pos, 1);
}
void main()
{
string str1;
getline(cin, str1);
removeStuff(str1, ',');
cout<<"the new string "<<str1<<endl;
}
then.
Regards
rbo
EDIT / Addendum:
In order to adress some efficiency concerns of readers,
I tried to come up with the fastest solution possible.
Of course, this should kick in on string sizes over
about 10^5 characters with some characters to-be-removed
included:
void fastRemoveStuff(string& str, char character)
{
size_t len = str.length();
char *t, *buffer = new char[len];
const char *p, *q;
t = buffer, p = q = str.data();
while( p=(const char*)memchr(q, character, len-(p-q)) ) {
memcpy(t, q, p-q);
t += p-q, q = p+1;
}
if( q-str.data() != len ) {
size_t tail = len - (q-str.data());
memcpy(t, q, tail);
t += tail;
}
str.assign(buffer, t-buffer);
delete [] buffer;
}
void main()
{
string str1 = "56,4,44,55,5,55"; // should be large, 10^6 is good
// getline(cin, str1);
cout<<"the old string " << str1 << endl;
fastRemoveStuff(str1, ',');
cout<<"the new string " << str1 << endl;
}
My own procedural version:
#include <string>
#include <cassert>
using namespace std;
string Remove( const string & s, char c ) {
string r;
r.reserve( s.size() );
for ( unsigned int i = 0; i < s.size(); i++ ) {
if ( s[i] != c ) {
r += s[i];
}
}
return r;
}
int main() {
assert( Remove( "Foo,Bar,Zod", ',' ) == "FooBarZod" );
}
Here is the program:
void main()
{
int i ;
char n[20] ;
clrscr() ;
printf("Enter a number. ") ;
gets(n) ;
printf("Number without comma is:") ;
for(i=0 ; n[i]!='\0' ; i++)
if(n[i] != ',')
putchar(n[i]) ;
getch();
}
For detailed description you can refer this blog: http://tutorialsschool.com/c-programming/c-programs/remove-comma-from-string.php
The same has been discussed in this post: How to remove commas from a string in C
Well, if youre planing to read from a file using c++. I found a method, while I dont think thats the best method though, but after I came to these forums to search for help before, I think its time to contribute with my effort aswell.
Look, here is the catch, what I'm going to present you is part of the source code of the map editor Im building on right now, that map editor obviously has the purpose to create maps for a 2D RPG game, the same style as the classic Pokemon games for example. But this code was more towards the development of the world map editor.
`int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {`
Here we need to define the size of the string we want to extract after the previous comma and before the next comma
`strSize = strIterator - strStartPos;`
And here, we do the actual transformation, we give to the vector that is a 3D vector btw the string we want to extract at that moment
`m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);`
And here, we just define that starting position for the next small piece of the string we want to extract, so the +1 means that after the comma we just passed
strStartPos = strIterator + 1;
Here, well since my vector has only 6 postions that is defined by WorldMapPointInfos we need to increment the third dimension of the array and finally do a check point where if the info has arrived the number 6 then break the loop
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}
Either way on my code, think abt that the vector is just a string, thats all you need to know, hope this helps though :/
Full view:
int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {
strSize = strIterator - strStartPos;
m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);
strStartPos = strIterator + 1;
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}