reverse string using char * and string class - c++

I try to reverse a string by pointer walking. Logic is simple that I have two pointers to char one of them head that points to first char of the string. The other tail points to second-last character(before \0) of the string. Swap then char-by-char. C-style it works well, but C++-style doesn't work. I wonder its reason.
C-style
#include <iostream>
#include <cstring>
using std::cin;
using std::cout;
using std::endl;
using std::string;
void reverse(char *str)
{
char *tail, *head;
head = &str[0];
tail = &str[strlen(str)];
cout << "String inverted is: ";
while ((head!=tail)&&(head!=--tail))
{
char temp=*head;
*head++=*tail;
*tail=temp;
}
}
int main(int argc, char const *argv[])
{
char str[100];
cout << "Enter a string: ";
cin.getline(str,100);
reverse(str);
cout << str;
cout <<"\n";
return 0;
}
C++-style
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
void reverse(string str)
{
char *tail, *head;
head = &str[0];
tail = &str[str.size()];
cout << "String inverted is: ";
while ((head!=tail)&&(head!=--tail))
{
char temp=*head;
*head++=*tail;
*tail=temp;
}
}
int main(int argc, char const *argv[])
{
string str;
cout << "Enter a string: ";
getline(cin,str);
reverse(str);
cout << str;
cout <<"\n";
return 0;
}

You are not passing the string in to reverse by reference.
You are currently passing in a copy of the string.
make reverse have this prototype:
void reverse(string& str)

Related

How to find the last character of an string and assign it to a char pointer?

I need Ptr to have first character of the string and BufLim to have last character of the string.
#include <iostream>
using namespace std;
int main()
{
const char* Str = "Stackoverflow";
const char* Ptr = Str[0];
const char* BufLim = &Ptr.back(); // pointer pointing to last character of *ptr
cout << Ptr;
cout << BufLim;
return 0;
}
Kindly help me on this.
Prior to c++17, use std::string instead of const char* string literals.
Then you can easily have the pointer to the first and the last char of the string by the help of member functions std::string::front and std::string::back respectively (given that the string is not empty).
#include <string>
using namespace std::string_literals;
std::string Str{ "Stackoverflow"s };
/* const */ char* ptrFirst = &Str.front();
/* const */ char* ptrLast = &Str.back();
std::cout << *ptrFirst << "\n"; // prints S
std::cout << *ptrLast; // prints w
(Alternatively) in c++17, you can use std::string_view, which is basically a wrapper around const char*. Like std::string, it has the same kind of member functions std::string_view::front and std::string_view::back
#include <string_view>
using namespace std::string_view_literals;
std::string_view Str{ "Stackoverflow"sv };
const char* ptrFirst = &Str.front();
const char* ptrLast = &Str.back();
std::cout << *ptrFirst << "\n"; // prints S
std::cout << *ptrLast; // prints w

Alternative for a loop in C++

I want to reverse a string without the use of a loop. My code with the loop looks like:
#include <iostream>
#include <string>
using namespace std;
string reverseString(string str) {
string changedString;
int strLength = int(str.length() - 1);
for(int i {strLength}; i >= 0; i--) {
changedString.push_back(str.at(i));
}
return changedString;
}
int main() {
string str;
cout << "Enter a string to reverse it:\n" << flush;
cin >> str;
cout << reverseString(str) << flush;
}
Now I need to write a function without the loop. Only the methods of String should be used. Can you help me solving this problem?
It is very simple to write such a function
std::string reverse( const std::string &s )
{
return { s.rbegin(), s.rend() };
}
Here is a demonstrative program
#include <iostream>
#include <string>
std::string reverse( const std::string &s )
{
return { s.rbegin(), s.rend() };
}
int main()
{
std::string s( "Hello World" );
std::cout << s << '\n';
std::cout << reverse( s ) << '\n';
return 0;
}
Its output is
Hello World
dlroW olleH
Well, you can do that using recursion. Here are some links if you aren't aware what recursion is : link1 and link2.
Technically it won't be a loop.
string reverseString(string str, int index, string ans) {
if (index == -1) return ans;
ans += str[index];
return reverseString(str, index - 1, ans);
}
Parameters for this function will be str as it was by default, index = size(str) - 1 and ans ans = "";
reverseString(str, size(str) - 1, "") for example.
If you want your function to take exactly one argument, then you can write wrapper function and the one I wrote will have different name - reverseStringWrapper for example and in reverseString there will be only one line - return reverseStringWrapper(str, size(str) - 1, "");
string reverseStringWrapper(string str, int index, string ans) {
if (index == -1) return ans;
ans += str[index];
return reverseString(str, index - 1, ans);
}
string reverseString(string str) {
return reverseStringWrapper(str, size(str) - 1, "");
}
How was this?
In c, You can use strrev() function to reverse the string(char*)
In c++, you can either use std::reverse() or StringBuilder.reverse()
method to reverse a string.
.
This way you can reverse the char array(char*).
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
// Function to reverse a given character array using std::reverse
void reverse(char *str)
{
std::reverse(str, str + strlen(str));
}
// main function
int main()
{
/* using C string */
char s[] = "Hello World";
reverse(s);
cout << "Reverse of the given string is : " << s;
return 0;
}
This way you can reverse the string.
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
// Function to reverse a given character array using std::reverse
void reverse(char* str)
{
std::reverse(str, str + strlen(str));
}
// main function
int main()
{
/* using C string */
// char s[] = "Techie Delight";
string s = "hello world";
int n = s.length();
// declaring character array
char char_array[n + 1];
// copying the contents of the
// string to char array
strcpy(char_array, s.c_str());
reverse(char_array);
s = char_array;
cout << "Reverse of the given string is : " << s;
return 0;
}
Hope this might Helps:)

