storing system time to a variable in cpp - c++

I want to save the local time to a char variable. here is the code i have used. but it is saying
"cannot convert char * to char"
Here is my code:
#include <stdio.h>
#include <time.h>
struct tme
{
char intime;
}e;
void main( )
{
char timeStr [9];
_strtime( timeStr );
e.intime=timeStr;
printf( "The current time is %s \n", timeStr);
}
Thanx in advance.

That's simple, you have a char array timeStr of length 9 and trying to assign it to a char intime. There's type incompatibility. Think of it as char[] is never equal to char.
You could solve this as follows (but I don't know what you want to achieve):
struct tme
{
char* intime;
}e;
PS: MSDN states that (_strtime):
// Note: _strtime is deprecated; consider using _strtime_s instead

e.intime=timeStr;
timeStr is of type char [9]. It decays to a pointer pointing to first element during assignments or in a function call used as a parameter.
e.intime is of type char. char and char* aren't type compatible and the compiler is complaining you that. Instead you can do -
struct tme
{
char intime[10]; // +1 for the termination character to play safe
}e;
Now, strcpy can be used to copy the time to the member variable.
strcpy(e.intime, timeStr);
If it is C++, use std::string instead of raw arrays.

Some stages of refinement:
Stage 1: Fix your code.
struct tme {
char * intime; // You had a type mismatch
} e;
int main () { // Don't use void main()
char timeStr [9];
_strtime( timeStr );
e.intime=timeStr;
printf( "The current time is %s \n", timeStr);
}
There's a problem here: Your struct tme is relying on the external world to do everything for it, and to do so correctly. What if we want to reuse timeStr in main? What if you use this structure in a function other than main and set e.intime to a variable that goes out of scope?
Refinement: struct tme should own the time buffer.
struct tme {
char intime[9]; // Put the buffer here, not in main.
} e;
int main () {
_strtime( e.intime );
printf( "The current time is %s \n", e.intime);
}
We still have a problem here. That buffer can be modified by anyone, and the structure is just a passive receptacle.
Refinement: Hide the data and make the object active.
struct tme {
const char * set_time () { _strtime (intime); return intime; }
const char * get_time () const { return intime; }
private:
char intime[9];
};
int main () {
printf( "The current time is %s \n", e.set_time());
}

Related

SSLeay reading a PEM file

I am trying to use the PEM_read_bio function to get data from a file.
The version of SSLeay we are using is from 1997, so documentation is a bit thin on the ground. Thankfully in this case it seems there is a matching function documented here: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio.html
I originally tried this:
char ** names;
char ** headers;
unsigned char ** data;
long len;
BIO *in = BIO_new_file("C:\\filename.txt", "r");
if (!in)
{
// error
}
else
{
int result = PEM_read_bio(in, names, headers, data, &len);
}
BIO_free(in);
OPENSSL_free(names);
OPENSSL_free(headers);
OPENSSL_free(data);
However this results in a run-time check failure: The variable 'names' is being used without being initialized.
The documentation mentions OPENSSL_malloc( num ) is used to initialize memory, but it fails to mention whether it does this behind the scenes, or the user does it.
OPENSSL_malloc is similar in usage to C's malloc, but how are we supposed to know how much memory to allocate in advance, before reading the file?
I have tried the following at the beginning:
char ** names = reinterpret_cast<char **>(OPENSSL_malloc(2));
char ** headers = reinterpret_cast<char **>(OPENSSL_malloc(2));
unsigned char ** data = reinterpret_cast<unsigned char **>(OPENSSL_malloc(2));
long len;
This results in apparently random data.
The documentation you linked to says:
The name, header and data pointers are allocated via OPENSSL_malloc() and should be freed by the caller via OPENSSL_free() when no longer needed.
That means PEM_read_bio() calls OPENSSL_malloc() for you, and then you call OPENSSL_free() on the allocated memory it returns when you are doing with it.
You are passing uninitialized pointers to PEM_read_bio(), that is why it is failing. The name, header and data parameters are all output parameters. You need to pass in the addresses of your own pointer variables to receive the memory that PEM_read_bio() allocates for you, eg:
char *name;
char *headers;
unsigned char *data;
long len;
BIO *in = BIO_new_file("C:\\filename.txt", "r");
if (!in)
{
// error
}
else
{
int result = PEM_read_bio(in, &name, &headers, &data, &len);
if (!result)
{
// error
}
else
{
...
OPENSSL_free(name);
OPENSSL_free(headers);
OPENSSL_free(data);
}
BIO_free(in);
}

C++ Set value for a char**

I'm trying to assign a value to a char** variable. In my foo.h I've defined a couple of variables such as
#define APIOCTET int
#define APILONG long
#define APICHAR char
#define APISTRING char*
Now in my foo.cpp I'm tryng to use a method where
APILONG apiInitialize(APISTRING filePath, APISTRING* outputString)
{
//open text file to where output will be printed
//do other stuff, etc..
//return result;
}
I'd like to assign a value to my APISTRING* outputString but I just can't figure out how to do so, I've tried many things which are basically a variation of the following code
APISTRING error = "error";
APISTRING other = "string";
APISTRING charArr[] = { error, other, error };
APISTRING *charArr2[] = { charArr };
errorString = *charArr2;
Also im not 100% clear on what exactly is APISTRING* outputString. When I try to compile it gives me an error message where it mentions it's a char**. Is it a 2D array?.. A pointer to an array of chars?.. But most importantly, how would I assign a value for this variable? Thanks in advance.
The APISTRING* is a pointer to a pointer to char. It holds an address which holds the address of the first character of the string in memory.
See this question for more info on double pointers in C/C++.
To assign to the string you would need to do *outputString = "string"
APISTRING* outputString will be pre-processed and replcaed at compile-time as char** outputstring. Hence, outputString will be double pointer hence, you need to do it like this (below code). I combined both .h and cpp together for simplicity.
#include<iostream>
using namespace std;
#define APIOCTET int
#define APILONG long
#define APICHAR char
#define APISTRING char*
APILONG apiInitialize(APISTRING filePath, APISTRING* outputString)
{
APISTRING getIt = *outputString;
cout<<" "<<getIt<<endl;
}
int main()
{
APISTRING str = "hello";
APISTRING* outputString = &str;
APILONG val = apiInitialize("world", outputString );
system("PAUSE");
return 0;
}
I would recommend to use std::string, it'll be easy to tweak with certain behaviors. Hope this helps.

Two variables from different structs give me a compiling error when I match them

So I might be missing a key point because I've never been good with structs.
I have a struct like this:
typedef struct Message
{
int op;
char local[128];
char remote[128];
int port;
} Mensaje;
And so I am setting values of this struct like this:
Mensaje mensaje;
mensaje.op=htonl(2);
And now I want to get the info from one struct and put it into another, so I can send it.
I try this:
mensaje2.remote=mensaje1.remote;
And I get this error: error: incompatible types when assigning to type 'char[128]' from type 'char *'
And it absolutly baffles me, because both things come from the same struct. I've been trying messing with the operator -> but without success.
What should I do so that one struct, without values (mensaje2) gets the value of mensaje1.remote?
For historical reasons, arrays cannot be directly copied in C or C++. :(
If you used C++'s std::array<char, 128> instead then you'd be able to do it:
struct Message
{
int op;
std::array<char, 128> local;
std::array<char, 128> remote;
int port;
};
int main()
{
Message mensaje1, mensaje2;
mensaje1.remote = mensaje2.remote;
}
It rather looks like you want a string, though; std::string are copyable too!
struct Message
{
int op;
std::string local;
std::string remote;
int port;
};
int main()
{
Message mensaje1, mensaje2;
mensaje1.remote = mensaje2.remote;
}
Otherwise you're going to have to use std::copy to copy the array elements manually:
struct Message
{
int op;
std::string local;
std::string remote;
int port;
};
int main()
{
Message mensaje1, mensaje2;
std::copy(
std::begin(mensaje2.remote),
std::end(mensaje2.remote),
std::begin(mensaje2.remote)
);
}
The error message you're getting is confusing because the compiler tries, as a last-ditch effort, to use the implicit conversion of an array's name to pointer-to-its-first-element, before finally giving up.
Arrays are second class citizens in C, you cannot assign arrays. Use memcpy to copy an array or strcpy / strncpy to copy a string.
You must copy the contents of one array into the other, use strcpy
strcpy(mensaje2.remote, mensaje1.remote);

variable len string

i have a packet struct which have a variable len for a string example:
BYTE StringLen;
String MyString; //String is not a real type, just trying to represent an string of unknown size
My question is how i can make the implementation of this packet inside an struct without knowing the size of members (in this case strings). Here is an example of how i want it to "look like"
void ProcessPacket (PacketStruct* packet)
{
pointer = &packet.MyString;
}
I think its not possible to make since the compiler doesn't know the size of the string until run time. So how can make it look high level and comprehensible?.
The reason i need structs its for document every packet without the user actually have to look any of the functions that analyze the packet.
So i can resume the question to: is there a way to declare an struct of undefined size members or something close as a struct?
I would recommend a shell class that just interprets the packet data.
struct StringPacket {
char *data_;
StringPacket (char *data) : data_(data) {}
unsigned char len () const { return *data_; }
std::string str () const { return std::string(data_+1, len());
};
As mentioned in comments, you wanted a way to treat a variable-sized packet like a struct. The old C way to do that was to create a struct that looked like this:
struct StringPacketC {
unsigned char len_;
char str_[1]; /* Modern C allows char str_[]; but C++ doesn't */
};
And then, cast the data (remember, this is C code):
struct StringPacketC *strpack = (struct StringPacketC *)packet;
But, you are entering undefined behavior, since to access the full range of data in strpack, you would have to read beyond the 1 byte array boundary defined in the struct. But, this is a commonly used technique in C.
But, in C++, you don't have to resort to such a hack, because you can define accessor methods to treat the variable length data appropriately.
you can copy the string into a high-level std::string (at least, if my guess that String is a typedef for const char* is correct):
void ProcessPacket( const PacketStruct& packet )
{
std::string highLevelString( packet.MyString,
static_cast< size_t >( packet.StringLen ) );
...
}
A simple variant according to your posting would be:
struct PacketStruct {
std::string MyString;
size_t length () const { return MyString.length(); }
const char* operator & () const { return MyString.c_str(); }
};
This can be used (almost) as you desired above:
void ProcessPacket (const PacketStruct& packet)
{
const char * pointer = &packet;
size_t length = packet.length();
std::cout << pointer << '\t' << length << std::endl;
}
and should be invoked like:
int main()
{
PacketStruct p;
p.MyString ="Hello";
ProcessPacket(p);
}

Trying to write a simple Blackjack, but there are errors I don't understand

I have a problem with a code of mine. It gives random errors and I don't know why.. I'm a newbie to C++ so please bear with me >.>
Here is the code that's problematic:
while (!IsGameOver) {
struct decktype deck = DeckInit();
struct card card = PickACard(deck);
PrintHand(TextCard(card));
}
The parameter for 'PrintHand' causes compilation errors no matter what I do. Here are both the functions.
char *TextCard(struct card &card) {
char str[22];
sprintf(str,"%s of %s (%d)",card_num[card.number],card_type[card.color],card.value);
return str;
}
struct card PrintHand(char &cardtext) {
struct card card;
return card;
}
PrintHand isn't done yet, but I don't know how to make it work.. Basically what I want to do is feed a string from TextCard to be used in PrintHand. Could you please help? Much appreciated.
EDIT:
The structure 'card' at the moment looks like this.
struct card {
int color;
int number;
int value;
char *hand;
int totalvalue;
};
And the errors are along the lines of "can't convert something to something". Sorry I couldn't be more specific :/
You cannot create a local variable and return it from function. Use malloc or new instead.
char str[22];
char * str = (char *) malloc(22* sizeof(char)); OR
String str = "sometext" + "othertext";
I don't know, what you are trying to do here:
struct card PrintHand(char &cardtext) {
struct card card;
return card;
}
If you want just print text, do this:
void PrintHand(char * cardtext) { // * instead of &
printf("%s", cardtext);
}
PrintHand expect a reference to char, but you (i.e., TextCard) provide a pointer to char.
There are several errors.
struct card PrintHand(char &cardtext) {
struct card card;
return card;
}
Doesn't use the cardtext, but the real error is the value passed to it from TextCard is char*, so this should be struct card PrintHand(char *cardtext)
Then:
char *TextCard(struct card &card) {
char str[22];
sprintf(str,"%s of %s (%d)",card_num[card.number],card_type[card.color],card.value);
return str;
}
This returns, str, i.e. the address of str[0] which is on the stack, and disappers after TextCard returns, so nothing shoud use that return value. Either new some storage for the char array in the function return it, and have the caller cleanup, or pass in a char array from the caller.