c++ function to reverse string doesn't work - c++

Just learning c++. The following function is my attempt to reverse a string (doesn't work and I don't know why). Thank you for spotting my stupidity.
#include <iostream>
using namespace std;
string r(string s)
{
int len = s.length();
for (int i = 0; i < len; i++)
{
char temp = s[i];
s[i] = s[len - i];
s[len - i] = temp;
}
return s;
}
int main()
{
cout << r("ASTRING");
}
It changes first letter of the string to ' ' and outputs STRING

Another simple way:
string r(string s)
{
int len = s.length();
string temp;
for (int i = len - 1; i > -1; i--)
{
temp.push_back(s[i]);
}
s = temp;
return s; // or return temp;
}

Firstly, string.length() returns length with '\0' which mean end of string, so you need to delete 1.
Secondly, you don't travel whole string, you should stop at the middle, i/2 will just do this whatever the length is.
finally :
string r(string s)
{
int len = s.length() - 1;
for (int i = 0; i < len/2; i++)
{
char temp = s[i];
s[i] = s[len - i];
s[len - i] = temp;
}
return s;
}

Related

how to removing rubbish data(garbage data) from output in c++?

Well, I have to Create class to Insert String in another one at the specific position Without using class string(any pre-made classes except iostream.
When I ask for output it gets rubbish data..
#include "stdafx.h"
#include <iostream>
using namespace std;enter code here
//StrLen Calculates String Length
int StrLen(char *s) {
int len = 0;
while (s[len]!='\0'){
len++;
}
return len;
}
//The value of the string that is it's first argument is inserted into String that is it's second argument, pos is the beginning at position given by main.
char *InsertStr(char *s1, char *s2, int pos) {
int c = 0;
int len1 = StrLen(s1);
int len2 = StrLen(s2);
char s3[100];
int i = pos;
//This while move string from postion till the end of string to s3
while (s1[i] != '\0') {
s3[c] = s1[i];
c++;
i++;
}
c = 0;
i = pos;
//the string in s2[0 to the end of s2] moved to s1[from pos to len1]
while (s2[c] != '\0') {
s1[i] = s2[c];
c++;
i++;
}
int len3 = StrLen(s3);
len1 = StrLen(s1);
int x2 = len1 + len3;
c = 0;
len1 = StrLen(s1);
int x3 = pos + len2;
//this loop get the elements sent to s3 and get them back to
//s1[from pos + len2 till s3[i] reach the end]
for (int i = 0; i < len3; i++) {
s1[x3] = s3[i];
x3++;
}
return s1;
}
int main()
{
char s1[100];
char s2[100];
int pos=0;
cout << "Enter The First Argument String : \n";
cin.getline(s1, 100);
cout << "Enter The Second Argument String : \n";
cin.getline(s2, 100);
cout << "Enter The Position : \n";
cin >> pos;
cout << InsertStr(s1, s2, pos);
cout << "******************";
return 0;
}
I used In cin.getline(), to get all string till '\0'.
I traced the code all loops works fine except last one, Last one have garbage data.
I saw a video on youtube solved it like this but i couldn't trace it..
//This code is a working one, But i didn't use it since i couldn't trace it
#include "stdafx.h"
#include <iostream>
using namespace std;
int strlen(char *s)
{
int c = 0;
while (s[c] != '\0') c++;
return c;
}
char* my_strncat(char *s1, char *s2, int pos)
{
//k= pos
int len1, len2;
int i = 0, k = pos,l=0,j=0;
int x,x1, x2, x3;
len1 = strlen(s1);
len2 = strlen(s2);
char s3[100];
while (i <= len1) {
s3[i] = s1[i];
i++;
}
//x2=len2 j =len1
x1 = len1 + len2;
x3 = len2 + pos;
for (i = pos; i < x1; i++) {
x = s3[i];
if (l < len2) {
s1[i] = s2[l];
l++;
}
s1[x3] = x;
x3++;
}
return s1;
}
int main()
{
char s1[100] ;
char s2[100] ;
int pos = 0;
cout << "Enter The string of Source: \n";
cin.getline(s1,100);
cout << "Enter The string of Destination: \n";
cin.getline(s2, 100);
cout << "Enter The position of Destination: \n";
cin >> pos;
cout << my_strncat(s1, s2, pos) << endl;
return 0;
}
I cannot reproduce your garbage data but I see that you, in InsertStr() systematically forget, to add the zero at the end of strings. Your code goes in UB (Undefined Behaviour) so your garbage data a perfectly explained.
So, copying s1 in s3
while (s1[i] != '\0') {
s3[c] = s1[i];
c++;
i++;
}
s3[c] = '\0'; // add this line!
Copying s2 to s1+pos
while (s2[c] != '\0') {
s1[i] = s2[c];
c++;
i++;
}
s1[i] = '\0'; // add this line!
And copying the last part of s3 at the end of s1
for (int i = 0; i < len3; i++) {
s1[x3] = s3[i];
x3++;
}
s1[x3] = '\0'; // add this line!
Or, maybe, you can simply write your loops, using do/while, as follows
do
s3[c++] = s1[i];
while ( s1[i++] );
// ...
do
s1[i++] = s2[c];
while ( s2[c++] );
// ...
i = 0;
do
s1[x3++] = s3[i];
while ( s3[i++] );

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

copying strings , c++

i'm trying to perform a program that prints string correctly from it's middle
the problem to me is that strange behavior to me that at certain line it agrees to print string only char by char and refuses to return it to be printed in the main function
here is my code :
string unscramble(string line)
{
string temp;
int i,j;
int len=line.size();
i=len/2-1;
j=0;
do{
if(i<0)
i=len-1;
temp[j]=line[i];
cout << temp[j];
j++;
i--;
}while(i!=(len/2)-1);
return temp;
}
Your issue is in the assignment to temp. You'll also hit an issue if the string length is even. Do it this way instead:
string unscramble(string line)
{
string temp;
int i, j;
int len = line.size();
int factor = len / 2 - 1;
if(len % 2 == 1)
factor = len / 2;
i = factor;
j = 0;
do
{
if(i < 0)
i = len - 1;
temp += line[i];
j++;
i--;
}
while(i != factor);
return temp;
}
Example input: RUT OWT SNEH HCNERF EERHTEGDIRTRAP A DNA SEVODELT
Output: THREE FRENCH HENS TWO TURTLEDOVES AND A PARTRIDGE

How can I reverse the words in a sentence without using built-in functions?

This was the interview question:
How to convert Dogs like cats to cats like Dogs ?
My code shows: cats like cats. Where am I making the mistakes?
#include <iostream>
using namespace std;
int main()
{
char sentence[] = ("dogs like cats");
cout << sentence << endl;
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++)
{
len++;
}
cout << len << endl;
char reverse[len];
int k = 0;
for (int j = len - 1; j >= 0; j--)
{
reverse[k] = sentence[j];
k++;
}
cout << reverse << endl;
int words = 0;
char str[len];
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--)
{
str[words] = reverse[m];
words++;
}
}
}
cout << str;
return 0;
}
I know you can do this using pointers, stack, vectors... but interviewer was not interested in that!
This is a fixed version of your sample code:
Your principal problem is that every time you found and ' ' or '\0' you copy the bytes of the reverse string from the beginning to that point. Example in loop 5 you copy from index 0-5 (stac) from reverse to str in reverse order, but in in loop 10 you copy from index 0-10 (stac ekil) from reverse to str in reverse order, until here you have already the printed result string ('cats like cats'), and the same in loop 15 all of this incrementing the index of str, in the last loop you are written pass the end of the valid memory of str (and because of that not printed as output).
You need to keep track when end the last word reversed to reverse only the actual word, and not the string from the beginning to the actual index.
You don't want to count the special character (' ' and '\0') in the reversing of the words, you would end with cats like\0dogs
Modified sample code provided:
#include <iostream>
using namespace std;
int main() {
char sentence[] = ("dogs like cats");
cout << sentence << endl;
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;
char reverse[len];
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
cout << reverse << endl;
int words = 0;
char str[len];
// change here added last_l to track the end of the last word reversed, moved
// the check of the end condition to the end of loop body for handling the \0
// case
for (int l = 0, last_l = 0; ; l++) {
if (reverse[l] == ' ' || reverse[l] == '\0')
{
for (int m = l - 1; m >= last_l; m--) { // change here, using last_t to
str[words] = reverse[m]; // only reverse the last word
words++; // without the split character
}
last_l = l + 1; // update the end of the last
// word reversed
str[words] = reverse[l]; // copy the split character
words++;
}
if (reverse[l] == '\0') // break the loop
break;
}
cout << str << endl;
return 0;
}
Some code, written with the restriction of using the most simple features of the language.
#include <iostream>
// reverse any block of text.
void reverse(char* left, char* right) {
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main() {
char sentence[] = "dogs like cats";
std::cout << sentence << std::endl;
// The same length calculation as sample code.
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
std::cout << len << std::endl;
// reverse all the text (ex: 'stac ekil sgod')
reverse(sentence, sentence + len - 1);
// reverse word by word.
char* end = sentence;
char* begin = sentence;
while (end < sentence + len) {
if (*end != ' ')
end++;
if (end == sentence + len || *end == ' ') {
reverse(begin, end - 1);
begin = end + 1;
end = begin;
}
}
std::cout << sentence << std::endl;
return 0;
}
Dissecting your algorithm in pieces. First, you find the length of the string, not including the null char terminator. This is correct, though could be simplified.
size_t len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;
This could easily be written simply as:
size_t len = 0;
while (sentence[len])
++len;
Next, you reverse the entire string, but the first defect surfaces. The VLA (variable length array) you declare here, (which you don't need and shouldn't use, as it is a C++ extension and non-standard) does not account for, nor set, a terminating null-char.
char reverse[len]; // !! should be len+1
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
// !! Should have reverse[k] = 0; here.
cout << reverse << endl; // !! Undefined-behavior. no terminator.
This temporary buffer string is not needed at all. There is no reason you can't do this entire operation in-place. Once we calculate len correctly, you simply do something like the following to reverse the entire sequence, which retains the null char terminator in proper position:
// reverse entire sequence
int i = 0, j = len;
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}
Next we move to where you try to reverse each internal word. Again, just as before, the buffer length is not correct. It should be len+1. Worse (hard to imagine), you never remember where you left off when finding the end point of a word. That location should be the next point you start checking for, and skipping, whitespace. Without retaining that you copy from current point all the way back to the beginning of the string. which essentially blasts cats over dogs.
int words = 0;
char str[len]; // !! should be len+1
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--) {
str[words] = reverse[m];
words++;
}
}
}
cout << str; //!! Undefined behavior. non-terminated string.
Once again, this can be done in-place without difficulty at all. One such algorithm looks like this (and notice the loop that reverses the actual word is not-coincidentally the same algorithm as reversing our entire buffer):
// walk again, reversing each word.
i = 0;
while (sentence[i])
{
// skip ws; root 'i' at beginning of word
while (sentence[i] == ' ') // or use std::isspace(sentence[i])
++i;
// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (sentence[j] && sentence[j] != ' ') // or use !std::isspace(sentence[j])
++j;
// remember the last position
size_t last = j;
// same reversal algorithm we had before
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}
// start at the termination point where we last stopped
i = last;
}
Putting It All Together
Though considerably simpler to use pointers than all these index variables, the following will do what you're attempting, in place.
#include <iostream>
int main()
{
char s[] = "dogs like cats";
std::cout << s << '\n';
size_t len = 0, i, j;
while (s[len])
++len;
// reverse entire sequence
i = 0, j = len;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}
// walk again, reversing each word.
i = 0;
while (s[i])
{
// skip ws; root 'i' at beginning of word
while (s[i] == ' ') // or use std::isspace
++i;
// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (s[j] && s[j] != ' ') // or use !std::isspace
++j;
// remember the last position
size_t last = j;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}
// start at last-left posiion
i = last;
}
std::cout << s << '\n';
return 0;
}
Output
dogs like cats
cats like dogs
My advise would be to break up the original string into an array of words, reverse that array. Then add those words to your reversed sentence with a space in between.
Since they asked for no libraries, I assumed no std::string, no vectors, nothing at all and so I wrote it in C.. the only thing used is printf. Everything else is from scratch :l
The idea is that you reverse the array first. Then split the array by space and reverse each word.
Example: http://ideone.com/io6Bh9
Code:
#include <stdio.h>
int strlen(const char* s)
{
int l = 0;
while (*s++) ++l;
return l;
}
void reverse(char* str)
{
int i = 0, j = strlen(str) - 1;
for(; i < j; ++i, --j)
{
str[i] ^= str[j];
str[j] ^= str[i];
str[i] ^= str[j];
}
}
void nulltok(char* str, char tok, int* parts)
{
int i = 0, len = strlen(str);
*parts = 1;
for (; i < len; ++i)
{
if (str[i] == tok)
{
str[i] = '\0';
++(*parts);
}
}
}
char* reverse_sentence(char* str)
{
char* tmp = str;
reverse(str);
int i = 0, parts = 0, len = strlen(str);
nulltok(str, 0x20, &parts);
while(parts--)
{
reverse(str);
str += strlen(str) + 1;
}
for(; i < len; ++i)
if (tmp[i] == '\0')
tmp[i] = 0x20;
return tmp;
}
int main(void)
{
char str[] = "dogs like cats";
printf("%s", reverse_sentence(str));
return 0;
}
My solution
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string str;
cout<<"enter the sentence"<<endl;
getline(cin,str);
char* pch;
pch = strtok((char*)str.c_str()," ");
string rev = "";
while(NULL != pch)
{
rev.insert(0,pch);
rev.insert(0," ");
pch = strtok(NULL," ");
}
cout<<"the reversed string is :"<<rev<<endl;
return 0;
}

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;
}