so I want to do the simplest thing in c++ , reverse a string (store the new string) and than print it
my code is :
char a[size] , reverse[size];
strcpy(a,"dlow olleh " );
for (int i = 0 ; i <= strlen(a); i++) {
reverse[i]= a[strlen(a)-i];
}
cout << reverse ;
I must note that when
cout << reverse[i] ;
is inside the for loop every thing wotks fine , but when I wwant to print it as a string it just don't , I cant under stand what ive missed
cout << reverse[i] ;
what am i doing wrong?
You are using arrays of char and functions of the C Standard Library to manipulate strings in C++.
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string foo{ "Hello, World!" };
std::string bar{ foo };
std::reverse(bar.begin(), bar.end());
std::cout << '\"' << foo << "\" ==> \"" << bar << "\"\n";
}
If – for some reason beyond my comprehension – you *have to* do it by foot, do it in an idiomatic way and provide an interface that takes a pair of iterators:
#include <algorithm>
void str_reverse(char *begin, char *end)
{
while (begin < end)
std::swap(*begin++, *--end);
}
// ...
#include <cstring>
// ...
char foo[]{ "Hello, World!" };
str_reverse(foo, foo + std::strlen(foo));
If you can't use <algorithm> for whatever reason implement your own swap():
template<typename T>
void swap(T &a, T &b)
{
T tmp{ a };
a = b;
b = tmp;
}
In this loop
for (int i = 0 ; i <= strlen(a); i++){
reverse[i]= a[strlen(a)-i];
you are accessing characters beyond the actual characters of the strings.
For example when i is equal to 0 you are coping the terminating zero character from the string a into the first position of the string reverse.
reverse[0]= a[strlen(a)-0];
the code can be written simpler without for example reduntant calls of the function strlen.
char a[size], reverse[size];
strcpy( a, "dlrow olleh" );
size_t i = 0;
for ( size_t n = strlen( a ); i < n; i++ )
{
reverse[i] = a[n - i - 1];
}
reverse[i] = '\0';
std::cout << reverse << '\n';
Pay attention to that there is the standard algorithm std::reverse_copy that does the same task.
Below there is a demonstrative program.
#include <iostream>
#include <algorithm>
#include <cstring>
int main()
{
const size_t SIZE = 20;
char a[SIZE], reverse[SIZE];
std::strcpy( a, "dlrow olleh" );
std::cout << a <<'\n';
auto it = std::reverse_copy( a, a + strlen( a ), reverse );
*it = '\0';
std::cout << reverse <<'\n';
return 0;
}
The program output is
dlrow olleh
hello world
The first you copy when reversing the string is in fact the null terminator so when you are printing it to console it will not show up since the null terminator is the first in the array so you want to do this instead
int size = 12;
char a[12], reverse[12];
strcpy(a, "dlow olleh ");
for (int i = 0; i < strlen(a); i++) {
reverse[i] = a[strlen(a) - (i+1)];
}
reverse[strlen(a)] = '\0';
cout << reverse;
Related
I am studying pointers in C++. I have studied call by value and call by reference concept. I am trying to create a function to reverse a string which accepts a pointer to string and the size of string. The code is as follow
void reverse(string* str, int size)
{
int start = 0;
int end = size - 1;
while(start < end)
{
swap(*str[start++], *str[end--]);
}
}
int main()
{
string str = "Something";
reverse(&str, str.length());
cout << "Reversed string: " << str << endl;
return 0;
}
I am getting this error:
error: no match for ‘operator*’ (operand type is ‘std::string’ {aka
‘std::__cxx11::basic_string’})
12 | swap(*str[start++], *str[end--]);
I don't want to use the character array, is there way to do it?
Someone please explain, what's wrong in my code. Thank you.
Here is the simple fix. You don't need to change anything except a few lines.
#include <iostream>
#include <algorithm>
#include <cstring>
void reverse( std::string* str ) // no need to pass size to this function
{
int start = 0;
int end = str->length() - 1; // get the length of str like this
char* ptrToCharArray = const_cast<char*>( str->c_str() ); // gets the pointer to str's internal buffer
while ( start < end )
{
std::swap( ptrToCharArray[start++], ptrToCharArray[end--] ); // no need to use * operator anymore
}
}
int main()
{
std::string str = "Something";
reverse( &str );
std::cout << "Reversed string: " << str << std::endl;
return 0;
}
Output is:
Reversed string: gnihtemoS
Hopefully, this helps you.
Just need a little bit of change in your code
Change this *str[start++] to (*str).at(start++)
void reverse(string* str, int size)
{
int start = 0;
int end = size - 1;
while(start < end)
{
swap((*str).at(start++),(*str).at(end--));
}
}
int main()
{
string str = "Something";
reverse(&str, str.length());
cout << "Reversed string: " << str << endl;
return 0;
}
Note that there is no need to pass the size of the string as an argument to the function. You can use the member function std::string::size for that purpose as shown below:
Version 1: Passing pointer to string as argument
#include <iostream>
#include <algorithm>
void reverse(std::string *str)
{
int n=(*str).size()-1;//dereference the pointer and use size member function on the resulting string object
for(int i=0;i<((*str).size()/2);i++){
//Using the swap method to switch values at each index
std::swap((*str).at(i),(*str).at(n)); //note this can also be written as std::swap((*str)[i],(*str)[n]);
n = n-1;
}
}
int main()
{
std::string myString = "myString";
reverse(&myString);
std::cout<<"Reversed string is: "<<myString<<std::endl;
return 0;
}
In version 1, *(str) gives us a std::string type object. Next we call size member function on this std::string object. Similarly we can call the std::string::at member function on this std::string object.
Version 2: Passing reference to string as argument
#include <iostream>
#include <algorithm>
void reverse( std::string &str)
{
int n=str.size()-1;
for(int i=0;i<(str.size()/2);i++){
//Using the swap method to switch values at each index
std::swap(str.at(i),str.at(n));
n = n-1;
}
}
int main()
{
std::string myString = "myString";
reverse(myString);
std::cout<<"Reversed string is: "<<myString<<std::endl;
return 0;
}
I am new to C++ and want to test out how much I actually learned so I made this simple cRaZyTeXt generator. But there's a weird bug I can't find any way to solve.
Codes are here:
#include <iostream>
#include <string>
#include <algorithm>
#include <windows.h>
char convertToUppercase (char x)
{
int asciiCode {static_cast<int>(x) - 32};
char y {static_cast<char>(asciiCode)};
return y;
}
char convertToLowercase (char x)
{
int asciiCode {static_cast<int>(x) + 32};
char y {static_cast<char>(asciiCode)};
return y;
}
void toClipboard(const std::string &s){
OpenClipboard(0);
EmptyClipboard();
HGLOBAL hg=GlobalAlloc(GMEM_MOVEABLE,s.size() + 1);
if (!hg){
CloseClipboard();
return;
}
memcpy(GlobalLock(hg),s.c_str(),s.size() + 1);
GlobalUnlock(hg);
SetClipboardData(CF_TEXT,hg);
CloseClipboard();
GlobalFree(hg);
}
int main()
{
std::cout << "Enter the text you want to convert into cRaZy TeXt: " << '\n';
std::string userInput {};
std::getline(std::cin >> std::ws, userInput);
char userInputArray [userInput.size()];
std::copy(userInput.begin(), userInput.end(), userInputArray);
char outputArray [userInput.size()];
for (int i = 0; i <= userInput.size(); ++i)
{
int x {static_cast<int>(userInputArray[i])};
if (i % 2 == 0)
{
if (x <= 90 && x >= 65)
outputArray[i] = convertToLowercase(userInputArray[i]);
else
outputArray[i] = userInputArray[i];
}
else
{
if (x <= 122 && x >= 97)
outputArray[i] = convertToUppercase(userInputArray[i]);
else
outputArray[i] = userInputArray[i];
}
}
std::cout << outputArray << '\n';
toClipboard(outputArray);
system("pause");
return 0;
}
when I enter Hello, world!, it can output hElLo, WoRlD! as exactly how I want it to be. proof
But when I try my name is sean., its output would look like this: screenshot
mY NaMe iS SeAn.#y name is sean.#%�
What's more weird is that both my name is ma sean. and my name is sean ma. works fine.
my name is ma sean.
my name is sean ma.
I have tried above four inputs in both release and debug configuration and it's all the same.
Please elaborate on the issue and make the explanation friendlier for beginners.
Any helps are appreciated. Thank you in advance.
For starters variable length arrays as for example the declaration of this array
char userInputArray [userInput.size()];
is not a standard C++ feature.
There is no need to use auxiliary arrays to perform the task. You could change the original object userInput of the type std::string itself.
This variable length array
char outputArray [userInput.size()];
does not contain a space for the terminating zero character '\0' to make the stored sequence of characters a string.
As a result this output
std::cout << outputArray << '\n';
invokes undefined behavior.
This for loop
for (int i = 0; i <= userInput.size(); ++i)
leads to access memory beyond the declared variable length arrays because the valid range of indices is [ 0, userInput.size() ).
Also it is a bad idea to use magic numbers like for example 65 or 90. This makes the code unreadable.
If I have understood correctly what you need is a function like the following shown in the demonstrative program below.
#include <iostream>
#include <string>
#include <cctype>
std::string & cRaZyTeXt_generator( std::string &s )
{
int upper_case = 1;
for (auto &c : s)
{
if ( std::isalpha( static_cast< unsigned char >( c ) ) )
{
if ( ( upper_case ^= 1 ) )
{
c = std::toupper( static_cast< unsigned char >( c ) );
}
else
{
c = std::tolower( static_cast< unsigned char >( c ) );
}
}
}
return s;
}
int main()
{
std::string s( "Hello, World!" );
std::cout << s << '\n';
std::cout << cRaZyTeXt_generator( s ) << '\n';
}
The program output is
Hello, World!
hElLo, WoRlD!
I'm trying to print some values on a string like this:
std::vector<std::string> data;
data.push_back("One");
data.push_back("1");
const std::string & description = "This %s is number %s";
DWORD dwSize = data.size();
char szDescription[255 + 1];
for (DWORD i = 0; i < dwSize; ++i)
{
_snprintf(szDescription, sizeof(szDescription), description.c_str(), data[i].c_str());
}
return szDescription;
However, when I print the string it returns me:
This One is number 124897566
I print the strings after snprintf and the second value is handled on the first iteration
An alternative solution for you is to replace the tokens in the std::string one by one. There are different solutions you could use (e.g., using regular expressions, using a library like fmt, etc.). Here is a simple example that uses basic std::string methods:
#include <iostream>
#include <vector>
std::string build() {
std::vector<std::string> data;
data.push_back("One");
data.push_back("1");
const std::string token = "%s";
const std::string description = "This %s is number %s";
std::string out = "";
size_t start = 0;
size_t end = description.find(token);
int i = 0;
while (end != std::string::npos) {
out += description.substr(start, end - start);
out += data[i++];
start = end + token.length();
end = description.find(token, start);
}
out += description.substr(start, end - start);
return out;
}
int main () {
std::cout << build() << '\n';
return 0;
}
This code prints:
This One is number 1
Since this is C++, you can use std::ostringstream. The issue with _snprintf is that it is not type-safe (the input type must match the format specifier), and that it knows nothing about C++ objects such as std::string.
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
std::string foo()
{
std::vector<std::string> data;
data.push_back("One");
data.push_back("1");
std::ostringstream strm;
std::string s;
for (size_t i = 0; i < data.size(); ++i)
{
strm << "The " << data[i] << " is number " << i + 1;
s = strm.str();
std::cout << s << "\n";
strm.str("");
}
return s;
}
int main()
{
foo();
}
Output:
The One is number 1
The 1 is number 2
Live Example
I want to sort each string of array of strings , here is my code that i tried.
#include <iostream>
#include <algorithm>
void _sort_word(char *str)
{
int len = strlen(str);
std::sort(str,str+len); // program get stuck here.
}
int main()
{
char *str[] = {"hello", "world"};
for(int i=0;i<2;i++){
_sort_word(str[i]);
cout << str[i] << "\n";
}
}
I want to know is sort(str,str+len); a valid statement here, if not what should be done instead ?
First of all string literals in C++ have types of constant character arrays. So the correct array declaration will look like
const char *str[] = {"hello", "world"};
^^^^^
Thus the string literals pointed to by the elements of the array are immutable.
You should declare at least a two dimensional array.
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <cstring>
void sort_word( char *s )
{
size_t l = std::strlen( s );
std::sort( s, s + l );
}
int main()
{
char str[][6] = { "hello", "world" };
for ( auto &s : str ) sort_word( s );
for ( auto &s : str ) std::cout << s << std::endl;
return 0;
}
Its output is
ehllo
dlorw
If your compiler does not support the range based for statement then you can write instead
for ( size_t i = 0; i < sizeof( str ) / sizeof( *str ); i++ ) sort_word( str[i] );
I'm trying to write a code which stores strings in an array. I'm trying to do it with char* but I couldn't achieve. I search the net but couldn't find an answer. I've tried the code below, but it didn't compile.I use string stream because at some point I need to concatenate a string with an integer.
stringstream asd;
asd<<"my name is"<<5;
string s = asd.str();
char *s1 = s;
> I'm trying to write a code which stores strings in an array.
Well, first you'll need an arary of strings. I don't like using naked arrays, so I use std::vector:
std::vector<std::string> myStrings;
But, I understand you have to use an array, so we'll use an array instead:
// I hope 20 is enough, but not too many.
std::string myStrings[20];
int j = 0;
> I use string stream because ...
Okay, we'll use stringstream:
std::stringstream s;
s << "Hello, Agent " << 99;
//myStrings.push_back(s.str()); // How *I* would have done it.
myStrings[j++] = s.str(); // How *you* have to do it.
That gets us one string, but you want an array of them:
for(int i = 3; i < 11; i+=2) {
s.str(""); // clear out old value
s << i << " is a" << (i==9?" very ":"n ") << "odd prime.";
//myStrings.push_back(s.str());
myStrings[j++] = s.str();
}
Now you have an array of strings.
Complete, tested program:
#include <sstream>
#include <iostream>
int main () {
// I hope 20 is enough, but not too many.
std::string myStrings[20];
int j = 0;
std::stringstream s;
s << "Hello, Agent " << 99;
//myStrings.push_back(s.str()); // How *I* would have done it.
myStrings[j++] = s.str(); // How *you* have to do it.
for(int i = 3; i < 11; i+=2) {
s.str(""); // clear out old value
s << i << " is a" << (i==9?" very ":"n ") << "odd prime.";
//myStrings.push_back(s.str());
myStrings[j++] = s.str();
}
// Now we have an array of strings, what to do with them?
// Let's print them.
for(j = 0; j < 5; j++) {
std::cout << myStrings[j] << "\n";
}
}
How about something like this?
vector<string> string_array;
stringstream asd;
asd<<"my name is"<<5;
string_array.push_back(asd.str());
char *s1 = s;
Is illegal. You either need:
const char *s1 = s.c_str();
if you're not set on char*, or you'll need to allocate a new char* and use strcpy to copy the contents from the string.
Just change your code to
char const* s1 = s.c_str();
because a pointer to char can't store a string object, only a pointer to char, which is what c_str() returns.
I wouldn't use the char * directly. I would wrap it in something like the template below. You can override the operators you need to do any more operations (example, I would make data a private member, and override the operators to make the data print out cleanly). I did the assignment operator just to demonstrate how clean that could make code.
#include "MainWindow.h"
#include <stdio.h>
using namespace std;
template<size_t size>
class SaferChar
{
public:
SaferChar & operator=(string const & other)
{
strncpy(data, other.c_str(), size);
return *this;
}
char data[size];
};
int main(int argc, char *argv[])
{
SaferChar<10> safeChar;
std::string String("Testing");
safeChar = String.c_str();
printf("%s\n", safeChar.data);
return 0;
}