Creating a Palindrome String Checker C++ using Arrays and No Pointers - c++

Sorry if this seems really noobish and all, and the fact is, i've only been studying this for about a month now. I can't seem to get this to work right, wondering if any of you can help me out. The program once compiled only says that the inputted words are "not palindrome" even if they are.
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
bool isPal (char[], int);
int main ()
{
const int size = 10;
int flag = 0;
char arr[size];
cout << "Enter Word\n";
cin.getline(arr,10);
flag = isPal(arr, size);
if (flag == true)
cout << "Word is Palindrome\n";
else
cout << "Not Palindrome\n";
return 0;
}
bool isPal (char arr [],int size)
{
int q = 0;
char arr2[size];
for (int i = 0;i < size - 1; i++)
{
arr2[i] = arr[9 - q]; //here I attempt to reverse arr1 and assign each element to arr2
q++;
}
for (int j = 0; j < size - 1; j++)
{
if (arr [j] != arr2[j])
return false;
}
return true
}

If you only want to use plain C arrays then check with below code:-
bool isPallindrome ( char *p, int size ) //Remember here size must be one character before null //terminator.
{
char *begin, *end;
begin = p;
end = p + size;
while ( begin != end )
{
if( *begin != *end )
break;
begin++;
end--;
}
if ( begin != end )
return false;
return true;
}

Initialize the arr2
Use strlen to know the length you Input rather than use size, because your input data is not always fixed in 10
In your original code:
input: 1234567
*arr => "1234567\0"
*arr2 => "??\07654321"
Use size replaced by q
bool isPal (char arr [],int size)
{
//q=0; /* modified 3 */
char arr2[size] = ""; /* modified 1 */
for (int i=0; i<strlen(arr); i++) /* modified 2 */
{
arr2[i] = arr[strlen(arr)-i-1]; /* modified 2 */
//q++; /* modified 3 */
}
for (int i=0; i<strlen(arr); i++) /* modified 2 */
{
if (arr[i] != arr2[i])
return false;
}
return true
}
Array is "a pointer point to begin of array address", But for newbie, it's not easy to know how it works. You can reserve this thread until you learn the chapter pointer
Following the example of modified original code:
char arr[size];
char arr2[size];
// char *parr = (char*)malloc(sizeof(char)*size);
// char *parr2 = (char*)malloc(sizeof(char)*size);
cin.getline(arr,10);
// parr = &arr[0];
// cin.getline(parr, 10);
arr2[i] = arr[9 - q];
// parr1 = &arr[9-q];
// parr2 = &arr2[i]
// *parr2 = *parr1;
if (arr [j] != arr2[j])
// parr1 = &arr[j]
// parr2 = &arr2[j]
// if (*parr1 != *parr2)

Related

what is the issue with this char reverse function?

