How to modify string to char array in C/C++? - c++

i'm writing a program called 'Zuma'. The program works like this.
Input:
ACCBA // a string make up of char from 'A' to 'Z'
5 // number of inputs
1 B // insert char 'B' to position '1' of the string
0 A // and so on...
2 B
4 C
0 A
When 3 same chars next to each other, we erase/remove/delete them from the string.
For example, when we insert char 'C' to position 2 of string 'ABCC', we got 'AB' because
'CCC' are removed from the string.
Output:
ABCCBA
AABCCBA
AABBCCBA // the process is AABBCCCBA -> AABBBA -> AAA -> -
- // if the string is empty, we output "-"
A
This is my code with string:
#include <iostream>
using namespace std;
int main()
{
int n, pos;
int k = 0;
int length = 0;
string zuma, marble; // i use string
cin >> zuma;
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> pos >> marble;
zuma.insert(pos, marble);
length = zuma.length(); // length of current string
// compare each char from pos[i] with pos[i+1] and pos[i+2]
// and then ++i until end of string
while (k != length && length >= 3)
{
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
zuma.erase(k, 3); // erase 3 same char in the string
k = 0; // set k to zero to start from pos[0] again
}
else
k++;
}
// if string is not empty
if (!zuma.empty())
{
cout << zuma << endl; // output the current char in the string
k = 0;
}
else
cout << "-" << endl;
}
return 0;
}
This is my code with char array:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
void append (char subject[], const char insert[], int pos) {
char buf[100] = {};
strncpy(buf, subject, pos);
int len = strlen(buf);
strcpy(buf+len, insert);
len += strlen(insert);
strcpy(buf+len, subject+pos);
strcpy(subject, buf);
}
int main()
{
int n, pos;
int k = 0;
int length = 0;
char zuma[100], marble[100];
scanf("%s", zuma);
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%d %s", &pos, marble);
append(zuma, marble, pos); // acts like string::insert
length = strlen(zuma);
while (k != length && length >= 3)
{
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
//zuma.erase(k, 3); // need help with this part to remove 3 same chars like string::erase
k = 0;
}
else
k++;
}
if (strlen(zuma) != 0)
{
printf("%s\n", zuma);
k = 0;
}
else
printf("%s\n","-");
}
return 0;
}
My problem is how to write a function to remove 3 same chars just like what string::erase do?
Thanks for your help!!

You can use memmove to copy the remainder of the string to the position of the characters to remove. Use strlen to determine how much bytes to move. Note you cannot use strcpy because the source and destination buffers overlap.
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
int len = strlen(zuma+k+3) + 1; // +1 to copy '\0' too
memmove(zuma+k, zuma+k+3, len);
k = 0;
}

Related

Recursive program to insert a star between pair of identical characters

