I get the following output: olleh�hello but can't figure out where I'm going wrong!
int main()
{
char hello[6] = "hello";
char temp[6];
unsigned int t = 0;
for(int i=strlen(hello)-1;i>=0;i--)
{
if(t<strlen(hello))
{
temp[t] = hello[i];
t++;
}
}
cout << temp;
return 0;
}
You need a null terminator at the end of the string:
int main()
{
char hello[6] = "hello";
char temp[6];
unsigned int t = 0;
for(int i=strlen(hello)-1;i>=0;i--)
{
if(t<strlen(hello))
{
temp[t] = hello[i];
t++;
}
}
temp[t] = '\0';
cout << temp;
return 0;
}
you tagged the question as [C++], so here's C++ way to reverse string:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string hello = "hello";
std::reverse(hello.begin(), hello.end());
std::cout << hello << std::endl;
}
it's difficult to make any mistake here
You aren't terminating temp with a null (\0), so temp isn't a valid string and cout doesn't know quite what to do with it. Your problem will go away if you add:
temp[5] = 0;
after the for loop.
Related
I am writing a program to reverse a string and insert random characters in between.
Here is my code:
main.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include "encrypter.cpp"
using namespace std;
int main(int argc, char *argv[])
{
char message[256];
this_thread::sleep_for(chrono::milliseconds(1000));
cout << "Make sure theres no one around you" << endl;
this_thread::sleep_for(chrono::milliseconds(1000));
cout << "Enter secret message ";
cin.get(message, 256);
cout << "message encrypted" << endl;
enc(message);
return 0;
}
encrypter.cpp
#include <iostream>
#include <string>
int getRandom(int a, int b) {
return a + (rand() % static_cast<int>(b - a + 1));
}
using namespace std;
void enc(char message[256]) {
int i = 0;
int len = strlen(message);
int revlen = len - 1;
int wtpselector;
int charselector;
int encsim;
char randchar[6] = "##$%&";
char strreved[256];
char strenc[1024];
while (i < len) {
strreved[revlen] = message[i];
i++;
revlen--;
}
revlen = strlen(strreved);
len = revlen - 1;
i = 0;
encsim = 0;
while (i < revlen) {
wtpselector = getRandom(0, 4);
charselector = getRandom(0, 4);
if (wtpselector == 0) {
strenc[encsim] = strreved[i];
i++;
encsim++;
} else {
strenc[encsim] = randchar[charselector];
encsim++;
}
}
cout << strenc << endl;
}
But the output has many random characters that are not supposed to be there and are not in the program.
Like:
Input: hello world
Output: $%#$#&&d&&#%$%1%row &#$$#%&ol#%##%&1%&#$&#ehe$%%€##8#&%#$#& #%##%&¢&#%#&#$##$#%%##&%##&#&$8%#$###$#$##%&&#&##Q#$$#&¢%#% Q#\#&$##{&&&&$#¢ \ $$$$######&&&%%&&%{ $#¢v#&#&~u####%&%¢
Please help!!!
You have missed two important things:
when you declare an array it's values are not defined (whatever is in memory)
strlen counts to the first occurance of '\0' character
In order for your code to work you must initialize char arrays, which means change those two lines:
char strreved[256];
char strenc[1024];
to:
char strreved[256] = {0};
char strenc[1024] = {0};
I would like to reverse a c-style string and came up with the following code.
Play with the code
#include <iostream>
void reverse_c_str(char *c)
{
char *new_c = c;
for (; *new_c; ++new_c){} // find '\0'
--new_c; // new_c is now at the actual last char, which is 'g'
while (c < new_c) // swap chars
{
char tmp = *c;
*c = *new_c; // crash
*new_c = tmp;
--new_c;
++c;
}
}
int main()
{
char *c = "my string";
reverse_c_str(c);
std::cout << c << '\n';
}
Unfortunately, my code has an error, which I marked with // crash. Why does this line crash?
"my string" is a string literal, it is const.
It can be cast to a non-const char * for reasons of compatibility with C, but modifying a constant invokes undefined behavior. In some cases the OS will prevent it (as when it's stored in a read-only section), which is probably what you're observing.
Make a copy of the string in automatic storage, then you'll be able to modify it:
int main()
{
char c[] { "my string" };
reverse_c_str(c);
std::cout << c << '\n';
}
And of course there is a templated soultion:
#include <cstring>
template<std::size_t N>
void reverse_c_str(char (&str)[N]) {
std::size_t len = N-1;
for (std::size_t i = 0; i < len/2; ++i) {
str[i] ^= str[len-i-1];
str[len-i-1] ^= str[i];
str[i] ^= str[len-i-1];
}
}
int main() {
char c[] {"123"};
reverse_c_str(c);
char c2[] {""};
reverse_c_str(c2);
char c3[] {"4321"};
reverse_c_str(c3);
return 0;
}
Use std::swap and std::strlen. I made example for you here.
#include <iostream>
#include <cstring>
void reverse_c_str(char *c) {
int length = std::strlen(c);
for (int i = 0; i < length / 2; i++)
std::swap(c[i], c[length - i - 1]);
}
int main()
{
char c[] { "my string" };
reverse_c_str(c);
std::cout<<c << std::endl;
return 0;
}
Output:
gnirts ym
Another one version of function reverse_c_str
void reverse_c_str(char *c) {
if(*c) {
for(auto begin = c, end = c + std::strlen(c) - 1;
begin < end; ++begin, --end
) {
std::swap(*begin, *end);
}
}
}
Here is my code
int main(int argc, char *argv[]) {
char const *strings[10] = {"dhh", "aci", "cdh"};
join_def(strings, 'l');
return EXIT_SUCCESS;
}
// part 1 read lines
void join_def(char const **strings, char delim) {
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = sizeof(strings);
std::cout << delim << std::endl;
for (int i = 0; i < x; i++) {
int size = 0;
while(strings[i][size]!='\0'){
size++;
std::cout << strings[i][size] << std::endl;
}
}
}
I have spent hours now I just can't get to concatenate it
For this task, I cannot use cstring or anything other than iostream so please don't suggest.
The output needs to be a c-string = "dhhlacilcdh"
First, you cannot determine the number of elements in an array passed to a function, as that array will decay to a simple pointer. So, your sizeof(strings) expression will evaluate (at compile time) to the (fixed) size, in bytes, of a pointer. For the function to be 'aware' of how many elements there are in an array, it needs to be explicitly told (by way of an extra argument).
Second, you have your i' and size indexes the wrong way round in the std::cout << strings[i][size] << std::endl; line and, further, you increment size before printing the relevant character, whereas it should be incremented after you've printed it.
The code below also does the actual concatenation of the strings, and the modified join_def function now returns a pointer to that result (which must be freed when you're finished with it);
#include <iostream>
char* join_def(char const** strings, char delim, int x)
{
char* t = new char[100];
int length = 0;
t[0] = '\0';
//int x = sizeof(strings);
std::cout << delim << std::endl;
for (int i = 0; i < x; i++) {
int size = 0;
while (strings[i][size] != '\0') {
std::cout << strings[i][size] << std::endl;
t[length++] = strings[i][size]; // Append this character
size++;
}
t[length++] = delim; // Append delimiter
}
t[length] = '\0'; // Append nul-terminator
return t;
}
int main()
{
char const* strings[10] = { "dhh", "aci", "cdh" };
char* result = join_def(strings, 'l', 3);
std::cout << result << std::endl;
free(result);
return 0;
}
Note, also, that I have moved the join_def function code to before the main (which calls it). If you don't do this, then will at least have to provide a (forward) declaration of that function before main (just a char* join_def(char const** strings, char delim, int x); on its own will do).
Feel free to ask for further clarification and/or explanation.
I'm not exactly sure what you're trying to do, but maybe this helps?
#include <iostream>
// part 1 read lines
void join_def(char const **strings, char delim)
{
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = 0;
for (int i = 0; strings[i] != nullptr; i++)
x += sizeof(strings[i]) - 1;
std::cout << delim << std::endl;
for (int i = 0; strings[i] != nullptr; i++)
{
int size = 0;
while (strings[i][size] != '\0')
{
size++;
std::cout << strings[i][size] << std::endl;
}
}
}
int main(int argc, char *argv[])
{
char const *strings[] = {"dhh", "aci", "cdh", nullptr};
join_def(strings, 'l');
return EXIT_SUCCESS;
}
this is what you are looking for?
look that I remove all the std::endl because it like '\n'
also i moved your size++ after the std::cout
#include <iostream>
// part 1 read lines
void join_def(char const **strings, char delim,int length) {
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = length;
for (int i = 0; i < x; i++) {
int size = 0;
while(strings[i][size]!='\0'){
std::cout << strings[i][size]; //<--print befure increment size
size++;
}
std::cout << delim;
}
}
int main(int argc, char *argv[]) {
char const *strings[] = {"dhh", "aci", "cdh"};
join_def(strings,'|',3); //<- need to send the length of the char* array
return EXIT_SUCCESS;
}
In a C++14 program, I am given a string like
std::string s = "MyFile####.mp4";
and an integer 0 to a few hundred. (It'll never be a thousand or more, but four digits just in case.) I want to replace the "####" with the integer value, with leading zeros as needed to match the number of '#' characters. What is the slick C++11/14 way to modify s or produce a new string like that?
Normally I would use char* strings and snprintf(), strchr() to find the "#", but figure I should get with modern times and use std::string more often, but know only the simplest uses of it.
What is the slick C++11/14 way to modify s or produce a new string like that?
I don't know if it's slick enough but I propose the use of std::transform(), a lambda function and reverse iterators.
Something like
#include <string>
#include <iostream>
#include <algorithm>
int main ()
{
std::string str { "MyFile####.mp4" };
int num { 742 };
std::transform(str.rbegin(), str.rend(), str.rbegin(),
[&](auto ch)
{
if ( '#' == ch )
{
ch = "0123456789"[num % 10]; // or '0' + num % 10;
num /= 10;
}
return ch;
} // end of lambda function passed in as a parameter
); // end of std::transform()
std::cout << str << std::endl; // print MyFile0742.mp4
}
I would use regex since you're using C++14:
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
int main()
{
std::string text = "Myfile####.mp4";
std::regex re("####");
int num = 252;
//convert int to string and add appropriate number of 0's
std::string nu = std::to_string(num);
while(nu.length() < 4) {
nu = "0" + nu;
}
//let regex_replace do it's work
std::regex_replace(std::ostreambuf_iterator<char>(std::cout),
text.begin(), text.end(), re, nu);
std::cout << std::endl;
return 0;
}
WHy not use std::stringstream and than convert it to string.
std::string inputNumber (std::string s, int n) {
std::stringstream sstream;
bool numberIsSet = false;
for (int i = 0; i < s; ++i) {
if (s[i] == '#' && numberIsSet == true)
continue;
else if (s[i] == '#' && numberIsSet == false) {
sstream << setfill('0') << setw(5) << n;
numberIsSet = true;
} else
sstream << s[i];
}
return sstream.str();
}
I would probably use something like this
#include <iostream>
using namespace std;
int main()
{
int SomeNumber = 42;
std:string num = std::to_string(SomeNumber);
string padding = "";
while(padding.length()+num.length()<4){
padding += "0";
}
string result = "MyFile"+padding+num+".mp4";
cout << result << endl;
return 0;
}
Mine got out of control while I was playing with it, heh.
Pass it patterns on its command line, like:
./cpp-string-fill file########.jpg '####' test###this### and#this
#include <string>
#include <iostream>
#include <sstream>
std::string fill_pattern(std::string p, int num) {
size_t start_i, end_i;
for(
start_i = p.find_first_of('#'), end_i = start_i;
end_i < p.length() && p[end_i] == '#';
++end_i
) {
// Nothing special here.
}
if(end_i <= p.length()) {
std::ostringstream os;
os << num;
const std::string &ns = os.str();
size_t n_i = ns.length();
while(end_i > start_i && n_i > 0) {
end_i--;
n_i--;
p[end_i] = ns[n_i];
}
while(end_i > start_i) {
end_i--;
p[end_i] = '0';
}
}
return p;
}
int main(int argc, char *argv[]) {
if(argc<2) {
exit(1);
}
for(int i = 1; i < argc; i++) {
std::cout << fill_pattern(argv[i], 1283) << std::endl;
}
return 0;
}
I would probably do something like this:
using namespace std;
#include <iostream>
#include <string>
int main()
{
int SomeNumber = 42;
string num = std::to_string(SomeNumber);
string guide = "myfile####.mp3";
int start = static_cast<int>(guide.find_first_of("#"));
int end = static_cast<int>(guide.find_last_of("#"));
int used = 1;
int place = end;
char padding = '0';
while(place >= start){
if(used>num.length()){
guide.begin()[place]=padding;
}else{
guide.begin()[place]=num[num.length()-used];
}
place--;
used++;
}
cout << guide << endl;
return 0;
}
So I'm having a substantial amount of trouble with this one bit of code. I've included the whole program for context, but my issue lies in the cleanUp function, wherein I (attempt to) remove all characters that are not 'A' through 'Z'.
Any tips?
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
bool again(string title); // Checks if you want to run again.
void makeUpper(char word[]);
void getReverse(char word[], char reversed[]);
char * find(char *str, char what);
bool equal(char word[], char reversed[]);
int size(char word[]);
char * cleanUp(char *str);
int main()
{
char word[256] = "Hello?? There!", reversedWord[256];
do
{
cout<<"Please enter the string to check: ";
makeUpper(word);
cout << word;
cleanUp(word);
getReverse(word,reversedWord);
if(equal(word, reversedWord))
cout<<"You have a palindrome!"<<endl;
else
cout<<"You do not have a palindrome!"<<endl;
} while(again("Do you want to do this again? "));
return 0;
}
bool again(string title)
{
string answer;
cout<<endl<<title;
getline(cin,answer);
return toupper(answer[0]) == 'Y';
}
void makeUpper(char word[])
{
char *ptr = word;
while (*ptr) {
*ptr = toupper(*ptr);
ptr++;
}
cout << "In uppercase:: " << word << endl;
}
char * cleanUp(char * astrid)
{
char *new_astrid;
for (*astrid; *astrid != '\0'; astrid++)
{
cout << "First loop";
if (isalpha(*astrid))
{
*new_astrid = *astrid;
new_astrid = ++new_astrid;
cout << "Here!";
}
}
cout << *new_astrid;
return *new_astrid;
}
void getReverse(char word[], char reversed[])
{
char *ptr_ind = find(word, '\0'), *ptr_ind_2 = reversed;
while(ptr_ind != word-1)
{
*ptr_ind_2 = *ptr_ind;
ptr_ind--;
ptr_ind_2++;
}
*ptr_ind_2 = '\0';
}
char * find(char *str, char what)
{
char *ptr = str;
while(*ptr != what && *ptr != '\0')
ptr++;
return *ptr == what ? ptr : NULL;
}
bool equal(char word[], char reverse[])
{
int total;
char * ptr;
ptr = word;
if((total = size(word)) != size(reverse))
return false;
for(char * ptr2 = reverse; *ptr != '\0' && *ptr == *ptr2; ptr++, ptr2++);
return *ptr == '\0';
}
int size(char word[])
{
int total = 0;
char * ptr = word;
while(*ptr != '\0') //while(!ptr)
{
ptr++;
total++;
}
return total;
}
There are several errors in your code.
new_astrid is not initialized and when you call *new_astrid = *astrid you try to copy a character to uninitialized memory, which will crash the program.
You also return the dereferenced pointer to new_astrid but the function prototype of cleanUp says that you return a pointer to char.
You should initialize new_astrid with new char[strlen(astrid)]. But then your code will result in memory leaks, since you increase the pointer (new_astid = ++new_astrid). So you should store the pointer first, so you can delete it later.
Instead of using raw pointers, i would suggest you use std::strings.
My suggestion for a palindrome tester would be:
#include <iostream>
#include <string>
#include <locale>
bool isPalindrome(std::string word)
{
std::locale loc;
for (std::string::size_type i = 0; i < word.length() / 2 + 1; ++i)
{
if (std::toupper(word[i],loc) != std::toupper(word[word.length() - i - 1],loc))
{
return false;
}
}
return true;
}
int main(int , char **)
{
std::string str = "Abba";
//Remove all non alpha values from string
str.erase(std::remove_if(str.begin(), str.end(), [](char const c){return !std::isalpha(c);}), str.end());
if (isPalindrome(str) == false)
{
std::cout << str << " is no palindrome" << std::endl;
}
else
{
std::cout << str << " is a palindrome" << std::endl;
}
return 0;
}
The erasion of non alpha values in the string is from this question.