so I wrote this code to reverse one of the names based on the user option the idea is to use another function to reverse and to use pointers but after trying all I could think of my code return the same name not changed the best I could do was changing the first letter of the name to a weird sign.
#include <iostream>
using namespace std;
void reverse(char* A) {
int count = 0;
char temp[10];
for (int i = 0; A[i] != NULL; i++)
count++;
for (int i = 0; A[i] != NULL; i++) {
temp[count]=A[i];
count--;
}
for (int i = 0; A[i] != NULL; i++) {
A[i] = temp[i];
}
}
int main(){
int x= 0;
int index;
char Name_list[5][10];
cout << "please enter the names of the student " << endl;
for (int i = 0; i < 5; i++) {
cin >> Name_list[i];
for (int j = 0; Name_list[i][j] != NULL; j++) {
x++;
}
while (x > 10)
{
x = 0;
cout << "you have entered more then the allowed number of characters per name enter another name " << endl;
cin >> Name_list[i];
for (int j = 0; Name_list[i][j] != NULL; j++) {
x++;
}
}
x = 0;
}
for (int i = 0; i < 5; i++) {
cout << Name_list[i] << endl;
}
cout << "please enter the index of the name you want to reverse" << endl;
cin >> index;
while (index>4||index <0)
{
cout << "you entered incorrect index please enter a number from 0 to 4 " << endl;
}
reverse(Name_list[index]);
for (int i = 0; i < 5; i++) {
cout << Name_list[i] << endl;
}
system("pause");
}
For starters such a function should return a pointer to the result string. That is it should be declared like
char * reverse( char *s );
Note: do not use variable names consisting from upper case letters.
The type int can be not large enough to store length of a string. Instead use the type size_t.
char * reverse( char *s )
{
size_t count = 0;
//...
It is totally unclear why there is present an array with the number of elements equal to the magic number 10
char temp[10];
To reverse a string there is no need to declare an auxiliary array. Such an approach is principally wrong.
In this for loop
for (int i = 0; A[i] != NULL; i++)
there is compared an object of the type char with the pointer NULL. The compiler should issue a message for such a wrong comparison. It seems you mean
for (int i = 0; A[i] != '\0'; i++)
In any case the introduced variable i in this first for loop is redundant because you already has the variable count.
As you have the array temp with the fixed size equal to 10 then the both loops after the first loop can invoke undefined behavior even if the length of the source string is equal exactly to 10.
And the result string is not zero terminated.
The function can look the following way.
char * reverse( char *s )
{
size_t count = 0;
while ( s[count] ) ++count;
for ( size_t i = 0; i < count / 2; i++ )
{
char c = s[i];
s[i] = s[count - i - 1];
s[count - i - 1] = c;
}
return s;
}
Or using standard functions you could write the function reverse the following way
#include <utility>
#include <cstring>
//...
char * reverse( char *s )
{
for ( size_t i = 0, n = std::strlen( s ); i < n / 2; i++ )
{
std::swap( s[i], s[n-i-1] );
}
return s;
}
Pay attention to that there is the standard algorithm std::reverse. Using it you could reverse a string the following way
std::reverse( s, s + std::strlen( s ) );
for (int i = 0; A[i] != NULL; i++) {
temp[count]=A[i];
count--;
}
If i goes up from 0 to 5, count goes down from 6 to 1.
Ok, a few things.
If you want do some string manipulation, look into the stdlib. Unless you are doing this for class.
Your writing everything to the end of the temp. buffer
You need to add an extra character at the end of the strings for the null byte (I think this implementation may allow for a seg. fault)

Possible memory leak in using dynamic memory?

In this program, I coded to get a list of names, specifically using pointers, and perform bubble sort and binary search on the list. I recognize that there are better ways of dealing with this type of memory, but I want to learn this way properly before moving on. I was having errors with not properly deallocating and/or allocating memory, but now, I don't have any error messages popping up running this code, though I still believe that some memory has not been properly deallocated. Here's my code:
Main.cpp
#include "Functions.h"
void main() {
// initialize variables
int numNames = 0;
char* search;
int index = 0;
bool isSearching = true;
// get list of names
cout << "Enter your list of names:" << endl;
char** nameList = readList(numNames);
// sort list of names
bubbleSort(nameList, numNames);
// show sorted list of names
cout << "Sorted list of names:" << endl;
for (int i = 0; i < numNames; i++) {
cout << nameList[i] << endl;
}
// do binary search loop
do {
// get search word
cout << "Enter a word you would like to search for: " << endl;
search = readLine();
// get index of search
index = binarySearch(nameList, numNames, search);
// if missing
if (index == -1) {
cout << "That word is missing" << endl;
}
// show index
else {
cout << "That word is at index " << index << endl;
}
// set loop test
isSearching = search[0] != '\0';
// free mem
delete[] search;
} while (isSearching);
// free mem
for (int i = 0; i < numNames; i++) {
delete[] nameList[i];
}
delete[] nameList;
system("Pause");
}
Functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include "ReadFunctions.h"
#include "SortingAndSearchingFunctions.h"
#endif
ReadFunctions.h
#ifndef READ_FUNCTIONS_H
#define READ_FUNCTIONS_H
#include <iostream>
#include <conio.h>
#include <memory.h>
#include "Functions.h"
using namespace std;
char* readLine();
char** readList(int &);
#endif
ReadFunctions.cpp (the readList function was having problems before, and although errors are not popping up, I still think that there may be a memory leak.)
#include "ReadFunctions.h"
static void backspace() {
_putch('\b');
_putch(' ');
}
char** readList(int & numWords) { // read list of words
// initialize variables
const int firstNumWords = 10;
char* word;
numWords = 0;
int maxWords = firstNumWords;
char** wordList = new char*[maxWords];
char** temp;
// read list loop
while ((word = readLine())[0] != '\0') {
// add word
wordList[numWords++] = word;
// expand list
if (numWords >= maxWords) {
maxWords += firstNumWords;
temp = new char*[maxWords];
memcpy(temp, wordList, numWords * sizeof(char*));
wordList = temp;
//may need delete statement?
}
}
return wordList;
}
char* readLine() { // read word
// initialize variables
const int firstNumChar = 10;
char c;
int charsEntered = 0;
int maxChars = firstNumChar;
char* word = new char[maxChars + 1];
char* temp;
cout << "> ";
// read word loop
while ((c = _getch()) != '\r') {
// backspace
if (c == '\b') {
if (charsEntered == 0) {
c = '\a';
}
else {
backspace();
charsEntered--;
word[charsEntered] = '\0';
}
}
else {
// add character
word[charsEntered++] = c;
// expand word
if (charsEntered >= maxChars) {
maxChars += firstNumChar;
temp = new char[maxChars + 1];
memcpy(temp, word, charsEntered);
delete[] word;
word = temp;
}
}
_putch(c);
}
_putch('\n');
word[charsEntered] = '\0';
return word;
}
SortingAndSearchingFunctions.h
#ifndef SORTING_AND_SEARCHING_FUNCTIONS_H
#define SORTING_AND_SEARCHING_FUNCTIONS_H
#include "Functions.h"
#include <string.h>
void bubbleSort(char** &, int);
int binarySearch(char** &, int, char*);
#endif
SortingAndSearchingFunctions.cpp
#include "SortingAndSearchingFunctions.h"
static bool isAfter(char* str1, char* str2) { // check if first string is after the second string
// initialize variables
bool isGreater = false;
bool isEqual = false;
char c1;
char c2;
int compareLen = (strlen(str1) >= strlen(str2)) ? strlen(str2) : strlen(str1);
// check c-strings
for (int i = 0; i < compareLen; i++) {
// get compare characters
c1 = str1[i];
c2 = str2[i];
// check if both alphabetical
if (((c1 >= 'a' && c1 <= 'z') || (c1 >= 'A' && c1 <= 'Z')) && ((c2 >= 'a' && c2 <= 'z') || (c2 >= 'A' && c2 <= 'Z'))) {
// normalize for case insensitive
if (c1 >= 'A' && c1 <= 'Z') {
c1 = (char)(c1 + 32);
}
else if (c2 >= 'A' && c2 <= 'Z') {
c2 = (char)(c2 + 32);
}
}
// handle comes after
if (c1 > c2) {
isGreater = true;
isEqual = false;
i = compareLen;
}
// handle comes before
else if (c1 < c2) {
isGreater = false;
isEqual = false;
i = compareLen;
}
// handle equal
else {
isEqual = true;
}
// case with symbol, which case to compare with?
}
// handle equal comparison region
if (isEqual) {
if (strlen(str1) > strlen(str2)) {
isGreater = true;
}
}
return isGreater;
}
void bubbleSort(char** & wordList, int numWords) { // bubble sort for word lists
// initialize variables
char* temp;
bool swap = false;
// sort loop
do {
// set swap and numwords
swap = false;
numWords--;
// check list
for (int i = 0; i < numWords; i++) {
// swap
if (isAfter(wordList[i], wordList[i + 1])) {
swap = true;
temp = new char[((strlen(wordList[i]) >= strlen(wordList[i + 1])) ? strlen(wordList[i + 1]) : strlen(wordList[i])) + 1];
memcpy(temp, wordList[i], strlen(wordList[i]) + 1);
//temp = wordList[i];
memcpy(wordList[i], wordList[i + 1], strlen(wordList[i + 1]) + 1);
//wordList[i] = wordList[i + 1];
memcpy(wordList[i + 1], temp, strlen(temp) + 1);
//wordList[i + 1] = temp;
//delete[] temp; // if included shows access violation, but should still include and find another way?
}
}
} while (swap);
}
int binarySearch(char** & wordList, int numWords, char* search) { // binary search for word lists
// initialize variables
int first = 0;
int mid;
int last = numWords - 1;
// search loop
do {
// set middle index
mid = (first + last) / 2;
// check if equal
if (strcmp(search, wordList[mid]) == 0) {
return mid;
}
// check if after
else if (isAfter(search, wordList[mid])) {
first = mid + 1;
}
// check if before
else {
last = mid - 1;
}
} while (first <= last);
// not found
return -1;
}
If you don't find any problems, is there any way that I can properly set up dynamic memory and check for memory leaks so that I don't have any worries about this problem.
EDIT: Here's a modified version of the code in the while loop in the readList function in the ReadFunctions.cpp file:
// add word
wordList[numWords++] = word;
// expand list
if (numWords >= maxWords) {
maxWords += firstNumWords;
temp = new char*[maxWords];
memcpy(temp, wordList, numWords * sizeof(char*));
delete[] wordList;
wordList = temp;
}
What's keeping you from using std::vector and std::string? This would eliminate all memory leaks, make the code more efficient, and reduce the size of you code quite a bit. Using std::sort would also help reduce the unnecessary complexity of the code.
And you do need a delete[] statement around the //may need delete statement? comment.
Your modified code doesn't work, because :
if (numWords >= maxWords) {
maxWords += firstNumWords;
temp = new char*[maxWords];
for (int i = 0; i < numWords; i++) { // you're copying into uninititialized pointers !!!!!
memcpy(temp[i], wordList[i], (strlen(wordList[i]) + 1) * sizeof(char));
}
for (int i = 0; i < numWords; i++) {
delete[] wordList[i];
}
wordList = temp;
}
The proper way to resize an array of pointers:
if (numWords >= maxWords) {
temp = new char*[maxWords + firstNumWords]; // allocate new array
memcpy(temp, wordList, maxWords * sizeof(char*)); // copy the pointer values.
char* p = wordList;
wordList = temp; // put new array in place.
delete[] p; // delete old array.
maxWords += firstNumWords; // fix size var.
}

Dynamic Memory issue in C++

so I was writing a program which has to check if the input sting is a palindrome or not. And it's actually working but a problem with deleting the array I created during the course of it arouse.
#include <iostream>
using namespace std;
bool checkPalindrome(char* text);
char* clearString(char* src);
int main()
{
char buffer[1000];
cin.getline(buffer, 1000);
cout << boolalpha << checkPalindrome(buffer) << endl;
return 0;
}
bool checkPalindrome(char* text)
{
char* newStr = clearString(text);
if (!newStr)
return false;
int newLen = strlen(newStr);
for (int i = 0; i < newLen / 2; i++) {
if (newStr[i] == newStr[newLen - i - 1])
continue;
else
return false;
}
//delete[] newStr;
return true;
}
char* clearString(char* src)
{
unsigned len = strlen(src);
unsigned counter = 0;
for (int i = 0; i < len; i++) {
if (src[i] == ' '||src[i] == '.'||src[i] == ','||src[i] == '!')
counter++;
}
unsigned newSize = len - counter + 1;
char* dest = new(nothrow) char[newSize];
if (!dest) {
cout << "not enoough memory\n";
return NULL;
}
int i, j;
for(i = j = 0; j < newSize; ++i, ++j) {
if(src[i]==' '||src[i]=='.'||src[i]==','||src[i]=='!'||src[i]=='?')
i++;
else
dest[j] = src[i];
}
dest[j] = '\0';
return dest;
}
So the commentated delete in the checkPalindrome function causes a crash if executed and I get the "Heap corruption detected" error. I tried changing the function type to void and delete there and the same thing happened. Any ideas what causes it?
Your loop copies the '\0' at the end of the string, but then you add another '\0', using one more byte of memory than you allocated.

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