Error with strcpy and its second argument - c++

When I try and compile this program, I get errors (included below the code) about strcpy's second argument. I'm honestly stumped on what to do to fix it. And I'm sorry if my code is not efficient or pretty to look at; I'm just a beginning CS student.
#include "stdafx.h"
#include <iostream>
#include <ctime>
using namespace std;
int main(){
int r = 0;
char *article[]={"the", "a", "one", "some", "any"};
char *noun[]={"boy","girl","dog","town","car"};
char *verb[]={"drove","jumped","ran","walked","skipped"};
char *preposition[]={"to","from","over","under","on"};
char sentence [80];
srand(time(NULL));
for(int i=0;i<=20;i++){
r = (rand()%5);
strcpy(sentence,*article[r]);
strcat(sentence," ");
r = (rand()%5);
strcat(sentence,*noun[r]);
strcat(sentence," ");
r = (rand()%5);
strcat(sentence,*verb[r]);
strcat(sentence," ");
r = (rand()%5);
strcat(sentence,*preposition[r]);
strcat(sentence," ");
r = (rand()%5);
strcat(sentence,*article[r]);
strcat(sentence," ");
r = (rand()%5);
strcat(sentence,*noun[r]);
strcat(sentence,".");
}
sentence[0]= toupper(sentence[0]);
cout<<sentence <<endl;
system("pause");
return 0;}
1>Compiling...
1>assignment 8.cpp
1>e:\assignment 8\assignment 8\assignment 8.cpp(16) : warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data
1>e:\assignment 8\assignment 8\assignment 8.cpp(20) : error C2664: 'strcpy' : cannot convert parameter 2 from 'char' to 'const char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(23) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(26) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(29) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(32) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>e:\assignment 8\assignment 8\assignment 8.cpp(35) : error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

DANGER. strcat() AND strcpy() ARE THE LEADING CAUSES OF CODE CANCER. Using them exposes you to all kinds of buffer overflows. Use strncat()/strncpy(), or (even better) just use std::string, since you're using C++!
strcat() and strcpy() expect their arguments to be strings. *article[r] is a single char--article[r] is the string you want. So, drop the leading asterisks.

You have one asterisk too many - noun[r] already gives you a char* so you don't need to put an additional * in the second parameter.
Also, strcat is an unsafe function and can crash your program unexpectedly if your buffer (in your case, sentence) is ever too small for the content.
Please use strncat instead - you'll need to add one more parameter to that function, which is the buffer size - in this case, 80. Then in case of undersized buffer instead of program crash you would just notice that your sentence is clipped at the end.

Your articles, nouns, and verbs are arrays of char pointers. When selecting the item in the array to use, you get a char* to the word to use. This char* is what strcpy expects - when you dereference the char* (i.e. article[r]), you end up with a char, not a char.
Also, strcpy is an unsafe string operator, so it can overwrite large clumps of memory or otherwise open gaping security holes. Is there any reason you're not allowed to use std::string for this assignment?

Too much de-referencing, e.g. change:
strcpy(sentence,*article[r]);
to
strcpy(sentence, article[r]);
and similarly for the other instances.

*article[r] is a value of type char. It's the first character of the string. strcpy expects the address of the string which is simply article[r].

Instead of
strcpy(sentence,*article[r]);
you want
strcpy(sentence,article[r]);

Related

Conversion error when passing vector of type uint8_t to std::fill() in C++

I am using the below code snippet to pass vector of type "uint8_t" to std::fill()
size_t actual_size = 10;
std::vector<uint8_t> response;
std::fill(response.begin(), response.end() + actual_size, 0);
But i am getting the below warnings.
message : see reference to function template instantiation 'void std::fill<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,int>(const _FwdIt,const _FwdIt,const int &)' being compiled
with
[
_Ty=uint8_t,
_FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<uint8_t>>>
]
warning C4244: '=': conversion from 'const _Ty' to 'unsigned char', possible loss of data
with
[
_Ty=int
]
How to resolve this warning.
The reason you are getting the warning is because when filling 0(an int) to a vector<uint8_t>, you are implicitly converting an int to an uint8_t, which can potentially have data loss if the original int is not in the valid range of uint8_t.
To solve it, you can either create a uint8_t directly, or manually cast the int to uint8_t.
Also, when you do:
std::fill(vec.begin(), vec.end() + some_size, some_value)
You are literally filling elements pass the end iterator, without resizing the vector, which is likely not what you wanted.
Instead, you should use fill_n to specify the number of element to fill, and use back_inserter to push it to the vector:
std::fill_n(std::back_inserter(vec), some_size, some_value);
Or you can simply initialize the vector with the appropriate data filled:
std::vector<std::uint8_t> vec(some_size, some_value);
Or even zero initialize them, since you were going to assign them to 0s:
std::vector<std::uint8_t> vec(some_size);

initializing : cannot convert from LPVOID error

