Trying to copy strings without last characters using memcpy - c++

Newbie quetion here.
So i have a const char* and need to copy it to a char* without the last two character.
I already tried to use strncpy but i'm using c++ in vs and says it is deprectated.
I cannot use std::string.
Using memcpy prints me trash. I want to print adress but it prints me adress²²²²Üw
I will put my code here:
#include <cstring>
#include <iostream>
#include <stdio.h>
int main()
{
const char* ident = "adress.P";
char* tm_name;
if( (tm_name = (char*)malloc(sizeof(char) * (strlen(ident) - 2))) != NULL)
memcpy( tm_name, ident, strlen(ident) - 2);
printf("tm_name = %s", tm_name);
return 0;
}
best regards,
Guilherme Gil

i did not put '\0' xD
thx guys!
Now the code looks like this:
#include <cstring>
#include <iostream>
#include <stdio.h>
int main()
{
const char* ident = "adress.P";
char* tm_name;
int ident_size = strlen(ident);
if ((tm_name = (char*)malloc(sizeof(char) * (ident_size - 1))) != NULL) {
memcpy(tm_name, ident, ident_size - 1);
tm_name[ident_size - 2] = '\0';
}
printf("tm_name : %s , size = %d", tm_name, strlen(tm_name));
return 0;
}
And the output is:
tm_name : adress , size = 6
Thanks again!

Related

Trying to print a map in CPP with LIBCACA

