Meaning of this line of code in C++ - c++

I'm just started to pick up C and I am working on using the RSA cipher in my code. However, this line of code confuses me. Credits go to the author from this site here.
char* intmsg = new char[strlen(msg)*3 + 1];
This is the method which the line can be found.
inline void encrypt(char* msg,FILE* fout)
{
/* This function actually does the encrypting of each message */
unsigned int i;
int tmp;
char tmps[4];
char* intmsg = new char[strlen(msg)*3 + 1];
/* Here, (mpz_t) M is the messsage in gmp integer
* and (mpz_t) c is the cipher in gmp integer */
char ciphertext[1000];
strcpy(intmsg,"");
for(i=0;i<strlen(msg);i++)
{
tmp = (int)msg[i];
/* print it in a 3 character wide format */
sprintf(tmps,"%03d",tmp);
strcat(intmsg,tmps);
}
mpz_set_str(M,intmsg,10);
/* free memory claimed by intmsg */
delete [] intmsg;
/* c = M^e(mod n) */
mpz_powm(c,M,e,n);
/* get the string representation of the cipher */
mpz_get_str(ciphertext,10,c);
/* write the ciphertext to the output file */
fprintf(fout,"%s\n",ciphertext);
}

That code line isn't actually C, it's C++.
char* intmsg = new char[strlen(msg)*3 + 1];
Means to dynamically allocate a block of memory with room for the given number of chars, 3 times bigger + 1 than the original length of the msg string.
The C equivialent would be
char* intmsg = malloc(strlen(msg)*3 + 1);
To deallocate that memory block, delete []intmsg is used in C++, while if you used malloc in C, you'd do free(intmsg);

It creates an array of character which is 3 times larger than the list of characters stored in msg plus one character to store the string ending character '\0'.
More info on the C++ operator new[] here

Its a line of C++, and its dynamically allocating an array of chars 3 times the length of string "msg" + 1 more (for the null terminator)

This is C++ and the code allocates an array of char, the size of which is 3 times the length of the messages, plus one. The resulting pointer is assigned to intmsg.
Why does it do that? Because the message is converted, character by character, to a three digit per character decimal number in the loop with the sprintf(tmps,"%03d",tmp);.

It's c++ code :
char* intmsg = new char[strlen(msg)*3 + 1];
This tells the compiler to create memory for intmsg on heap of length of memory block ie equal to "one more than the 3 times of length of the msg".
means After the execution of this line intmsg started pointing to the block of memory on heap.

Related

C++ MPI - Scatter array of strings

I need to Scatter my string array. The problem is, I'm not sure, how to do it correctly, I'm used to it only in C.
My program has the array scatterArr which contains several strings (one for every process, so this number is changing). String length is changing too - my program loads text from a file, so, it depends on the word count.
Example of scatterArr (just for this example I assigned strings manually):
int world_size = 4; // number of processes
string * scatterArr = new string[world_size];
scatterArr[0] = "Hello;How;";
scatterArr[1] = "I;are;";
scatterArr[2] = "am;you;";
scatterArr[3] = "John;"; // only one word loaded
And now Scatter():
int arrCharCount = 21;
char * recvArr = new char[ ??? ]; // I'm not sure what size to expect
COMM_WORLD.Scatter( scatterArr, arrCharCount, CHAR, recvArr, ???, CHAR, 0 );
Here I'm not sure about using char * as a recvArr type (maybe string would be better?) and about the size I should allocate for my recvArr array.
So, could you please help me with this and explain it, if possible, more thoroughly? I've found this question, but I've not understood, how can I determine the size of recvArr when I don't know the exact number of CHARS which will come.

Weird characters when trying to grab char * from fstream

I am trying to read 4 characters at a specific position from a file. The code is simple but the result is really confusing:
fstream dicomFile;
dicomFile.open(argv[1]);
dicomFile.seekg(128,ios::beg);
char * memblock = new char [4];
dicomFile.read(memblock,4);
cout<<"header is "<<memblock<<endl;
Ideally the result should be "DICM" but the actual result from the console was "DICM" plus weird characters, as shown in the picture. What's more, every time I run it, the characters are different. I suppose this may be something about ASCII and Unicode, I tried to change project property from Unicode to multibytes and then change back, no difference.
Does anyone know what's happening here and how do I solve it please? Thanks very much!
C style (char *) strings use the concept of null-terminators. This means strings are ended with a '\0' character in their last element. You are reading in exactly 4 characters into a 4 character buffer, which does not include a null character to end the string. C and C++ will happily run right off the end of your buffer in search for the null terminator that signifies the end of the string.
Quick fix is to create a block of length + 1, read in length data, then set str[length] = '\0'. In your case it would be as below.
char * memBlock = new char [5];
// populate memBlock with 4 characters
memBlock[ 4 ] = '\0';
A better solution is to use std::string instead of char * when working with strings in C++.
You could also initialize the buffer with zeros, putting null-terminators at every location.
char * memblock = new char [5](); // zeros, and one element longer
Fairly inefficient though.