istringstream-function string_to_int cannot take c-str, why?

I learned a helper function that can convert strings to integers:
int string_to_int(string s)
{
istringstream instr(s);
int n;
instr>>n;
return n;
}
It's mentioned that the argument s cannot be c-str string, why is this the case?
But you can pass a C style string.
The reason for that is because the std::string constructor can implicitly accept a CharT* (Char type, which is char in this case) as a parameter. Thus, something like the following would work:
#include <iostream>
#include <sstream>
using namespace std;
int string_to_int(string s)
{
istringstream instr(s);
int n;
instr>>n;
return n;
}
int main()
{
const char* test = "12345";
std::cout << string_to_int(test) << "\n"; // Outputs 12345
std::cout << string_to_int("122") << "\n"; // Outputs 122
}

ERROR deprecated conversion from string constant to 'char*'

I'm stuck with error message deprecated conversion from string constant to 'char*'
What I tried to do here is to assign "First", "Last" to cfoo1 and make cfoo2 equal to cfoo1. Lastly, display cfoo1 and cfoo2 to standard output.
#include <iostream>
#include <cstring>
#include "cfoo.h"
using namespace std;
CFoo :: CFoo(char first[], char last[]){
m_first[BUF] = first[BUF];
m_last[BUF] = last[BUF];
}
void CFoo :: WriteFoo(){
cout << m_first[BUF] << ", " << m_last[BUF];
}
#ifndef CFOO_HEADER
#define CFOO_HEADER
#include <iostream>
#include <cstring>
using namespace std;
const int BUF = 256;
class CFoo{
public:
CFoo(char first[], char last[]);
void WriteFoo();
private:
char m_first[BUF];
char m_last[BUF];
};
#endif
#include <iostream>
#include "cfoo.h"
using namespace std;
int main(){
CFoo foo1("Jong", "Yoon");
CFoo foo2 = foo1;
cout << "foo1 = ";
foo1.WriteFoo();
cout << endl;
cout << "foo 2 = ";
foo2.WriteFoo();
cout << endl;
return 0;
}
There are two issues:
Using string literals (which are of type char const*) to call a function that expects char[].
Trying to assign to char arrays.
Fixes:
Change the constructor to:
CFoo(char const* first, char const* last);
Change its implementation to:
CFoo(char const* first, char const* last)
{
// Make sure to copy at most BUF-1 characters
// to m_first and m_last.
m_first[0] = '\0'
strncat(m_first, first, BUF-1);
m_last[0] = '\0'
strncat(m_last, last, BUF-1);
}
You also need to change the implementation of CFoo::WriteFoo() to use the entire string
void CFoo::WriteFoo()
{
cout << m_first << ", " << m_last;
}
Also,
Accessing m_first[BUF] or m_last[BUF] is an error since the maximum value of a valid index to access those arrays is BUF-1.

Unexpected output when I try to reverse a char*

#include<iostream>
#include<string>
using namespace std;
void reverse(char* str)
{
char *new_str = str;
while(*new_str != '\n'){
new_str++;
}
while(new_str != str){
cout << *new_str;
new_str--;
}
cout << *new_str;
}
int main()
{
char *str = new char[1024];
str = "hello world";
reverse(str);
}
When I try to run this I get some crazy output and my computer starts to beep. What am I doing blatantly wrong here?
The end of a C string is marked by the character '\0'. You used '\n' which is the newline character.
You mean apart from using the naked leaky new, the deprecated char* instead of const char* or even better std::string, not using a Standard Library algorithm std::reverse, mixing IO with your algorithm and including the entire namespace std (which might indirectly bring std::reverse() into scope) without putting your own reverse() inside its own namespace?
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
// using namespace std; // for the brave, and drop the std:: in the next 3 lines
int main()
{
std::string str = "hello world"; // std::string instead of char*
std::reverse(begin(str), end(str)); // standard library algorithm
std::cout << str; // IO separate from algorithm
}
If you are only interested in how to code a reverse algorithm, here is one way to do it without relying on the fact that you have a null terminator:
template<class BidirIt>
void reverse(BidirIt first, BidirIt last)
{
while ((first != last) && (first != --last)) {
std::swap(*first++, *last);
}
}
The problem is that at first you assigned str the address of allocated memory and then reassigned it to point to string literal that has type const char[] in C++.
char *str = new char[1024];
str = "hello world";
This string literal has terminating zero char '\0'. It has no the new line char '\n'. So the function is invalid because it will try to access memory beyond the array searching the new line char.
The valid code could look the following way
#include <iostream>
using namespace std;
void reverse( const char* s )
{
const char *p = s;
while ( *p ) p++;
while ( p != s ) cout << *--p;
}
int main()
{
const char *s = "hello world";
reverse( s );
}
Or if you want to enter a string yourself interactively then main could look as
int main()
{
const size_t N = 1024;
char s[N];
cout << "Enter a statement: ";
cin.getline( s, N );
reverse( s );
}
correct your function :
void reverse(char* str)
{
char *new_str = str;
while(*new_str){ // use this instead of *new_ptr != '\n'
new_str++;
}
while(new_str != str){
cout << *new_str;
new_str--;
}
cout << *new_str;
}