void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
what is the mistake in this code. I couldn't find out.
if I entered aaaa, abaa etc. it runs perfect.
but when i entered scatter is shows scat*ter?#
so what is the perfect solution ?
input string is aaaa . so output is a*a*a*a instead of a*aa*a.
You do not copy terminating character \0!
So when you have inserted a character termination of string is undefined.
Note also that proper answer for aaaa should be a*a*a*a (or a*aa*a depending on problem definition).
Split argument to define soruce and destination and use separate buffers.
void copyAddStarToPairs(const char *src, char *dst)
{
*dst = *src;
if (!*dst) return;
dst++;
char prev = *src++;
if (prev = *src) *dst++ = '*';
copyAddStarToPairs(src, dst);
}
May be you should use std::string as your char buffer may not be long enough.
#include <string>
using std::string;
void pairStar(string & s, int st) {
if (st >= (int)s.size() - 1)
return;
else if (s[st] == s[st + 1]) {
s += ' ';
for (int i = (int)s.size() - 1; i > st + 1; i--)
s[i] = s[i - 1];
s[st + 1] = '*';
st++;
}
pairStar(s, st + 1);
}
int main() {
string s = "aadqwedabbbbb*dqwdasd";
pairStar(s, 0);
cout << s << endl;
}
Add the line input[len+1]='\0'; after the lineinput[1]='*';.
What happens actually is that once you append '*',you aren't appending the '\0' character. This line will append it to the end that means string end here for the first call that you made. So recursive function will also do the same, it will add '\0' character at the end letting know that string ends here.
Consider an example:
aa is a string of length 2 and and after adding star the length of string will become 3 so input[len+1] will be input[2+1]=input[3].
So character next to the moved character will be '\0' character everytime.
PS: this is my first time adding an answer on stackoverflow...
I offer to solve this problem, using the algorithm Depth first search.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int maximumSize=40;
string symbols="aadqwedabbbbb*dqwdasd";
string symbolsNew;
vector<int> visited(maximumSize, 0);
template<class Type>
void showContent(Type input)
{
for(int index=0; index<input.size(); ++index)
{
cout<<input[index];
}
return;
}
void depthFirstSearch(int current, int previous)
{
if(visited[current]==1)
{
return;
}
visited[current]=1;
symbolsNew.push_back(symbols[current]);
int interactions=0;
for(int next=(current+1); next<symbols.size(); ++next)
{
if(interactions!=0)
{
break;
}
if(symbols[current]==symbols[next])
{
symbolsNew.push_back('*');
}
++interactions;
}
for(int next=current; next<symbols.size(); ++next)
{
depthFirstSearch(next, current);
}
return;
}
void solve()
{
depthFirstSearch(0, -1);
cout<<"symbols <- ";
showContent(symbols);
cout<<endl<<"symbolsNew <- ";
showContent(symbolsNew);
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
symbols <- aadqwedabbbbb*dqwdasd
symbolsNew <- a*adqwedab*b*b*b*b*dqwdasd
void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len+1; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
void helper(char input[], int start)
{
if (input[start] == '\0')
{
return;
}
helper(input, start + 1);
if (input[start] == input[start + 1])
{
for (int i = strlen(input); i >= start + 1; i--)
{
input[i + 1] = input[i];
}
input[start + 1] = '*';
}
}
void pairStar(char input[])
{
helper(input, 0);
}

Splitting char array into other arrays for using it later and ignoring numbers c++

So I have this assignment where you have to reposition letters in a char array by given number of repositions. The last letter must become first. For example:
Input: Hello 3
Output: lloHe
But if you have a sentence, you have to do it for each word seperately and, what is more, if there are numbers, you must ignore them. So I have trouble dealing with the check for numbers and dealing with seperate words(I use strtok to split them). This is what I have so far:
#include <iostream>
#include <cstring>
using namespace std;
void Reposition(char text[10000], int n, char result[10000])
{
int startIndex = strlen(text)-1;
int k = n-1;
int currentIndex = 0;
for(int i = 0; i < n; i++)
{
result[k] = text[startIndex];
k--;
startIndex--;
currentIndex++;
}
for(int i = 0; i <= startIndex; i++)
{
result[currentIndex] = text[i];
currentIndex++;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char *words;
words = strtok(text, " .,");
while(words != NULL)
{
Reposition(text, n, result);
words = strtok(NULL, " .,");
}
for(unsigned i = 0; i <= strlen(result); i++)
cout << result[i];
return 0;
}
Use std::string instead of C-style string
To remove numbers from a string, use std::remove_if from <algorithm>:
std::string s;
. . .
s.erase(std::remove_if(s.begin(), s.end(), ::isdigit), s.end());
To reposition characters in a string, use std::rotate:
std::rotate(s.begin(), s.begin() + 1, s.end());
I did your homework.
Don't know if you are familiar with all this code.
I Also rewrote your reposition code. It looked very messy.....
One time favour from me. Try to learn something from this.
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
void Reposition(char * text, int len, int n, char * result)
{
int k = n - 1;
for(int i = 0; i < len; i++)
{
result[i] = text[k++];
if(k == len) k = 0;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char * word;
char * beginOfWord = text;
char * resultPointer = result;
int wordLen;
while(* beginOfWord)
{
// copy up to somthing from the alphabet
if(!isalpha(* beginOfWord))
{
*resultPointer++ = * beginOfWord++;
continue;
}
// Find the end of this word
word = strpbrk(beginOfWord, " .,0123456789");
if(word != NULL)
{
// len is distance between end of word and begin of word
wordLen = word - beginOfWord;
}
else
{
// Maybe it is the end of the string
wordLen = strlen(beginOfWord);
}
//reposition the word
Reposition(beginOfWord, wordLen, n, resultPointer);
// Move the pointers beyond the word
beginOfWord += wordLen;
resultPointer += wordLen;
}
//Always terminate
*resultPointer ='\x0';
cout << result;
return 0;
}
//reverse will reverse the string starting at position xn and ending at position (yn-1)
void reverse(char *str, int xn, int yn)
{
//positioning the pointers appropriately
char *start = str + xn;
char *end = str + yn - 1;
char temp;
while(start < end)
{
temp = *start;
*start = *end;
*end = temp;
++start;
--end;
}
}
//one of the logic to reposition
void reposition(char *str, int n)
{
int length = strlen(str);
n = (length > n) ? n : (n % length);
reverse(str, 0, n);
reverse(str, n, length);
reverse(str, 0, length);
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
strcpy(result, text);
cout << "before: " << result << endl;
char *word;
word = strtok(text, " .,");
while(word != NULL)
{
//check if it is not a number
if(isdigit(word[0]) == 0)
{
reposition(word, n);
//find the word postion in text
int word_position = word - text;
//copy the repositioned word in result at its corresponding position.
int i = 0;
while(word[i])
{
result[word_position + i] = word[i];
++i;
}
}
word = strtok(NULL, " .,");
}
cout << "after : " << result << endl;
return 0;
}
Output:
abcd 345 pqrst 321
3
before: abcd 345 pqrst 321
after : dabc 345 stpqr 321

Recursive function to generate string does not contain two adjacent identical substring c++

I have a task that is difficult for me to handle. The task is: Create recursive function that can be generate a string of length N (N <= 100), formed by the letters 'A', 'B' and 'C' and does not containing two identical adjacent substring. For example: enter for N = 6 and the program should generate such a string in which no one else to repeated substrings: ABACAB. Wrong strings are: AABACA - because 'A' is to 'A'; ABCBCA - as 'BC' is to 'BC' and ABCABC is also wrong because 'ABC' is to 'ABC'.
I made a version of the program but an iterative way, here is the code:
#include <iostream>
#include <ctime>
using namespace std;
const char letters[] = "ABC";
char generate_rand()
{
return letters[rand() % 3];
}
int check(char *s, int pos)
{
for (int i = 1; i <= (pos + 1)/2; i++)
{
int flag = 1;
for (int j = 0; j < i; j++)
if (s[pos-j] != s[pos-i-j])
{
flag = 0;
break;
}
if (flag)
return 1;
}
return 0;
}
int main()
{
char s[100];
int n;
cout << "enter n: ";
cin >> n;
srand(time(NULL));
for (int i = 0; i < n; i++)
{
do
{
s[i] = generate_rand();
} while (check(s, i));
cout << s[i] << " ";
}
cout << " ok" << endl;
system("pause");
return 0;
}
I think the entrance of the recursive function may need to be the number of characters in the string, which will seek to repeat with an adjacent string and each time increased by 1, but not more than half the length of the original string, but do not know how to do it.
So lets start with a simple recursive function which prints 10 letters but doesn't check anything:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (strlen(buf) < max_length)
addLetter(buf);
}
int main()
{
srand(time(NULL)); //I forgot srand!
int max_length = 10; //ask user to input max_length, like you had earlier
char buf[100];
memset(buf,0,sizeof(buf));
addLetter(buf, max_length);
printf("\n%s\n", buf);
return 0;
}
Now lets change the recursive function, get it to check just 1 letter:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (len > 0)
{
if (buf[len] == buf[len-1])
buf[len] = 0;
}
if (strlen(buf) < max_length)
addLetter(buf);
}
Next step, check 2 letters with previous ones etc. You should be able to take it from here.

Reverse n characters in the string (there is no spaces in string) without using built-in functions in c++

I have a string like str="ABCDEFGHIJK";
need o/p like this str="CBAFEDIHGJK"
am getting "CBA" correctly after that its not printing anything.
can anyone check the following code and let me know where is the problem?
int main()
{
string str="ABCDEFGHIJK";
char str1[10],rev[10];
int n=str.length(),count=0,c=3,k=0,j=0;
for(int i=0;i<n;i++)
{
str1[i]=str[i];
count++;
cout<<str1[i]<<" and "<<count<<"and "<<c<<endl;
if(count==c)
{
cout<<"Entered into if loop"<<count<<"and"<<c<<"and "<<k<<endl;
cout<<c<<" and "<<k<<endl;
while(j<c)
{
rev[j]=str1[c-k-1];
cout<<rev[j]<<" and "<<str1[c-k-1]<<endl;
j++;
k++;
}
count=0;
}
/*else
{
if(count < c && str[i]=='\0')
{
for(int k=0;k<count;k++)
{
rev[k]=str1[count-1];
count--;
count=0;
}
}
}*/
}
cout<<"The string is: "<<rev<<endl;
return 0;
}
Please help me on this.
No need to use a c++ string object for this use-case; just use a normal char *.
Also, always make sure you store enough room for the string null-terminator character ('\0'). This is required as c string functions assume your string is terminated in this way.
Following will reverse string in ansi C89
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse(char *in, char *rev)
{
int i, n;
n = strlen(in);
for(i = n-1; i>=0; i--)
{
rev[n-i-1] = in[i];
}
/* add the null-terminator */
rev[n] = '\0';
}
int main()
{
char *str = "ABCDEFGHIJK";
char str1[12], temp;
char triplet[4];
char rev_triplet[4];
int index;
triplet[3] = '\0';
rev_triplet[3] = '\0';
str1[0] = '\0';
for(index = 0; index < strlen(str); index += 3)
{
memcpy(triplet, str + index, 3 * sizeof(char));
reverse(triplet, rev_triplet);
strcat(str1, rev_triplet);
}
printf("Initial string is: %s\n", str);
printf("Reverse string is: %s\n", str1);
return 0;
}
Outputs
$ ./test
Initial string is: ABCDEFGHIJK
Reverse string is: CBAFEDIHGKJ
If you intend to use C++ (and not C) for this:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_triples(std::string s)
{
const unsigned int N = 3;
for (int i = 0, j = N - 1; i < s.length() - (s.length() % N); i += N, j += N)
{
std::swap(s[i], s[j]);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s);
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
Whatever value of N you need can be modified (and even supplied as a function parameter if you want). You only need to swap the outer characters (so all the elements below N / 2 will be swapped with the elements above N / 2). For N == 3, it is just a single swap. If you want to do it more generically:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_substrings(std::string s, unsigned int substring_size)
{
for (int i = 0, j = substring_size - 1; i < s.length() - (s.length() % substring_size); i += substring_size, j += substring_size)
{
std::reverse(s.begin() + i, s.begin() + j + 1);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s, 4); // passing 3 gets you the same results as before
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
First, let us examine how std::reverse might be implemented. It uses iterators.
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
We can extend the logic to use indices instead of iterators, where i and j represent iterators (positions) and s[i] and s[j] represent the data pointed to by the iterators.
void reverse(std::string& s)
{
int i = 0;
int j = s.size();
while ((i != j) && (i != (--j)))
{
std::swap(s[i], s[j]);
++i;
}
}
Now you want to reverse "chunks" rather than the entire string.
void reverse(int n, std::string& s)
{
int beg = 0;
int end = beg + n;
int size = s.size();
// We're going to modify s in place
// So store a copy
std::string copy = s;
s = "";
// Add + 1 to avoid the loop cutting off short
// Or do i <= size / n;
for (int i = 0; i < size / n + 1; i++)
{
std::string chunk(copy.begin() + beg, copy.begin() + end);
// If there's no n sized chunks left
// don't reverse
if (end < size)
reverse(chunk);
s += chunk;
beg += n;
// Don't go past the size of the string
end += (end + n > size ? size - end : n);
}
}
int main()
{
std::string s("ABCDEFGHIJK");
std::string target("CBAFEDIHGJK");
reverse(3, s);
std::cout << s << "|" << target <<"|\n";
std::cout << s.size() << " " << target.size() << "\n"; // 11 11
std::cout << std::boolalpha << (s == target); // true
return 0;
}

how to check whether 2 strings are rotations to each other ?

Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html