C code convert to C++ sha1 issue - c++

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
int main()
{
unsigned char ibuf[] = "trysha";
unsigned char obuf[20];
SHA1(ibuf, strlen(ibuf), obuf);
int i;
for (i = 0; i < 20; i++) {
printf("%02x ", obuf[i]);
}
printf("\n");
return 0;
}
I got some error with this code..
sha.cpp: In function ‘int main()’:
sha.cpp:10:27: error: invalid conversion from ‘unsigned char*’ to ‘const char*’ [-fpermissive]
/usr/include/string.h:399:15: error: initializing argument 1 of ‘size_t strlen(const char*)’ [-fpermissive]

strlen() wants a const char *, or at least a char*, the problem is that you're giving to it an unsigned char*. You should do this:
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
int main()
{
char ibuf[] = "trysha";
unsigned char obuf[20];
SHA1(ibuf, strlen(ibuf), obuf);
int i;
for (i = 0; i < 20; i++) {
printf("%02x ", obuf[i]);
}
printf("\n");
return 0;
}
If SHA1 expects an unsigned char* as first argument, you may have to cast ibuf: SHA1(static_cast<unsigned char*>(ibuf), strlen(ibuf), obuf);
By the way you don't need strlen(), you can replace it by this:
SHA1(ibuf, sizeof(ibuf), obuf);

It tells you exactly what is wrong -- strlen doesn't accept unsigned char*, but rather plain const char*. According to 3.9.1.1 of the C++98 standard, signed char, unsigned char and char are distinct types and you cannot convert them explicitly.
Why are you using unsigned char for C-style strings anyway?

Related

How can I convert a character from a string into a integer variable using C++

string phone_nb = "173";
char just_one_char = phone_nb[1];
int i_just_one_char = stoi(just_one_char);
I get these errors:
no matching function for call to 'stoi'
int i_just_one_char = stoi(just_one_char);
note: candidate function not viable: no known conversion from 'char' to 'const std::__1::string' (aka 'const basic_string<char, char_traits<char>, allocator<char> >') for 1st argument
_LIBCPP_FUNC_VIS int stoi (const string& __str, size_t* __idx = 0, int __base = 10);
note: candidate function not viable: no known conversion from 'char' to 'const std::__1::wstring' (aka 'const basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >') for 1st argument
_LIBCPP_FUNC_VIS int stoi (const wstring& __str, size_t* __idx = 0, int __base = 10);
You can try something like this:
#include <iostream>
#include <string>
int main() {
std::string phone_nb = "173";
int i_just_one_char = phone_nb[0] - '0';
std::cout << i_just_one_char;
}
Which works by relying on how characters/ASCII is structured to convert from a character to its integer equivalent.
The above code will output a 1.
The easiest fix for your code would be to just use atoi instead of stoi
You can modify your code like this:
string phone_nb = "173";
char just_one_char_str[2];
just_one_char_str[0] = phone_nb[1];
just_one_char_str[1] = '\0';
int i_just_one_char = atoi(just_one_char);
You can read up more on atoi() here
Alternative
As mentioned by #RemyLebeau, one could also use the substr() function and get a similar result or could also use the answer by #Rietty
string phone_nb = "173";
string just_one_char = phone_nb.substr(0, 1);
int i_just_one_char = stoi(just_one_char);

Variadic function int to size_t warning

I have a function accept multiple arguments.
#include <iostream>
#include <cstdarg>
#include <vector>
using namespace std;
template<typename... Values>
void doSomething(size_t input, Values... inputs)
{
size_t len = sizeof...(Values) + 1;
size_t vals[] = {input, inputs...};
vector<size_t> n(len);
std::copy( vals, vals+len, n.data() );
for(size_t i=0; i<len; i++) cout<<n[i]<<endl;
//Do something with n vector
}
It works fine when I call this function by:
size_t a(1), b(2), c(3);
doSomething(a,b,c);
However, it will have a problem when I call this function by:
doSomething(1,2,3);
It will give out warning message:
warning: narrowing conversion of ‘inputs#0’ from ‘int’ to ‘size_t {aka long unsigned int}’ inside { } [-Wnarrowing]
size_t vals[] = {inputs...};
I do not like this warning message, is there a way to solve this problem? I would like the function to be able to accept either size_t or int. Thank you.

Invalid conversion from ‘const char*’ to ‘unsigned char*’