My program is giving different output on different machines..!

#include<iostream>
#include<string.h>
#include<stdio.h>
int main()
{
char left[4];
for(int i=0; i<4; i++)
{
left[i]='0';
}
char str[10];
gets(str);
strcat(left,str);
puts(left);
return 0;
}
for any input it should concatenate 0000 with that string, but on one pc it's showing a diamond sign between "0000" and the input string...!
You append a possible nine (or more, gets have no bounds checking) character string to a three character string (which contains four character and no string terminator). No string termination at all. So when you print using puts it will continue to print until it finds a string termination character, which may be anywhere in memory. This is, in short, a school-book example of buffer overflow, and buffer overflows usually leads to undefined behavior which is what you're seeing.
In C and C++ all C-style strings must be terminated. They are terminated by a special character: '\0' (or plain ASCII zero). You also need to provide enough space for destination string in your strcat call.
Proper, working program:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
/* Size is 4 + 10 + 1, the last +1 for the string terminator */
char left[15] = "0000";
/* The initialization above sets the four first characters to '0'
* and properly terminates it by adding the (invisible) '\0' terminator
* which is included in the literal string.
*/
/* Space for ten characters, plus terminator */
char str[11];
/* Read string from user, with bounds-checking.
* Also check that something was truly read, as `fgets` returns
* `NULL` on error or other failure to read.
*/
if (fgets(str, sizeof(str), stdin) == NULL)
{
/* There might be an error */
if (ferror(stdin))
printf("Error reading input: %s\n", strerror(errno));
return 1;
}
/* Unfortunately `fgets` may leave the newline in the input string
* so we have to remove it.
* This is done by changing the newline to the string terminator.
*
* First check that the newline really is there though. This is done
* by first making sure there is something in the string (using `strlen`)
* and then to check if the last character is a newline. The use of `-1`
* is because strings like arrays starts their indexing at zero.
*/
if (strlen(str) > 0 && str[strlen(str) - 1] == '\n')
str[strlen(str) - 1] = '\0';
/* Here we know that `left` is currently four characters, and that `str`
* is at most ten characters (not including zero terminaton). Since the
* total length allocated for `left` is 15, we know that there is enough
* space in `left` to have `str` added to it.
*/
strcat(left, str);
/* Print the string */
printf("%s\n", left);
return 0;
}
There are two problems in the code.
First, left is not nul-terminated, so strcat will end up looking beyond the end of the array for the appropriate place to append characters. Put a '\0' at the end of the array.
Second, left is not large enough to hold the result of the call to strcat. There has to be enough room for the resulting string, including the nul terminator. So the size of left should at least 4 + 9, to allow for the three characters (plus nul terminator) that left starts out with, and 9 characters coming from str (assuming that gets hasn't caused an overflow).
Each of these errors results in undefined behavior, which accounts for the different results on different platforms.
I do not know why you are bothering to include <iostream> as you aren't using any C++ features in your code. Your entire program would be much shorter if you had:
#include <iostream>
#include <string>
int main()
{
std::string line;
std::cin >> line;
std::cout << "You entered: " << line;
return 0;
}
Since std::string is going to be null-terminated, there is no reason to force it to be 4-null-terminated.
Problem #1 - not a legal string:
char left[4];
for(int i=0; i<4; i++)
{
left[i]='0';
}
String must end with a zero char, '\0' not '0'.
This causes what you describe.
Problem #2 - fgets. You use it on a small buffer. Very dangerous.
Problem #3 - strcat. Yet again trying to fill a super small buffer which should have already been full with an extra string.
This code looks an invitation to a buffer overflow attack.
In C what we call a string is a null terminated character array.All the functions in the string.h library are based on this null at the end of the character array.Your character array is not null terminated and thus is not a string , So you can not use the string library function strcat here.

Resizing character array in c

A MFC coder want to learn some basic about character array intialisation and deletion of element.Take following examples compare with MFC (there is CString so no need of memory allocation or de allocation but same needed in c.)
(don't have std::string interface )
Example 1:-
To construct string we us following code in MFC.
CString constructString;
constructString = "";
constructString = "ABC";
constructString = constructString + "PQR";
constructString = constructString + "LMN";
whatever size of string we have this will work.
for C i used following code
#define DEFAULT_ARRAY_SIZE 20000
char* constructString = new char[DEFAULT_ARRAY_SIZE];
strcpy(constructString ,"");
strcat(constructString ,"ABC");
strcat(constructString ,"PQR");
strcat(constructString ,"LMN");
Problem :-
1)Code will work fine till my char* constructString size is less than 20000 but when it exceed i dont have solution,how to resize my array so it will take more charecters.
2)I intialize char* constructString with 20000 but when my string is very small of size 10 then my remaining 18990 charecters are wasted or not i dont know,will this effect my executable perfomance.If yes then how to delete my remaining dummy charecters.
Example 2:-
To read content from file we use following code in MFC.
CStdioFile ReadFile;
ReadFile.Open("Sample.txt",CFile::typeText|CFile::Read);
CString CurrentString;
CStringArray WholeFile;
while(ReadFile.ReadString(CurrentString))
{
WholeFile.Add(CurrentString);
}
Whitever size of File it will work fine.
For C i use following code
#define MAX_FILE_SIZE 65534
FILE *ptr_file;
const char* list[MAX_FILE_SIZE];
wchar_t CurrentString[1000];
ptr_file =fopen("Sample.txt","rb");
int __index = 0;
while(fgetws (CurrentString , 1000 , ptr_file) != NULL)
{
char* errorDes;
errorDes = new char[1000];
wcstombs(errorDes, CurrentString, 1000);
list[__index] = errorDes;
__index++;
}
Problem :-
1)Same as above if my one line charecters exceed 1000 then more than 1000 charecters are not consider and vise versa.
2)If my file size exceed 65534 then char* list array will not fill properly and vise versa.
Please provide me any link,block of code,suggestion that help me to solve all problem in pure C.
In C
#define DEFAULT_ARRAY_SIZE 20000
#define NEW_SIZE 20100
char* constructString = (char *)malloc(DEFAULT_ARRAY_SIZE * sizeof(char));
// Now you have the array allocated
// To reallocate it:
constructSring = (char *)realloc (construcString, NEW_SIZE)
// Now you can assign new values into the new array positions:
constructString[20000] = 'a'
constructString[20001] = 'b'
constructString[20002] = 'c'
...
I hope this helps you
You can create a vector of chars with variable length in C, copying the behaviour of std::string.
I gave complete source code in an answer to this question.
Basically, you need to create various functions (String_add, String_getLine, String_delete...) around a struct which will hold the pointer to char vector, the size and the capacity. In order to minimize the number of memory allocations, you can follow the std::string strategy, doubling the capacity each time.
Hope this helps.

