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.
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!