What's wrong with my memcpy? - c++

I have written a function to implement memcpy
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
char *memcpy(char *dest,char *src,int n){
char *ch=dest;
while (n--)
*ch++=*src++;
return dest;
}
int main(){
char *src="georgia";
int n=strlen(src);
char *dest=new char[n];
std::cout<<*memcpy(dest,src,n)<<std::endl;
return 0;
}
But it only prints a single g. Why?

Because you're printing a single character.
std::cout<<*memcpy(dest,src,n)<<std::endl;
This dereferences the destination buffer (*memcpy) and therefore returns the first character of the string (which is g). You should be fine using this:
std::cout << memcpy(dest, src, n) << std::endl;
Other than that, it's still not gonna work: you need to include the terminating NULL character of your string in the copy, but strlen excludes it from the length of the string; so your buffer is missing 1 character. You need to add 1 to n to balance it, and everything should be fine.
int n = strlen(src) + 1;

Nothing wrong with the memcpy function but you have the * operation on the result. If we break the print line down it is...
char * result = memcpy(dest,src,n);
std::cout << *result << std::endl;
You really want...
std::cout << memcpy(dest,src,n) << std::endl;

Your memcpy() returns a pointer to char. In the line
std::cout<<*memcpy(dest,src,n)<<std::endl;
you dereference the pointer (you use operator*) so effectively you send one char (the one the return value points to) to the stream.
There is a bug in your code. strlen returns number of characters in the literal "georgia", but wihtout the terminating null character. You should increase n by one, to allocate appropriate storage for dest and to copy also the terminating null character.

You're dereferencing a char*, which is a char. This will be the first character, g.

Related

Are std::string with null-character possible?

I initialized a C++ string with a string literal and replaced a char with NULL.
When printed with cout << the full string is printed and the NULL char prints as blank.
When printed as c_str the string print stop at the NULL char as expected.
I'm a little confused. Does the action came from cout? or string?
int main(){
std::string a("ab0cd");
a[2] = '\0'; // '\0' is null char
std::cout << a << std::endl; // abcd
std::cout << a.c_str() << std::endl; // ab
}
Test it online.
I'm not sure whether the environment is related, anyway, I work with VSCode in Windows 10
First you can narrow down your program to the following:
#include <iostream>
#include <string>
int main(){
std::string a("ab0cd");
a[2] = '\0'; // replace '0' with '\0' (same result as NULL, just cleaner)
std::cout << a << "->" << a.c_str();
}
This prints
abcd->ab
That's because the length of a std::string is known. So it will print all of it's characters and not stop when encountering the null-character. The null-character '\0' (which is equivalent to the value of NULL [both have a value of 0, with different types]), is not printable, so you see only 4 characters. (But this depends on the terminal you use, some might print a placeholder instead)
A const char* represents (usually) a null-terminated string. So when printing a const char* it's length is not known and characters are printed until a null-character is encountered.
Contrary to what you seem to think, C++ string are not null terminated.
The difference in behavior came from the << operator overloads.
This code:
cout << a.c_str(); // a.c_str() is char*
As explained here, use the << overloads that came with cout, it print a char array C style and stop at the first null char. (the char array should be null terminated).
This code:
cout << a; // a is string
As explained here, use the << overloads that came with string, it print a string object that internally known is length and accept null char.
string end limit (boundary) is not 0 (NULL) like simple char* but its size keep internally in its member data as it's actually user-defined type (an instantiated object) as opposed to primitive type, so
int main(){
string a("abc0d");
a[3] = 0; // '\0' is null char
a.resize(2);
std::cout << a << std::endl; // ab
std::cout << a.c_str() << std::endl; // ab
}
i'm sorry change your code to be more comfortable, watch as it results in
ab
ab
good learning: http://www.cplusplus.com/reference/string/string/find/index.html

pointers *char and &char

I have doubt on below programme
#include "stdafx.h"
#include "stdio.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char *chr = "hello";
cout<<chr; //hello
cout<<endl;
cout<<*chr; //h
cout<<endl;
cout<<*(&chr); //hello
system("pause");
return 0;
}
why second cout prints h where as third one prints hello when represents the same
To be a little bit more explicit. chr is a pointer pointing to a chunk of memory where the characters 'h','e','l','l' and 'o' are stored. After the last character of chr is a terminating \0. This is needed to signal that the chunk pointed by chr is now over.
When passing chr to cout, cout will read (not cout it self but the underlying function wich is called by using the << operator) this chunk up to the terminating \0. When passing *chr to cout you dereference the pointer and simply pass the first character pointed by chr to cout ('h').
*(&chr) is the same thing as just chr because the adress-of operator gives you the adress of chr wich is a pointer to a pointer to character. Dereferencing it using * will then give you the pointer pointing to the chunk of memory starting with 'h' and coutwill again read up to the terminating \0.
EDIT
As birdypme pointed out correctly, the * operator (dereferencing operator) is the inverse to the address-of operator. It is like + and -. Therefore something like this
cout << *(&(*(&chr))) << endl;
will still be the same as
cout << chr << endl;
You can do this to infinity if you like to.
cout << *(&(*(&(*(&(*(&(*(&(*(&(*(&chr))))))))))))) << endl; // I hope i didn't miss a ')'
Because in the second case, you are passing to cout a single char, the one pointed by chr, that is the first of the C-string "hello".
In the second example you are dereferencing the pointer. This is the same as using chr[0] and in this case it is h.
In the last example you are taking the address of chr and then dereferencing:
&chr --> char**
*(&chr) --> char*
So at the and you again have a char*
Your statement
cout<<*chr; is same as cout<<chr[0];
because the pointer is dereferenced and passes only the first character pointed by chr
In case of cout<<*(&chr); , if i convert it into words, it would be, print the value present at the address of chr. Now since chris a pointer, you will get a pointer to a pointer by this statement &chrand the again you are dereferencing it, which gives you hello.