I'm trying to display a simple map using the caca_put_str() / caca_printf() function except that it doesn't interpret the '\n' correctly. Any tips to share to fix this? The documentation is quite empty btw...
Thanks in advance !
Here is the code :
#include <string>
#include <caca.h>
#include <iostream>
#include <fstream>
caca_canvas_t *cv;
static std::string readFile(const std::string &file)
{
std::ifstream buffer(file);
std::string str;
if (buffer.is_open())
{
std::getline(buffer, str, '\0');
buffer.close();
return (str);
}
return (NULL);
}
int main(void)
{
std::string map = readFile("arcade.txt");
caca_display_t *dp;
caca_event_t event;
int width = 1080;
int height = 980;
cv = caca_create_canvas(width, height);
dp = caca_create_display(cv);
if (!dp)
std::exit(1);
caca_set_display_title(dp, "Windows");
while (true)
{
caca_refresh_display(dp);
caca_put_str(cv, 0, 0, map.c_str();
}
caca_free_canvas(cv);
caca_free_display(dp);
}
I'm trying to print this :
############################
#............##............#
#.####.#####.##.#####.####.#
#.####.#####.##.#####.####.#
#..........................#
#.####.##.########.##.####.#
#......##....##....##......#
######.#####.##.#####.######
#....#.##..........##.#....#
#....#.##.###--###.##.#....#
######.##.#......#.##.######
..........#......#..........
######.##.#......#.##.######
#....#.##.########.##.#....#
#....#.##..........##.#....#
######.##.########M##.######
#............##............#
#.####.#####.##.#####.####.#
#...##................##...#
###.##.##.########.##.##.###
#......##....##....##......#
#.##########.##.##########.#
But it is displayed on a single line.

Using Strftime to format DateTime

I am working on a function to format the input timestamp to the input format.
std::string 1stformat = "dd - MM - yyyy HH 'Hours' mm 'Minutes' ss 'Seconds' SSS 'Miliseconds –' a '– Time Zone: ' Z '-' zzzz";//will not print anything
std::string 2ndformat = "'This took about' h 'minutes and' s 'seconds.'";//will print out
After format
char date_string[100];
strftime(date_string, 50, format.c_str(), curr_tm);
My problem is that there will be sometimes the input format too long which made the buffer date_string not enough to content. I am just getting into C++ for the past 3 weeks so I don't have much ex about this.
A wrapper for strftime() that grows a buffer as needed until it's big enough to fit the desired time string:
#include <ctime>
#include <iostream>
#include <memory>
#include <string>
std::string safe_strftime(const char *fmt, const std::tm *t) {
std::size_t len = 10; // Adjust initial length as desired. Maybe based on the length of fmt?
auto buff = std::make_unique<char[]>(len);
while (std::strftime(buff.get(), len, fmt, t) == 0) {
len *= 2;
buff = std::make_unique<char[]>(len);
}
return std::string{buff.get()};
}
int main() {
std::time_t now;
std::time(&now);
std::cout << safe_strftime("The date is %Y-%m-%d", std::localtime(&now))
<< '\n';
return 0;
}
Unfortunately, the interface to std::strftime() is less helpful than that of std::snprintf() in that it returns 0 if the buffer is too small, rather than the number of characters that would be written. We need to increase the buffer size heuristically and retry, perhaps like this:
#include <ctime>
#include <string>
#include <vector>
std::string time_to_string(const char *format, const std::tm* time)
{
// first try with an on-stack buffer (fast path)
char buf[200];
auto written = std::strftime(buf, sizeof buf, format, time);
if (written > 0) {
return buf;
}
// now, iterate with an allocated buffer
auto len = sizeof buf;
std::vector<char> v;
do {
v.resize(len *= 2);
written = std::strftime(v.data(), v.size(), format, time);
} while (written == 0);
return {v.data(), written};
}

Linux File Read and Write - C++

I supposed to create a program that reads source.txt's first 100 characters, write them in destination1.txt, and replace all "2" to "S" and write them to destination2.txt. Below is my code
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdio>
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]){
argv[0] = "source.txt";
argv[1] = "destination1.txt";
argv[2] = "destination2.txt";
int count=100;
char buff[125];
int fid1 = open(argv[0],O_RDWR);
read(fid1,buff,count);
close(fid1);
int fid2 = open(argv[1],O_RDWR);
write(fid2,buff,count);
close(fid2);
//How to change the characters?
return 0;
}
Thanks guys I am able to do the copying. But how to perform the character replacement? If it's fstream I know how to do it with a for loop. But I'm supposed to use Linux system calls.
Define an array out_buf and copy buff into out_buf character by character, replacing 2's to S.
...
read(fid1,buff,count);
close(fid1);
char out_buf [125];
int i;
for (i = 0; i < sizeof (buf); i++) {
if (buff [i] == '2')
out_buf [i] = 'S'
else
out_buf [i] = buff [i]
}
int fid2 = open(argv[1],O_RDWR);
write(fid2, out_buf,count);
close(fid2);
return 0;
You should replace the filename assignments to something like this:
const std::string source_filename = "source.txt";
const std::string dest1_filename = "destination1.txt";
const std::string dest2_filename = "destination2.txt";
There is no guarantee that the OS will allocate 3 variables to your program.

Possible memory leak in string memory allocation