A simple C++ code:
int main(){
unsigned char* t="123";
}
on compilation with g++ gives following error:
invalid conversion from ‘const char*’ to ‘unsigned char*’ [-fpermissive]
Why?
In C++ string literals have types of constant character arrays. For example string literal "123" has type const char[4].
In expressions with rare exceptions arrays are converted to pointers to their first elements.
So in this declaration
unsigned char* t="123";
the initializer has type const char *. There is no implicit conversion from const char * to unsigned char *
You could write
const unsigned char* t = reinterpret_cast<const unsigned char *>( "123" );
Another approach, which gets you a modifiable unsigned char array as you originally wanted, is:
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
unsigned char ta[] = "123";
unsigned char* t = ta;
cout << t << endl; // Or ta.
return EXIT_SUCCESS;
}
You can add const to both declarations if you wish, to get const unsigned char without an explicit cast.
Simply use
just char* in place of unsigned char* during declaration
char t[MAX_SIZE] = "123"; // MAX_SIZE should be defined earlier
time tested strcpy() and strncpy functions
Conversions from one type to another type is easy when you use self-defined macros. So here is a set of macros you can use across any platform (Windows, Linux, Solaris, AIX etc...)
#define M_ToCharPtr(p) reinterpret_cast<char*>(p) // Cast to char*
#define M_ToWCharPtr(p) reinterpret_cast<wchar_t*>(p) // Cast to wchar_t*
#define M_ToConstCharPtr(p) reinterpret_cast<const char*>(p) // Cast to const char*
#define M_ToConstWCharPtr(p) reinterpret_cast<const wchar_t*>(p) // Cast to const wchar_t*
#define M_ToUCharPtr(p) reinterpret_cast<unsigned char*>(p) // Cast to unsigned char*
#define M_ToConstUCharPtr(p) reinterpret_cast<const unsigned char*>(p) // Cast to const unsigned char*
#define M_ToUCharPtr(n) reinterpret_cast<unsigned char*>(n) // Cast to unsigned char*
#define M_ToVoidPtr(p) reinterpret_cast<void*>(p) // Cast to void*
#define M_ToConstVoidPtr(p) reinterpret_cast<const void*>(p) // Cast to const void*
#define M_ToIntPtr(n) reinterpret_cast<int*>(n) // Cast to int*
#define M_ToConstIntPtr(p) reinterpret_cast<const int*>(p) // Cast to const int*
#define M_ToDoublePtr(n) reinterpret_cast<double*>(n) // Cast to double*
#define M_ToConstDoublePtr(n) reinterpret_cast<const double*>(n) // Cast to const double*
#define M_ToBoolPtr(n) reinterpret_cast<bool*>(n) // Cast to bool*
#define M_ToConstBoolPtr(n) reinterpret_cast<const bool*>(n) // Cast to const bool*
// General Cast
#define M_To(T, p) reinterpret_cast<T>(p) // Cast to T
In your case
const unsigned char* t = reinterpret_cast<const unsigned char *>("UCHAR TO CONST UCHAR");
is equivalent to
const unsigned char* t = M_ToConstUCharPtr("UCHAR TO CONST UCHAR");

Converting std::string::length to int

string::length has the return type of size_t, but it seems to able to be put into an int without any casting or anything. Why can I assign a size_t to an int in this case?
int main() {
string line;
getline(cin, line);
cout << line << endl;
int i = line.size();
int j = line.length();
cout << i << " " << j << endl;
}
The size_t values are being narrowed. In c++11, you could make this fail with an error by doing:
#include <string>
int main() {
std::string line;
int i{line.size()};
int j{line.length()};
}
The errors produced look like:
gh.cc:5:11: error: non-constant-expression cannot be narrowed from type 'size_type' (aka 'unsigned long') to 'int' in initializer list [-Wc++11-narrowing]
int i{line.size()};
^~~~~~~~~~~
gh.cc:5:11: note: override this message by inserting an explicit cast
int i{line.size()};
^~~~~~~~~~~
static_cast<int>( )
gh.cc:6:11: error: non-constant-expression cannot be narrowed from type 'size_type' (aka 'unsigned long') to 'int' in initializer list [-Wc++11-narrowing]
int j{line.length()};
^~~~~~~~~~~~~
gh.cc:6:11: note: override this message by inserting an explicit cast
int j{line.length()};
^~~~~~~~~~~~~
static_cast<int>( )
size_t is a 32 bit integer.
Go to your compiler directory and open the stdio.h file.
There is a declaration, something like this:
typedef unsigned int size_t;