Ok I'm trying to write this under the WFSExecute but if I type:
WFSPINGETDATA * pingetdata = lpCmdData;
I get an error:
errorC2440: 'initializing' : cannot convert from 'LPVOID' to 'WFSPINGETDATA *'
If I comment out that line, the app execute.
Also, if I write:
((WFSPINDATA*) (temp)) ->lpPinKeys = malloc(sizeof(LPWFSPINKEY)*NumberOfKeys) ;
I get an error:
errorC2440: '=' cannot convert from 'void' to 'LPWFSPINKEY *'
Any solution to solve this?
C++ is more strict on type safety than C is. In this case, void* must be type-casted when assigned to anything other than another void*.
WFSPINGETDATA * pingetdata = lpCmdData;
cannot convert from 'LPVOID' to 'WFSPINGETDATA *'
This means lpCmdData is a void*, so a type-cast is needed:
WFSPINGETDATA * pingetdata = (WFSPINGETDATA*) lpCmdData;
Or, using a C++-style cast instead of a C-style cast:
WFSPINGETDATA * pingetdata = static_cast<WFSPINGETDATA*>(lpCmdData);
((WFSPINDATA*) (temp)) ->lpPinKeys = malloc(sizeof(LPWFSPINKEY)*NumberOfKeys) ;
cannot convert from 'void' to 'LPWFSPINKEY *'
malloc() returns a void*, so a type-cast is needed here as well:
((WFSPINDATA*) (temp)) ->lpPinKeys = (LPWFSPINKEY*) malloc(sizeof(LPWFSPINKEY)*NumberOfKeys);
Or, using C++-style casts:
static_cast<WFSPINDATA*>(temp)->lpPinKeys = static_cast<LPWFSPINKEY*>(malloc(sizeof(LPWFSPINKEY)*NumberOfKeys));
Or, using C++-style allocation instead of C-style allocation:
static_cast<WFSPINDATA*>(temp)->lpPinKeys = new LPWFSPINKEY[NumberOfKeys];
// must use 'delete[] lpPinKeys' instead of 'free(lpPinKeys)' to deallocate the memory

C++ create empty byte

I was wondering if you could help me with a small problem I have:
I am currently devloping in C++/Qt and got the following error message:
P:\Produkt\Savor_V100\webapi.cpp:84: error: C2664: 'CryptoPP::PasswordBasedKeyDerivationFunction::DeriveKey' : cannot convert parameter 1 from 'const char *' to 'byte *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
The parameter in the function is not used, therefore I would like to pass an empty byte in there. After a bit of research I found out that a byte is just a simple unsigned char?
My code looks like this:
byte* unused;
qDebug() << CryptoPP::PasswordBasedKeyDerivationFunction::DeriveKey(CryptoPP::SHA1::StaticAlgorithmName(), CryptoPP::SHA1::BLOCKSIZE, unused, user->getPassword(), sizeof(user->getPassword()), user->getSerial(), sizeof(user->getSerial()), 0 );
As said in the comment, the issue here is with the first argument of the function, not with the third where you used unused. Since I guess you do need this parameter, you should try as suggested:
qDebug() << CryptoPP::PasswordBasedKeyDerivationFunction::DeriveKey(
reinterpret_cast<byte*>(CryptoPP::SHA1::StaticAlgorithmName()),
CryptoPP::SHA1::BLOCKSIZE,
0,
user->getPassword(),
sizeof(user->getPassword()),
user->getSerial(),
sizeof(user->getSerial()),
0 );

C code in C++ compiler