This is my code:
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>
std::string & fileread(const char * name)
{
FILE *fp = fopen(name,"rb");
size_t sz;
int i;
char *buff;
fseek(fp, 0, SEEK_END);
sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
buff = (char *)malloc(sizeof(char)*(sz+1));
buff[sz] = '\0';
fread(buff,sz,1,fp);
std::string * rtstr = new std::string(buff);
free(buff);
fclose(fp);
return * rtstr;
}
int main(int argc,char * argv[])
{
std::string file_info(fileread(argv[1]));
std::cout<<file_info << std::endl;
return 0;
}
It is simply read one file, and print its content to screen.
In the function fileread, I use new std::string(buff); to get a std::string *, and return the point back. Will it cause memory leak? And if the answer is 'yes' , how to avoid it?
About use C in C++: fread is much faster than ifstream (tested with 1 billion random number)
My problem is about memory leak.
Return std::string by value. Don't worry, C++ will take care of not copying the object redundantly (unless you have a very old compiler).
Here is the code, fixed:
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>
std::string fileread(const char * name)
{
FILE *fp = fopen(name,"rb");
size_t sz;
int i;
char *buff;
fseek(fp, 0, SEEK_END);
sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
buff = (char *)malloc(sizeof(char)*(sz+1));
buff[sz] = '\0';
fread(buff,sz,1,fp);
std::string rtstr(buff);
free(buff);
fclose(fp);
return * rtstr;
}
int main(int argc,char * argv[])
{
std::string file_info(fileread(argv[1]));
std::cout<<file_info << std::endl;
return 0;
}
I made only the small change necessary and ignored any other problems you might have in your code. Take care.
As Nawaz rightly commented: "DONT code C in C++. Use std::ifstream and std::string (not std::string*)". Here is the code in C++ to avoid all the issues:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("myfile.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}

c++ mcrypt error at mcrypt_generic

I have the following code:
[test.cpp]
#include <mcrypt.h>
#include <string>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
char algo[] = "rijndael-256";
char mode[] = "cbc";
char *block_buffer=(char*)"HELLO!! MY NAME IS: ";
cout<<"here"<<endl;
string s;
char key="1234-5678-9654-7512-7895-2543-12";
char iv[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};;
MCRYPT td = mcrypt_module_open(algo, NULL, mode, NULL);
if (td == MCRYPT_FAILED) { cout<<"error"<<endl;}
int keysize=32;
int r = mcrypt_generic_init(td, key, keysize, iv);
if (r<0)
{
cout<<"error2"<<endl;
mcrypt_perror(r);
return 1;
}
//while ( fread (&block_buffer, 1, 1, stdin) == 1 ) {
int j= mcrypt_generic (td, &block_buffer, sizeof(block_buffer));
if (j!=0){std::cout<<"error encrypting"<<std::endl;} // I HAVE ERROR HERE J==0
//how to print the encrypted string??
cout<<"buffer "<<block_buffer<<endl; //this is not the encriperd string. why?
mcrypt_generic_deinit(td);
mcrypt_module_close(td);
}
I am testing the code:
$: g++ test.cpp -o tst -lmcrypt
$: ./tst
WHERE SHOULT I ADD THE PKCS 7?
I have the following method:
std::string add_pkcs7_padding(std::string s, std::size_t n)
{
const std::size_t fill = n - (s.length() % n);
s.append(fill, static_cast<char>(fill));
return s;
}
std::string strip_pkcs7_padding(std::string s, std::size_t n)
{
const std::size_t pad = static_cast<unsigned char>(*s.rbegin());
return s.substr(0, s.length() - pad);
}
I din't know when should i run it and where in my code.
NEED SOME HELP. APPRECIATE A LOT!!
EDIT:
I have error at: mcrypt_generic (td, &block_buffer, sizeof(block_buffer)); The compiler prints
that the value j=0;
You should invoke mcrypt_generic() with a char*, not a char** as you do:
mcrypt_generic(td, block_buffer, sizeof(block_buffer));
^^^ ^^^^^^^^^^^^^^^^^^^^
ouch!
Also, the length is wrong, as sizeof(block_buffer) is just be the size of the pointer, not the string; if anything you need strlen(block_buffer).
But this is still going to be wrong in general because you need your message to be a multiple of the block size. Use the padding function:
std::string s = add_pkcs7_padding(block_buffer, mcrypt_enc_get_block_size(td));
std::vector<char> v(s.begin(), s.end()); // this will hold the encrypted data
mcrypt_generic(td, v.data(), v.size());
By the way, your plaintext should be declared like this:
const char * block_buffer = "HELLO!! MY NAME IS: ";
^^^^^ ^^^^
constness! no explicit cast!
But why so clumsy, it's better to just use a string:
std::string plaintext = "HELLO!! MY NAME IS: ";
I think you might benefit from picking up a good C++ book and familiarizing yourself with the basics of the language a bit - it's good to have a project to work on, but most of your problems aren't really related to encryption or mcrypt, but just general C++ programming.