C++ pointer and array basics

Code:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
char testChar[] = {'a','b','c'};
char *testPointer = testChar ;
cout << testPointer << endl;
return 0;
}
Question:
When I use cout << mypointer,
Why does to print each letter of the array and the mess(refer to
output) at the end? My assumption is when I see out the pointer
points to the first letter prints then the second then etc and
prints the stuff at the end.
What is the mess (refer to output) at the end , the address?
Comments:
I know at the end of the array there's suppose to be a null pointer right?
I learnt this a year ago and forget please help me recall what is going on.
Output:
abc 310 367 277_ 377
Program ended with exit code: 0
When printing out a string (or char array in your case), it must be terminated by a null character \0, otherwise cout will continue to print out characters located in memory past the intended string until it either hits a null character, or it accesses memory it is not allowed to read from which results in a segmentation fault.
That "mess" at the end that is being printed are the values located in the memory locations immediately past the char array.
Also after initializing char testChar[] = "abc"; you actually don't need 'char *testPointer = testChar' statement since testChar is itself an address to the first element of the array. So cout << testChar << endl;will do.

snprintf of unsigned long appending a comma

I try to convert a unsigned long into a character string, appending a comma at the end of the it. When compiling and running the test code you can find below, I get the following output:
"1234," "1234"
"1234"
The test code is:
#include <cstdio>
#include <iostream>
int main () {
unsigned long c = 1234;
char ch[50];
char ch1[50];
sprintf(ch, "%lu,", c);
std::cout << "\"" << ch << "\"" << " \"" << c << "\"" << std::endl;
snprintf(ch1, 5, "%s", ch);
std::cout << "\"" << ch1 << "\"" << std::endl;
return 1;
}
As far as I understand, ch should be of length 5, 4 digits plus 1 for the comma.
Do I miss an extra plus one for the termination character?
Cheers!
The size that is passed to snprintf includes the terminating null character. Although it is not printed, it still takes space in the buffer.
You should pass strlen(ch) + 1 instead. Or even better, just sizeof(ch1) will suffice since you want to accommodate the entire result before filling the buffer.
Also make sure that the destination buffer is always of a sufficient size, equal to or greater than the size you pass to snprintf. In your particular case it can hardly happen, but in general you should keep that in mind.
From the Linux manual page:
The functions snprintf() and vsnprintf() write at most size bytes (including the trailing null byte ('\0')) to str.
So yes, you should have a length of 6 to get the comma as well.
The C++ way:
#include <string>
unsigned long int c = 1234;
std::string s = "\"" + std::to_string(c) + ",\"";
std::string t = '"' + std::to_string(c) + ',' + '"'; // alternative
As you wrote, you miss an extra space for the termination character.
The functions snprintf() and vsnprintf() write at most size bytes
(including the terminating null byte ('\0')) to str.
As several people has pointed out, you need to include enough space for the null terminator.
It's always worth checking the result returned from snprintf is what you think it should be, as well.
Lastly, I'd recommend using snprintf(buffer, sizeof(buffer), etc, etc)
Your less likely to get embarrassing results if the 2nd parameter happens to be larger than the actual space you've got available.

how to print char array in c++

how can i print a char array such i initialize and then concatenate to another char array? Please see code below
int main () {
char dest[1020];
char source[7]="baby";
cout <<"source: " <<source <<endl;
cout <<"return value: "<<strcat(dest, source) <<endl;
cout << "pointer pass: "<<dest <<endl;
return 0;
}
this is the output
source: baby
return value: v����baby
pointer pass: v����baby
basically i would like to see the output print
source: baby
return value: baby
pointer pass: baby
You haven't initialized dest
char dest[1020] = ""; //should fix it
You were just lucky that it so happened that the 6th (random) value in dest was 0. If it was the 1000th character, your return value would be much longer. If it were greater than 1024 then you'd get undefined behavior.
Strings as char arrays must be delimited with 0. Otherwise there's no telling where they end. You could alternatively say that the string ends at its zeroth character by explicitly setting it to 0;
char dest[1020];
dest[0] = 0;
Or you could initialize your whole array with 0's
char dest[1024] = {};
And since your question is tagged C++ I cannot but note that in C++ we use std::strings which save you from a lot of headache. Operator + can be used to concatenate two std::strings
Don't use char[]. If you write:
std::string dest;
std::string source( "baby" )
// ...
dest += source;
, you'll have no problems. (In fact, your problem is due to the fact
that strcat requires a '\0' terminated string as its first argument,
and you're giving it random data. Which is undefined behavior.)
your dest array isn't initialized. so strcat tries to append source to the end of dest wich is determined by a trailing '\0' character, but it's undefined where an uninitialized array might end... (if it does at all...)
so you end up printing more or less random characters until accidentially a '\0' character occurs...
Try this
#include <iostream>
using namespace std;
int main()
{
char dest[1020];
memset (dest, 0, sizeof(dest));
char source[7] = "baby";
cout << "Source: " << source << endl;
cout << "return value: " << strcat_s(dest, source) << endl;
cout << "pointer pass: " << dest << endl;
getchar();
return 0;
}
Did using VS 2010 Express.
clear memory using memset as soon as you declare dest, it's more secure. Also if you are using VC++, use strcat_s() instead of strcat().