Unexpected output when I try to reverse a char* - c++

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

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

C++ program not returning a Value (Functions)

I want to write a program, to create a function that concatenates two strings to form a single string. However, my program is not returning any value.
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
char* my_str_cat( char* s1, char* s2, char* combined ){
for(int i = 0;i<strlen(s1);i++){
combined[i]=s1[i];
}
for (int j=0;j<strlen(s2);j++){
combined[strlen(s1)+j]=s2[j];
}
return combined;
}
int main(){
char s1[100];
char s2[100];
char** combined = new char*;
cout<<"Enter s1: "<<endl;
cin.getline(s1,100);
cout<<s1<<endl;
cout<<"Enter s2: "<<endl;
cin.getline(s2,100);
my_str_cat(s1,s2,*combined);
delete combined;
return 0;
}
This declaration
char** combined = new char*;
declares a pointer of the type char ** that points to an allocated memory for an object of the type char *.
Dereferencing this pointer in this call
my_str_cat(s1,s2,*combined);
passes an uninitialized pointer of the type char * to the function my_str_cat.
And within the function this uninitialized pointer is used to access a memory that results in undefined behavior.
You need to allocate a memory for a character array large enough to store two concatenated C strings forming a new C string.
You could allocate the memory within the function itself.
The function can look the following way as it is shown in the demonstrative program below.
#include <iostream>
#include <iomanip>
#include <cstring>
char * my_str_cat( const char *s1, const char *s2 )
{
size_t n1 = std::strlen( s1 );
char * result = new char[n1 + std::strlen( s2 ) + 1];
std::strcpy( std::strcpy( result, s1 ) + n1, s2 );
return result;
}
int main()
{
const size_t N = 100;
char s1[N];
char s2[N];
std::cout << "Enter s1: ";
std::cin.getline( s1, sizeof( s1 ) );
std::cout << "Enter s2: ";
std::cout << std::noskipws;
std::cin.getline( s2, sizeof( s2 ) );
char *combined = my_str_cat( s1, s2 );
std::cout << combined << '\n';
delete []combined;
return 0;
}
The program output might look like
Enter s1: Hello
Enter s2: World!
Hello World!
Another approach of declaring and defining the function is when it is the user of the function that is responsible to supply the result character array to the function that will contain two concatenated strings.
For example
#include <iostream>
#include <iomanip>
#include <cstring>
char * my_str_cat( char *result, const char *s1, const char *s2 )
{
return std::strcat( std::strcpy( result, s1 ) , s2 );
}
int main()
{
const size_t N = 100;
char s1[N];
char s2[N];
std::cout << "Enter s1: ";
std::cin.getline( s1, sizeof( s1 ) );
std::cout << "Enter s2: ";
std::cout << std::noskipws;
std::cin.getline( s2, sizeof( s2 ) );
char *combined = new char[std::strlen( s1 ) + std::strlen( s2 ) + 1];
std::cout << my_str_cat( combined, s1, s2 ) << '\n';
delete []combined;
return 0;
}
The program output might look the same way as it is shown for the previous demonstrative program that is
Enter s1: Hello
Enter s2: World!
Hello World!
Without using standard string functions and using only loops the function can be defined the following way.
char * my_str_cat( char *result, const char *s1, const char *s2 )
{
char *p = result;
while ( *s1 ) *p++ = *s1++;
while ( ( *p++ = *s2++ ) );
return result;
}
First thing first, it (would) return a value its, just not assigned to anything. to do so:
*combined = my_str_cat(s1,s2,*combined);
Also either pass combined by refrence, or dont pass it al all.
But it doesnt cause it crashes with a seg fault, because you refere to s1[i] while s1 is not initialized.
Im gonna correct that in C style cause your code is really just C with spice:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
using namespace std;
void my_str_cat( char* s1, char* s2, char* &combined){
int len = strlen(s1);
combined = (char*)calloc(1, (len + strlen(s2)));
strcpy(combined, s1);
strcpy(combined + len, s2);
}
int main(){
char s1[100];
char s2[100];
char* combined;
cout<<"Enter s1: " << endl;
cin.getline(s1,100);
cout<<s1<<endl;
cout<<"Enter s2: " << endl;
cin.getline(s2,100);
my_str_cat(s1,s2, combined);
cout << combined << endl;
delete combined;
return 0;
}
(Tho this works, i had i feeling of missing something while writting this. Please let me know what is it if you know.)

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
}

reverse string using char * and string class

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)