my code:
#include <iostream>
using namespace std;
struct widget
{
char brand[20];
int type;
union id
{
long id_num;
char id_char[20];
}id_val;
};
int main()
{
widget prize =
{"Rolls", 0, "A2X"};
return 0;
}
The problem is with initialization "A2X" when initializing a union in a structure. Compiler doesn't know I want to choose second option with array of chars when I am passing "A2X", it's requiring long type. When I put
char id_char[20]
before
long id_num
everything is ok. But I want to know how to enforce compiler to accept "A2X" with char as the second option in union. Thank for your help.
But I want to know how to enforce compiler to accept "A2X" with char as the second option in union.
You can use a constructor:
id(char const *id_char) {
std::strcpy(this->id_char, id_char);
}
Alternatively you could use a widget constructor.
A drawback is that the compiler probably won't be able to warn you if you use a too large input string for initialization. The shown trivial constructor can be expanded with strlen to check overflow at runtime. I suggest throwing an exception if you choose to check.
This works with -std=c++11:
#include <cstring>
#include <stdexcept>
struct widget
{
char brand[20];
int type;
union id
{
long id_num;
char id_char[20];
}id_val;
widget(char const*Str, int Type, char const *Id);
};
widget::widget(char const*Str, int Type, char const *Id)
{
if (strlen(Str)+1 > sizeof brand)
throw std::length_error{"brand too large"};
memcpy(brand,Str,strlen(Str)+1);
type = Type;
if (strlen(Id)+1 > sizeof id_val.id_char)
throw std::length_error{"id too large"};
memcpy(id_val.id_char,Id,strlen(Id)+1);
}
int main()
{
widget prize = {"Rolls", 0, "A2X"};
return 0;
}
Related
I am new to c++ & don't know the basics all that well. pls help (sorry if the solution to this is already available, but I couldn't find any)
This is the Error I am getting:
expected primary-expression before ‘]’ token
char CusName[50]=x[];
^
For this code below:
#include <iostream>
using namespace std;
class BankAccount
{
private:
char CusName[50];
char CusId[10];
float accBalance, dep, witd;
public:
void setCusDetails(char x[], char n)
{
char CusName[50]=x[];
}
};
int main()
{
BankAccount customer1;
char cus1Name[50];
cin>>cus1Name;
customer1.setCusDetails(cus1Name, 50);
return 0;
}
Your char array looks like a string. Try using std::string instead and prefer using const references for function parameters.
If you want to use char arrays, and if your point was to copy a null-terminated string by value, then use functions like strncpy.
Using std::string may be easier for you to hide the burden of memory allocation and discover the language step by step.
You can instead use string to input and pass values.
#include <iostream>
using namespace std;
class BankAccount
{
private:
string CusName; //CusName of type string
char CusId[10];
float accBalance, dep, witd;
public:
void setCusDetails(string str, char n) //parameter str of type string
{
CusName=str; //Assign it to the already declared 'CusName' variable.
}
};
int main()
{
BankAccount customer1;
string cus1Name;
cin>>cus1Name;
customer1.setCusDetails(cus1Name, 50);
return 0;
}
Hi I am new in c++ and I make skeleton of program and I have some problems with destructors and constructors.
My head.cpp:
#include <iostream>
#include "set_char.hpp"
using namespace std;
int main()
{
set_char *z1 = new set_char(unsigned char *zbior[]);
delete z1;
return 0;
};
My set_char.hpp class file:
#define ROZMIAR_MAX 256
class set_char
{
unsigned char zbior[ROZMIAR_MAX];
public:
set_char(unsigned char *zbior[]);
~set_char(unsigned char *zbior[]);
int nalezy(unsigned char);
int licznosc();
void dodaj(unsigned char);
void usun(unsigned char);
};
And my set_char.cpp file:
#include "set_char.hpp"
#include <iostream>
#include <math.h>
using namespace std;
set_char(unsigned char *zbior[]);
~set_char(unsigned char *zbior[]);
void set_char::dodaj(unsigned char)
{
};
void set_char::usun(unsigned char)
{
};
int set_char::nalezy(unsigned char)
{
};
int set_char::licznosc()
{
};
Among others:
you should not add any parameters in destructors:
~set_char(unsigned char *zbior[]);
^^^^^^^^^^^^^^^^^^^^^^ --- remove it
When creating set_char you should provide pointer to your array, and not the actual parameter type:
set_char *z1 = new set_char(unsigned char *zbior[]);
^^^^^^^^^^^^^^^^^^^^^^
1
You did not define your Constructor and Destructor
You declared them both in your set_char.hpp
set_char(unsigned char *zbior[]);
~set_char(unsigned char *zbior[]);
However in set_char.cpp you re-declare them again without a return type. Defining a Constructor and Destructor outside of a class is illegal. Your compiler thinks they are functions and searches for a return type.
2
a Destructor may not have any arguments.
3
If you define an array as an argument in a Function or a Constructor or Destructor with brackets '[]', it may not be of variable length, thus it must be defined. If it is intended to be of variable length, it must be left out.
4
You are calling the constructor in a bad way using:
new set_char(unsigned char *zbior[]);
You already declared what arguments it takes, so hand it the arguments. A null pointer, for example.
The correct way to do it in set_char.hpp:
set_char(unsigned char *);
~set_char();
The correct way to do it in set_char.cpp:
set_char::set_char(unsigned char *zbior)
{
//Your definition
}
set_char::~set_char();
{
//Your definition
}
The correct way to do it in head.cpp:
set_char *z1 = new set_char(0x0);
Also side-note, usually using the define macro to define constants, is a C way. In C++ it is usually done with:
static const size_t ROZMIAR_MAX 256;
Second side-note. It is considered 'neater' code if you have your constants/functions and whatnot defined inside a namespace
I need to expose a compile time constant with the size of internal class. To do so I tried next code:
#include <cassert>
struct A
{
//consider Private class as private for this example, just to be able to put the assert like this in main
class Private{};
enum { PrivateSize = sizeof(Private) };
};
int main()
{
//here I have warning on some compilers, signed/unsigned comparison
assert(A::PrivateSize == sizeof(A::Private));
}
My problem is that PrivateSize is signed on some compiler and unsigned on others and I get warnings about this when comparing it with signed types. As far as I know enum's underlying type is implementation defined and can't be forced to be signed or unsigned.
Do you know a way to expose sizeof(A::Private) outside A as compile time constant, but keeping Private class... private? Please note I can't use constexpr as the code will be used on some old compilers.
Following works:
struct A
{
friend int main(int argc, char *argv[]); // For test purpose
private:
class Private{};
public:
static const unsigned int PrivateSize = sizeof (Private);
};
int main(int argc, char *argv[])
{
assert(A::PrivateSize == sizeof(A::Private));
return 0;
}
I write a sample code and when the list push_back it always caused coredump
This is my code:
#include <iostream>
#include <list>
#include <string.h>
using namespace std;
struct FDTinstance
{
int type;
unsigned int expirestime;
unsigned int fileTOI;
string filename;
unsigned int contentlength;
unsigned long long T3;
unsigned long long T1;
unsigned long long T4;
unsigned long long sessionstarttime;
};
struct PacketInfo
{
unsigned int port;
unsigned long long arrivetime;
unsigned int syncType;
unsigned short timeStamp;
unsigned short packNum;
unsigned int packCount;
unsigned int TSI;
unsigned int TOI;
FDTinstance fDTinstance;
};
int main(int argc, char* argv[])
{
struct PacketInfo packet;
packet.fDTinstance.filename = "http://123.com";
packet.syncType=1;
packet.fDTinstance.expirestime = 100;
packet.fDTinstance.fileTOI = 0;
struct PacketInfo pack;
memcpy(&pack, &packet, sizeof(packet));
mVodList.push_back(pack);//cause core
return 0;
}
If I use const char* filename ,the program is OK. But when I use string type the program will core at push_back(). I don't kown why .Thanks
Just remove the memcpy and do this:
PacketInfo pack = packet;
or even better, forget about the intermediate copy altogether and do this:
mVodList.push_back(packet); // stores a copy of packet
The reason is that memcpy only works for POD types, and std::string is not one of those. In any case, even for PODs, using the copy constructor or assignment operator is the idiomatic way of copying one object into another one.
Also note that in C++ you don't need to write struct all over the place. So why say this
struct PacketInfo packet;
when you can say this?
PacketInfo packet;
memcpy(&pack,&packet,sizeof(packet));
That's not a valid way to copy non-POD objects, and there's no reason to use it for POD objects either. Just use the assignment operator (operator=). Or the copy constructor.
I have a class with private member variables declared in a header file. In my constructor, I pass in some filenames and create other objects using those names. This works fine. When I try to add another member variable, however, and initialize it in the constructor, I get an access reading violation. I sent the code to someone else and it works fine on his computer. Any idea what could be wrong?
Here is the offending code:
The .h file:
class QUERYMANAGER {
INDEXCACHE *cache;
URLTABLE *table;
SNIPPET *snip;
int* iquery[MAX_QUERY_LENGTH];
int* metapointers[MAX_QUERY_LENGTH];
int blockpointers[MAX_QUERY_LENGTH];
int docpositions[MAX_QUERY_LENGTH];
int numberdocs[MAX_QUERY_LENGTH];
int frequencies[MAX_QUERY_LENGTH];
int docarrays[MAX_QUERY_LENGTH][256];
int qsize;
public:
QUERYMANAGER();
QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname);
~QUERYMANAGER();
This is the .cpp file:
#include "querymanagernew.h"
#include "snippet.h"
using namespace std;
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname){
cache = new INDEXCACHE(indexfname, btfname);
table = new URLTABLE(urltablefname);
snip = new SNIPPET(snippetfname, snippetbtfname);
//this is where the error occurs
qsize = 0;
}
I am totally at a loss as to what is causing this - any ideas?
Thanks, bsg
Suggestion, factor out the arrays:
class QUERYMANAGER
{
// Snip
int* iquery[MAX_QUERY_LENGTH];
int* metapointers[MAX_QUERY_LENGTH];
int blockpointers[MAX_QUERY_LENGTH];
int docpositions[MAX_QUERY_LENGTH];
int numberdocs[MAX_QUERY_LENGTH];
int frequencies[MAX_QUERY_LENGTH];
int docarrays[MAX_QUERY_LENGTH][256];
int qsize;
// Snip
};
Looks like you should have another structure:
struct Info
{
int* iquery;
int* metapointers;
int blockpointers;
int docpositions;
int numberdocs;
int frequencies;
int docarrays[256];
};
And the QueryManager now looks like:
class QueryManager
{
INDEXCACHE *cache;
URLTABLE *table;
SNIPPET *snip;
int qsize;
Info details[MAX_QUERY_LENGTH];
};
This may help encapsulate themes a little better.
Your dependencies are probably not right, and the necessary files aren't getting rebuilt. Try a "clean" rebuild.
As a note to style, use initializer lists.
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname,
char *snippetfname, char *snippetbtfname) :
cache(new INDEXCACHE(indexfname, btfname)),
table(new URLTABLE(urltablefname)),
snip(new SNIPPET(snippetfname, snippetbtfname)),
qsize(0)
{
}
and you may not need to make those items pointers:
class QUERYMANAGER {
INDEXCACHE cache;
URLTABLE table;
SNIPPET snip;
...
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname,
char *snippetfname, char *snippetbtfname) :
cache(indexfname, btfname),
table(urltablefname),
snip(snippetfname, snippetbtfname),
qsize(0)
{
}
Have you built clean? Since accessing the last member variable blows up, but assigning to earlier ones works OK, either you're not constructing/allocating the instance right when you do use it, or you have object files that refer to older versions of the header that didn't have qsize in the object yet, and thus aren't allocating enough space. Or something along those lines.
As expected, this runs just fine on my machine:
#include <cstdlib>
struct INDEXCACHE {};
struct URLTABLE {};
struct SNIPPET {};
const std::size_t MAX_QUERY_LENGTH = 256;
class QUERYMANAGER {
INDEXCACHE *cache;
URLTABLE *table;
SNIPPET *snip;
int* iquery[MAX_QUERY_LENGTH];
int* metapointers[MAX_QUERY_LENGTH];
int blockpointers[MAX_QUERY_LENGTH];
int docpositions[MAX_QUERY_LENGTH];
int numberdocs[MAX_QUERY_LENGTH];
int frequencies[MAX_QUERY_LENGTH];
int docarrays[MAX_QUERY_LENGTH][256];
int qsize;
public:
QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname);
};
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname)
: cache(new INDEXCACHE(/*indexfname, btfname*/))
, table(new URLTABLE(/*urltablefname*/))
, snip(new SNIPPET(/*snippetfname, snippetbtfname*/))
, qsize(0)
{
}
int main()
{
QUERYMANAGER foo("blargl", "frxnl", "wrgxl", "brlgl", "srgl");
return 0;
}
So the error must be in the code you're not showing.
BTW, all upper-case names are boo except for macros. They're making your code harder to read and confuse everyone used to a more common coding style.