Copy and reverse char* in the C++ - c++

I would like to copy reversed char* to the another char*. I miss one letter in the second line of the output.
I did:
#include <iostream>
using namespace std;
void cp(char *str2, char *str1){
char *pom1 = str1;
while(*pom1){
pom1++;
}
char* pom2 = str2;
while(*pom1 != *str1){
pom1--;
*pom2 = *pom1;
pom2++;
}
*pom2 = '\0';
}
int main()
{
char *str1 = "ppC", str2[10] = "Witaj";
cout << "Napis str2 "<< str2 << endl;
cp(str2,str1);
cout << "Napis str2 "<< str2 << endl;
cp(str2,"CJP");
cout << "Napis str2 "<< str2 << endl;
return 0;
}
and the output is:
Napis str2 Witaj
Napis str2 Cp
Napis str2 PJC
While it should be:
Napis str2 Witaj
Napis str2 Cpp
Napis str2 PJC

The bug is in this statement of the function
while(*pom1 != *str1){
There must be
while( pom1 != str1){
Take into account that string literals have type of constant arrays. So for example variable str1 has to be declared as
const char *str1 = "ppC";
Also the function should be declared as
void cp( char *str2, const char *str1 );
Also It will be useful to know that there is standard algorithm std::reverse_copy declared in header <algorithm>:)

There's reverse_copy in the stdlib
... and that it's used like:
template <typename CharT, size_t Ndest>
void cp(CharT (&dest)[Ndest], CharT const *src){
auto f = src, l = src + std::strlen(src);
assert(std::distance(f,l) < Ndest);
*(std::reverse_copy(f, l, dest)) = '\0';
}
So, see it Live On Coliru
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cassert>
template <typename CharT, size_t Ndest>
void cp(CharT (&dest)[Ndest], CharT const *src){
auto f = src, l = src + std::strlen(src);
assert(std::distance(f,l) < Ndest);
*(std::reverse_copy(f, l, dest)) = '\0';
}
#include <iostream>
int main()
{
char str1[] = "ppC";
char str2[10] = "Witaj";
std::cout << "Napis str2 "<< str2 << std::endl;
cp(str2, str1);
std::cout << "Napis str2 "<< str2 << std::endl;
cp(str2,"CJP");
std::cout << "Napis str2 "<< str2 << std::endl;
return 0;
}

Just use the Standard Library, std::reverse_copy() in this case:
std::reverse_copy( input , input + strlen( input ) , output );

copy paste solution
int len(const char *p) {
int c = 0;
while (*p != '\0')
{
c++;
p++;
}
return(c);
}
void cp(char *str2, const char *str1){
if(!(len(str2)<len(str1))){
const char *pom1 = str1;
while(*pom1){
pom1++;
}
char* pom2 = str2;
while( pom1 != str1){
pom1--;
*pom2 = *pom1;
pom2++;
}
*pom2 = '\0';
}
}

Related

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

C++ XOR failing when reaching null byte?

Here is the code I have right now:
#include <iostream>
#include <string>
#include <sstream>
std::string string_to_hex(const std::string& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
std::string encrypt(std::string msg, std::string key)
{
// Make sure the key is at least as long as the message
std::string tmp(key);
while (key.size() < msg.size())
key += tmp;
// And now for the encryption part
for (std::string::size_type i = 0; i < msg.size(); ++i)
msg[i] ^= key[i];
return msg;
}
std::string decrypt(std::string msg, std::string key)
{
return encrypt(msg, key); // lol
}
int main()
{
std::cout << string_to_hex(encrypt("Hello World!", "monkey")) << std::endl;
std::cout << decrypt("\x25\x0A\x02\x07\x0A\x59\x3A\x00\x1C\x07\x01\x58", "monkey") << std::endl;
std::cout << string_to_hex(encrypt("Hello. This is a test of encrypting strings in C++.", "monkey")) << std::endl;
std::cout << decrypt("\x25\x0A\x02\x07\x0A\x57\x4D\x3B\x06\x02\x16\x59\x04\x1C\x4E\x0A\x45\x0D\x08\x1C\x1A\x4B\x0A\x1F\x4D\x0A\x00\x08\x17\x00\x1D\x1B\x07\x05\x02\x59\x1E\x1B\x1C\x02\x0B\x1E\x1E\x4F\x07\x05\x45\x3A\x46\x44\x40", "monkey") << std::endl;
}
The output is the following:
250A02070A593A001C070158
Hello W
250A02070A574D3B06021659041C4E0A450D081C1A4B0A1F4D0A000817001D1B070502591E1B1C020B1E1E4F0705453A464440
Hello. This is a test of e
The decryption seems to stop when reaching a \x00. Does anyone have any ideas on how to fix or get around that?
Thanks!
The std::string constructor that takes in a char* assumes that the input is a null-terminated string, so even though your string literal has lots of data in it past the null byte, when you pass it into your function the std::string constructor will stop reading as soon as it hits that null byte.
You have a couple of options to fix this. As one option, the std::string type has a two-argument constructor where you can give a pointer to the first element in the string and the past-the-end byte of the string. The std::string will then initialize itself to the text in that range, ignoring intermediary null terminators.
char s1[] = "\x25\x0A\x02\x07\x0A\x59\x3A\x00\x1C\x07\x01\x58";
char s2[] = "\x25\x0A\x02\x07\x0A\x57\x4D\x3B\x06\x02\x16\x59\x04\x1C\x4E\x0A\x45\x0D\x08\x1C\x1A\x4B\x0A\x1F\x4D\x0A\x00\x08\x17\x00\x1D\x1B\x07\x05\x02\x59\x1E\x1B\x1C\x02\x0B\x1E\x1E\x4F\x07\x05\x45\x3A\x46\x44\x40";
std::cout << string_to_hex(encrypt("Hello World!", "monkey")) << std::endl;
std::cout << decrypt(std::string(std::begin(s1), std::end(s1)-1), "monkey") << std::endl;
std::cout << string_to_hex(encrypt("Hello. This is a test of encrypting strings in C++.", "monkey")) << std::endl;
std::cout << decrypt(std::string(std::begin(s2), std::end(s2)-1), "monkey") << std::endl;
Demo.

Printing all Blanks (literally no tokens are printed)

Basically my code doesn't print the tokens. It just prints blanks. What am I doing wrong?
I've consulted many other guides on this issue and I can't seem to understand what I'm doing wrong.
Thanks.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stack>
#include <stdexcept>
#include <string>
#include <stdlib.h>
#include <cstring>
using namespace std;
int main() {
stack<double> s;
string str = "";
getline(cin, str);
char *cstr = new char [str.length()+1];
strcpy(cstr, str.c_str());
char* strp = strtok(cstr, " ");
while (strp != 0){
double n = strtod(cstr, &strp);
s.push(n);
cout << strp << endl;
strp = strtok(0," ");
}
return 0;
}
This code works for me:
int main()
{
stack<double> s;
string str = "";
getline(cin, str);
char *cstr = new char [str.length()+1];
strcpy(cstr, str.c_str());
char* strp = strtok(cstr, " ");
while (strp != NULL)
{
double n = strtod(strp, NULL);
s.push(n);
cout << n << endl;
strp = strtok(NULL, " ");
}
return 0;
}
But hell, this really is a painfull mix of C and C++. You should get rid of those strcpy, strtok and strod functions. Use istringstream instead.

C++ convert int into string? [duplicate]

This question already has answers here:
How to convert a number to string and vice versa in C++
(5 answers)
Closed 8 years ago.
I tried to convert int into a string , but it doesn't work I dont know why...
here my Code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <array>
using namespace std;
int main()
{
struct Studentendaten {
int matrnr;
string name;
string vorname;
string datum;
float note;
};
Studentendaten stud;
array<Studentendaten,100> studArray ;
FILE * pFile;
int ch;
int mnr;
string sub;
string sub1;
string sub2;
string sub3;
string sub4;
string sub5;
int i = 0;
int pos ;
pFile=fopen("studentendaten.txt","r");
if (pFile==nullptr)
{
perror ("Fehler beim öffnen der Datei");
}
else
{
while (ch != EOF)
{
ch = fgetc(pFile);
sub += (char)(ch);
pos = sub.find(";");
if (pos != -1)
{
sub1 = sub.substr(0,pos);
sub2 = sub.substr(pos+1,pos);
sub3 = sub.substr(pos+1,pos);
sub4 =sub.substr(pos+1,pos);
sub5 =sub.substr(pos+1,pos);
mnr =stoi(sub1);
stud.matrnr = mnr;
stud.name = sub2;
stud.vorname = sub3;
stud.datum = sub4
stud.note = float(sub5);
}
if (ch == '\n')
{
stud = {matrn,name,vorname,datum,note};
studArray.[i] = stud;
i++;
}
putchar(ch);
}
fclose (pFile);
}
return 0;
}
I tried int mnr =stoi(sub1);
as well as int mnr = atoi(sub1);
where sub1 = "029383214" something like that.... why does it not work? Compiler complains...
Simply use a std::stringstream:
int parse_int( const std::string& str )
{
std::stringstream ss( str );
int value;
if( ss >> value )
return value;
else
throw;
}
You can use stringstream:
#include <sstream>
...
// int to string
int intVar = 10;
std::stringstream out;
out << intVar;
std::string converted = out.str();
// string to int
std::string src = "555";
std::stringstream in(str);
int result = 0;
in >> result;
And check boost::lexical_cast as well.
Use std::to_string(int).
Reference.
You can use std::to_string for simple cases or std::stringstream when you need more control over formatting (zero padding, hexadecimal etc.)
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
int main(int argc, const char * argv[]) {
int value = 19;
cout << to_string( value ) << endl;
stringstream s1, s2;
s1 << setfill('0') << setw(4) << value;
s2 << "0x" << hex << setfill('0') << setw( 8 ) << value;
cout << s1.str() << endl << s2.str() << endl;
}
I would rather use boost::lexical_cast if I were on your place
string stringValue = lexical_cast<string>(101);
int intValue = lexical_cast<int>("101");
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_lexical_cast.html

What is the proper way to create a temporary char* and print to it?

I have a helper function that takes an unsigned char array of a fixed length, and returns it as a formatted char *. However, I'm having some problems.
I tried
char* byteArrayToString(unsigned char byte[6]) {
char t[18] = {""};
char* str = t;
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return str;
}
and
char* byteArrayToString(unsigned char byte[6]) {
std::string t = "";
char* str = t;
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return str;
}
and
char* byteArrayToString(unsigned char byte[6]) {
char* str = new char();
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return str;
}
The second one results in some side effects of the value of that string being changed. The first one ends up giving me junk values and the last seg faults (but I can't figure out why).
The problem with your first one is not in the printing, but in the returning. You're returning a pointer to an array which has been reclaimed (because it is an automatic variable, its lifetime ends when the function returns).
Instead try:
string byteArrayToString(const unsigned char* const byte)
{
char t[18] = {""};
sprintf(t, "%02X:%02X:%02X:%02X:%02X:%02X", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5]);
return t;
}
Proper way is to return std::string as:
#include <sstream> //for std::ostringstream
#include <string> //for std::string
#include <iomanip> //for std::setw, std::setfill
std::string byteArrayToString(unsigned char byte[6])
{
std::ostringstream ss;
for(size_t i = 0 ; i < 5 ; ++i)
ss << "0X" << std::hex << std::setw(2) << std::setfill('0') << (int) byte[i] << ":";
ss << "0X" << std::hex << std::setw(2) << std::setfill('0') << (int) byte[5];
return ss.str();
}
Online demo
On the callsite you can get const char* as:
std::string s = byteArrayToString(bytes);
const char *str = s.c_str();