strncpy() to get end of string

I am using C Style strings for a project, and I am confusing myself a bit. I am checking strings to see what they are prepended with (zone_, player_, etc) then getting the rest of the string after that.
else if(strncmp(info, "zone_", 5) == 0)
{
int len = strlen(info);
char *zoneName = new char[len];
strncpy(zoneName, &info[5], len-5);
Msg("Zone Selected: %s\n", zoneName);
delete zoneName;
}
When I print out the zoneName variable though, it is correct except it is followed by a bunch of gibberish. What am I doing wrong? (I realize that the gibberish is the rest of the char array being empty, but I don't know a better way to do this)
See strncpy description :
No null-character is implicitly
appended to the end of destination, so
destination will only be
null-terminated if the length of the C
string in source is less than num.
You have to remember that C-style strings are terminated with a NUL character. You've allocated enough space in zoneName, but you only need len-5 plus one:
char *zoneName = new char[len - 5 + 1];
Then, you can actually use strcpy() to copy the tail of the string:
strcpy(zoneName, &info[5]);
You don't need to specify the length because the source string is NUL terminated.
C strings are zero terminated - so they occupy len bytes (chars to be precise) plus one more with value zero known as the 'zero terminator'. You need to allocate one more character, and either copy one more from the source (since it should be zero terminated) or just set the last char of the destination to 0.
int len = strlen(info);
char *zoneName = new char[len - 5 + 1];
strncpy(zoneName, &info[5], len - 5 + 1);
C-style strings has to be finished with a byte with zero value. You should modify your code like this:
char *zoneName = new char[len-5+1];
strncpy(zoneName, &info[5], len-5);
/* correct string ending */
zoneName[len]=0;
/* Now, it's safe to print */
Msg("Zone Selected: %s\n", zoneName);