I have following code, it's code from tomcrypto's manual and it won't work on MS VC++ 2008 EE. Any help? Also can I ask replace char* by std::string object?
int main(void)
{
hash_state md;
unsigned char *in = "hello world", out[16];
/* setup the hash */
md5_init(&md);
/* add the message */
md5_process(&md, in, strlen(in));
/* get the hash in out[0..15] */
md5_done(&md, out);
return 0;
}
Errors:
\main.cpp(7) : error C2440: 'initializing' : cannot convert from 'const char [12]' to 'unsigned char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
.\main.cpp(11) : error C2664: 'strlen' : cannot convert parameter 1 from 'unsigned char *' to 'const char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
EDIT: Now code looks like:
int main(void)
{
register_hash(&md5_desc);
hash_state md;
char* p = "hello wordl";
unsigned char *in = reinterpret_cast<unsigned char*>(p);
char* out[16];
/* setup the hash */
md5_init(&md);
/* add the message */
md5_process(&md, const_cast<char*>(in), strlen(in));
/* get the hash in out[0..15] */
md5_done(&md, out);
return 0;
}
Errors:
\main.cpp(21) : error C2440: 'const_cast' : cannot convert from 'unsigned char *' to 'char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
.\main.cpp(21) : error C2664: 'strlen' : cannot convert parameter 1 from 'unsigned char *' to 'const char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
.\main.cpp(23) : error C2664: 'md5_done' : cannot convert parameter 2 from 'char *[16]' to 'unsigned char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
unsigned char *in = "hello world"
This is incorrect in C++: "hello world" is a string literal and is of type const char[12]. In C it is of type char[12], but the const here doesn't matter because in C++ there is an implicit (but deprecated) conversion that allows a string literal to be converted to a char*.
The problem is that char and unsigned char are different types. It doesn't matter whether char is unsigned; the three char types (char, unsigned char, and signed char) are all distinct and in C++ you cannot convert between pointers to those three types without a cast.
This works in C because in C you can convert any pointer-to-object type to any other pointer-to-object type without a cast. That isn't the case in C++.
In C++ you would need to use:
// use the implicit conversion to 'char*' to cast away constness:
char* p = "hello world";
// explicitly cast to 'unsigned char*'
unsigned char* in = reinterpret_cast<unsigned char*>(p);
The removal of constness is usually a bad idea since string literals are not modifiable, but sometimes it is necessary when dealing with legacy libraries that are not const-correct.
The conversion from char* to unsigned char* is safe because all objects can be treated as an array of char, unsigned char, or signed char in C++.
char is a different type to signed char or unsigned char; string literals are always of type (const) char *; so you cannot assign them to a (const) signed char * or a (const) unsigned char *. To fix this, remove the unsigned from line 4.
If your md5_process() function explicitly takes an unsigned char * as an argument, then you should perform a cast at that point:
md5_process(&md, reinterpret_cast<unsigned char*>(in), strlen(in));
[As others have said, you should really define in as const char *in as it's pointing to a string literal, but that is not the issue here.]
Let's try again:
int main(void)
{
register_hash(&md5_desc);
hash_state md;
const char* p = "hello wordl";
const unsigned char* in = reinterpret_cast<const unsigned char*>(p);
unsigned char out[16];
/* setup the hash */
md5_init(&md);
/* add the message */
md5_process(&md, in, strlen(p));
/* get the hash in out[0..15] */
md5_done(&md, out);
return 0;
}
Does this work?
This is because litteral strings are const in C++, while you initialize it with a non-const pointer:
const char* in = "hello world";
char * out[16];
However it might cause a problem if md5_process takes a non-const char*, in this case you'll have to cast to a non-const:
md5_process(&md, const_cast<char*>(in), strlen(in));

How to add strings to a 2d array of char elements?

I have the below program written in C++:
#include <iostream>
using namespace std;
int main()
{
int age[5];
char name[5][10];
age[0]=10;
age[1]=20;
age[2]=30;
age[3]=25;
age[4]=40;
name[0]="abc";
name[1]="abc";
name[2]="abc";
name[3]="abc";
name[4]="abc";
cout<<name[0]<<" is "<<age[0]<<"years old";
cout<<"\n";
cout<<name[1]<<" is "<<age[1]<<"years old";
cout<<"\n";
cout<<name[2]<<" is "<<age[2]<<"years old";
cout<<"\n";
cout<<name[3]<<" is "<<age[3]<<"years old";
cout<<"\n";
cout<<name[4]<<" is "<<age[4]<<"years old";
cout<<"\n\n";
system("PAUSE");
}
When I compile and run it, I get these errors:
error C2440: '=' : cannot convert
from 'const char [3]' to 'char [10]'
There is no context in which this conversion is possible
error C2440: '=' : cannot convert
from 'const char [2]' to 'char [10]'
There is no context in which this conversion is possible
error C2440: '=' : cannot convert
from 'const char [2]' to 'char [10]'
There is no context in which this conversion is possible
error C2440: '=' : cannot convert
from 'const char [2]' to 'char [10]'
There is no context in which this conversion is possible
error C2440: '=' : cannot convert
from 'const char [2]' to 'char [10]'
There is no context in which this conversion is possible
I am running MSVC 2008 under Windows 7. I have tried many possible solutions but I failed in fixing this. Any help would be appreciated,
You are treating the name array as if it was defined thus:
char *name[5];
So either define it that way, or use the following code to populate it:
strcpy(name[0], "abc");
strcpy(name[1], "abc");
strcpy(name[2], "abc");
strcpy(name[3], "abc");
strcpy(name[4], "abc");
I prefer the former choice. The point being you are trying to assign a char * to a char [] which is what strcpy is for. Given you are manipulating initialized C strings in this case anyway, you might as well deal with char * throughout the code.
You should use std::string for this purpose. The use of char* and char[] to represent strings is deprecated in C++ for many good reasons.
Given the program snippet, name can be initialized at the declaration itself.
char name[5][10] = { "abc", "abc", "abc", "abc", "abc" } ;
// ^ index 5 is not necessary. char name[][10] = { .. } would also suffice.
Specified the length of each row is 10 but only using first 3 indexes of it. Every 3rd index ( i.e., 4th element in the array ) is automatically added with a '\0'.
Initialization can be done in case of age array too.
You can use also std::string name[10] instead of 2d char's array. In this case only you can assign new values to the strings through operator '='.
Otherwise you should to use array of char* and use strcpy() function for assignment.