c-style string sorting with sort and qsort

I'm trying to use both sort and qsort to sort a c-style string and them see which of them is better, so I've written this code, but it is not working , so can you please tell me what is wrong with it.
thanks in advance.
#include <iostream>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<chrono>
#include<string>
#include<sstream>
using namespace std;
using namespace std::chrono;
void bvect(vector<double> &vec, int num)
{
auto gen = bind(normal_distribution<double>(15,4.0),default_random_engine());
for(int i=0; i<num; ++i)
vec.push_back(gen());
}
char* converttostring(int number)
{
stringstream ss;
ss << number;
return (ss.c_str());
}
int cst_cmp(const void *one, const void *two)
{
char a = *((char*)one);
char b = *((char*)two);
return strcmp(a, b);
}
//Generated random strings
void textvect(vector<string> &vec, int num)
{
srand(time(NULL));
for(int i=0; i<num; ++i)
vec.push_back(converttostring(rand()%num +1));
}
void displayvector(vector<char*>vect)
{
for (int i=0; i<vect.size(); ++i){
for (int j=0; j<strlen(vect[i]); ++j)
cout<<vect[i][j];
cout<<endl;
}
}
int main(){
int sz=100000;
vector<char*>text1, text2;
textvect(text1, sz);
text2.resize(text1.size());
copy(text1.begin(),text1.end(),text2.begin());
// qsort() string
auto t1 = system_clock::now();
qsort(&text1[0], text1.size(), sizeof(char*), cst_cmp);
auto t2 = system_clock::now();
auto dms = duration_cast<milliseconds>(t2-t1);
cout << "string qsort() took " << dms.count() << " milliseconds\n";
// sort() string
auto t3 = system_clock::now();
std::sort(text2.begin(), text2.end());
auto t4 = system_clock::now();
auto dms1 = duration_cast<milliseconds>(t4-t3);
cout << "string sort() took " << dms1.count() << " milliseconds\n";
return 0;
}
For std::sort, you are just using the default comparator, which will just compare pointer values. You need to pass a comparator that does a proper comparison (using strcmp, for example):
std::sort(text2.begin(), text2.end(),
[](const char* lhs, const char* rhs) { return strcmp(lhs,rhs) < 0; });
That's one problem, there may be others.
One problem is in your compare function for qsort:
int cst_cmp(const void *one, const void *two)
{
char a = *((char*)one);
char b = *((char*)two);
return strcmp(a, b);
}
You are not comparing strings here, because a and b are just chars. You might as well avoid them:
int cst_cmp(const void *one, const void *two)
{
return (strcmp(*(char **)one, *(char **)two));
}
These are the errors I obtain trying to compile your code:
> g++ main.cc -std=c++0x
main.cc: In function ‘char* converttostring(int)’:
main.cc:24:15: error: ‘std::stringstream’ has no member named ‘c_str’
main.cc: In function ‘int cst_cmp(const void*, const void*)’:
main.cc:31:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
/usr/include/string.h:143:12: error: initializing argument 1 of ‘int strcmp(const char*, const char*)’ [-fpermissive]
main.cc:31:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
/usr/include/string.h:143:12: error: initializing argument 2 of ‘int strcmp(const char*, const char*)’ [-fpermissive]
main.cc: In function ‘int main()’:
main.cc:55:23: error: invalid initialization of reference of type ‘std::vector<std::basic_string<char> >&’ from expression of type ‘std::vector<char*>’
main.cc:35:6: error: in passing argument 1 of ‘void textvect(std::vector<std::basic_string<char> >&, int)’
24:15 c_str() is a member function of string not of stringstream. See here.
31:23 strcmp() wants two const char * not two char. See here.
55:23 and 35:6 char* is not the same type as string.
This function isn't working
char* converttostring(int number)
{
   stringstream ss;
   ss << number;
   return (ss.c_str());
}
and if it was sort of fixed (ss.str().c_str()), it would return a pointer to a temporary.
If you have a compiler with some C++11 support, you can use std::to_string from the standard library. Otherwise, change the return type to std::string (no pointer!).
Ask Stroustrup ;) just allocate space for the C string array and enter characters ino it.. remember to deallocate it..