OK i have a function
int main
{
....
char *wordl=word();//wordl pointer is an array of characters
...
gamewindow(wordl,length);
}
void gamewindow(char &wordl,int length);
My question is how to pass pointer such that passed pointer points to the same array list..
and i can access it by wordl[i] in gamewindow function.
From the comment below, implementation of word():
char* word()
{ int j=1988497762; cout<<j<<endl ;
static char original[25];
int x;
ifstream fin("out.txt");
for (j=0;!fin.eof();j++)
fin.getline(original,25);
fin.close();
srand ( (unsigned) time(NULL) );
x = rand()%j; cout<<x<<"\n";
cout<<rand()<<endl;
char c;
ifstream finn("out.txt");
for (j=0; !finn.eof(); j++)
{ finn>>c; finn.getline(original,25); if (x==j) break; }
finn.close();
return original; }
If you really want to use it like this only (and not use std::vector or std::string) you need change gamewindow to void gamewindow(char *wordl,int length); Then you can access char using word1[i].
Better use std::string, std::vector and other standard containers. If on C++2011, use perhaps std::array
So declare instead
void gamewindow(std::string&str);
Related
If I create a two class members of char* type and is array. And if I resize first member of the class it overwrite the second member with same values.
Why it happens?
Is it some memory management issues?
#include <iostream>
using namespace std;
class myclass
{
private:
const char *arr1[0];
const char *arr2[4] {
"one",
"two",
"three",
"four"
};
public:
void run() {
int f = 0;
*this->arr1 = new char[4];
for(f = 0; f < 4; f++) {
this->arr1[f] = "foo";
}
for(f = 0; f < 4; f++) {
cout << this->arr2[f] << endl;
}
}
};
int main()
{
myclass *my = new myclass();
my->run();
return 0;
}
Output
foo
foo
foo
foo
const char *arr1[0];
Zero-sized arrays are not allowed in standard C++. Your compiler is allowing it as an extension to the language.
Even if your compiler has this extension, dereferencing an array of size 0 causes undefined behavior and you are doing this here:
*this->arr1 = new char[4];
I don't know what your intention here is, either you want
const char *arr1[4];
in which case *this->arr1 = new char[4]; is unnecessary or you want
const char **arr1;
in which case it should be this->arr1 = new const char*[4];.
You should not use char* to manage strings, use std::string instead, which does the memory management for you. Similarly, for multiple strings use std::vector<std::string> instead of char**.
There doesn't seem any reason to use dynamic memory allocation in main either. The same way as you should use std::vector to manage dynamically-sized arrays of objects instead of using new[]/delete[], don't use dynamic memory allocation to create single objects if you don't have a good reason for it and if you have to, use std::unique_ptr instead of raw new/delete.
int main()
{
myclass my;
my.run();
return 0;
}
This does the same without dynamic allocation.
I have 3 classes.
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
[custructor with/without param, display function - works well each one of it]
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
[custructor with/without param, display function - works well each one of it]
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
void afisare()
{
cout<<nr;
}
In main i have this:
piesa_c C(2, H,14,"TIPC",20);
C.afisare();
But this doesn't work.
I don't know if the "buf" was declared properly because the problem seems to be in last class.
Why?
Later Edit:
The entire code is here: http://pastebin.com/nx2FGSfe.
Now, i have this in main
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
The display function return this error
main.cpp:143:14: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
nr is not initialized in the piesa_c() constructor, meaning it will have an undefined value.
Instead of using a dynamically allocated array used a std::vector<piesa_b> instead. It will handle dynamic memory allocation and do the right thing when instances of piesa_c is copied. Using std::vector also means the nr member variable can omitted as that information can be obtained from vector::size() and the std::vector can be populated in the initializer list instead of in the constructor body:
std::vector<piesa_b> buf;
piesa_c(int n,
piesa_b *bu,
int aid,
char* tipi,
int pretzz) : piesa_a(aid,tipi,pretzz),
buf(bu, bu + nr) {}
And to invoke a member function on each element in buf:
// C++11 lambda, otherwise use
// std::vector<piesa_b>::const_iterator.
//
std::for_each(buf.begin(), buf.end(), [](piesa_b& pb) { pb.afisare(); });
If afisare() does not modify then make it const:
void afisare() const
{
}
Additonally, use std::string instead of char*. If you insist on having dynamically allocated members in the classes you need to obey the rule of three.
I am not sure what "not work" means in this context, but when you call this constructor:
piesa_c C(2, H,14,"TIPC",20);
the data member nr is not set. It can have any value that fits into an int, so when you use it to initialize an array you will get variable and weird results.
Note that you could save yourself a lot of trouble by using std::vector and std::string instead of dynamically allocated arrays and char*.
My code is already working, seen here: http://pastebin.com/mekKRQkG
Right now, my functions work but utilizing information that I've declared globally, I guess, and I want to convert them so that they are in the format as seen on lines 11-15, but I'm unsure of how to convert them to do so. Simply put, I'm trying to convert my function of
"void add_county_election_file"
to be in the format of
"void add_county_election_file(const string, const vector &, const vector &, const vector &, const vector &)"
and I have no idea where to begin or how to even start.
Could someone please help me out and show me how I'd do this for the first function, so I can implement it across the board?
Thanks guys!
Your function declaration should look something like this:
void add_county_election_file(const string, vector<int>&, vector<string>..);
Make sure that your argument list for the vector template is correct(that's the type you put between <>)
Then match the implementation of you function to the declaration:
void add_county_election_file(const string, vector<int>&, vector<string>..){...}
Now call your function with apppropriate arguemtns in main:
string s;
vector<int> arg;
vector<string> sv;
void someFunction (s, arg, sv ...);
I think you are doing correct as the function you have declared
void add_county_election_file(const string, vector<int>&, vector<int>&,..);
so you just have to call the above function with the required arguments, as right now you are not passing the argument and your current definition doesn't accepts any arguments.
And as a good practice, in your int main() function you can use switch rather than going for if else.
Store your variables and functions in a class, overload operators and create functions to access these variables.
Declare all variables in int main() and set parameters to be passed into each function e.g.
void print_results() is modified to become
void print_results(std::vector<int> vec, int nCount, etc..)
Similar to the first one, create a struct to hold all data members, then pass the struct(by ref) into each function.
struct CountryTracker
{
std::vector<int> ID;
std::string name;
//etc...
}
`void print_results(CountryTracker& Obj) //pass single struct into functions`
The OOP way to do this is to create a class called perhaps ElectionInfo, where:
These would be its member fields:
vector <string> countyNameVector;
vector <int> countyNCount;
vector <int> countyFCount;
vector <int> countyOCount;
int NCount;
int FCount;
int OCount;
int NTotal;
int FTotal;
int OTotal;
and these would be its member functions:
void add_county_election_file(const string);
void search_county(const string);
void print_results();
This way you don't have to pass the references to the vectors around at all, instead you can just do:
ElectionInfo an_elect_info;
char selection = get_menu_choice();
// some if-statements to decide which of the following to call:
an_elect_info.add_county_election_file(county_name);
an_elect_info.search_county(county_name);
an_elect_info.print_results();
But if you'd prefer to stay with the current functional approach:
Declare and initialize the following inside your main method:
vector <string> countyNameVector;
vector <int> countyNCount;
vector <int> countyFCount;
vector <int> countyOCount;
int NCount;
int FCount;
int OCount;
int NTotal;
int FTotal;
int OTotal;
The syntax for the commented out function declarations should be tweaked to look like this:
void add_county_election_file(const string, vector<string>&, vector<int>&, vector<int&, vector<int>&);
(Of course, the definition should follow suit)
You would invoke it like this:
add_county_election_file(countyname, countyNameVector, countyNCount, countyFCount, countyOCount);
Objects are automatically passed-by-reference.
The basic process of refactoring should at the first step involve only code grouping and placement and should only minimally involve writing new logic. Using this as a principle you can go about modifying the code in the following way at first.
string ReadInputString(const char* title)
{
string s
cout << title;
cin >> s;
}
void add_county_election_file(const std::string& filename
, std::vector<string>& countyNameVector
, std::vector<int>& countyNCount
, std::vector<int>& countyFCount
, std::vector<int>& countyOCount
)
{
int NCount = 0;
int FCount = 0;
int OCount = 0;
int NTotal = 0;
int FTotal = 0;
int OTotal = 0;
char vote;
std::ifstream input((filename).c_str());
string countyName;
if(input.is_open())
{
input >> countyName;
countyNameVector.push_back(countyName);
while(input >> vote)
{
if(vote == 'N' || vote == 'n')
{
NCount = NCount + 1;
}
else if(vote == 'F' || vote == 'f')
{
FCount = FCount + 1;
}
else
{
OCount = OCount + 1;
}
}
countyNCount.push_back(NCount);
countyFCount.push_back(FCount);
countyOCount.push_back(OCount);
}
cout << countyName << endl;
}
void add_county_election_file()
{
string fn = ReadInputString("Enter the county file to process: ");
add_county_election_file(fn,g_countyNameVector,g_countyNCount,g_countyFCount,g_countyOCount);
}
As you can see I have just extracted your code and moved them to individual functions and changed names to make some significance. Like in the function ReadInputString - the line "cin >> s" was originally "cin >> filename". The abstract name "s" is to signify that the ReadInputString has no knowledge or doesn't care what the semantic meaning of the string it is reading from console.
In order to not change your main function - I have added a overloaded add_county_election_file that calls one function followed by another. The idea is that you should keep something unchanged and change others (for good) and then alternate if need be.
And I have changed names of your global variable to differentiate them from the local variable using "g_" - the point is that "g_" should only be found at very few places in your code.
I want to make a function to allocate memory to an array. Suppose I have this:
PWSTR theStrings[] = { L"one", L"two", L"three" };
void foo(PWSTR a, int b) {
a=new PWSTR[b];
for(int i=0;i<b;i++) a[i]=L"hello";
return;
}
int main() {
foo(theStrings,4);
}
My question is, how do you make the function foo and the calling of that function so that after foo is called, theStrings will contain four "hello"
Thanks :)
Reinardus
There are two thing you must do to make this work:
Firstly, you must use a dynamically allocated array, rather than a statically allocated array. In particular, change the line
PSWTR theStrings[] = { L"one", L"two", L"three" };
into
PWSTR * theString = new PWSTR[3];
theString[0] = L"one";
theString[1] = L"two";
theString[2] = L"three";
This way, you're dealing with a pointer which can be modified to point to a different region of memory, as opposed to a static array, which utilized a fixed portion of memory.
Secondly, you're function should take either a pointer to a pointer, or a reference to a pointer. The two signatures look like this (respectively):
void foo(PWSTR ** a, int b); // pointer to pointer
void foo(PWSTR *& a, int b); // reference to pointer
The reference-to-pointer option is nice, since you can pretty much use your old code for foo:
void foo(PWSTR *& a, int b) {
a = new PWSTR[b];
for(int i=0;i<b;i++) a[i]=L"hello";
}
And the call to foo is still
foo(theStrings, 4);
So almost nothing must be changed.
With the pointer-to-pointer option, you must always dereference the a parameter:
void foo(PWST ** a, int b) {
*a = new PWSTR[b];
for(int i = 0; i<b; i++) (*a)[i] = L"hello";
}
And must call foo using the address-of operator:
foo(&theStrings, 4);
PWSTR theStrings[] = { L"one", L"two", L"three" };
void foo(PWSTR& a, int b) {
a=new PWSTR[b];
for(int i=0;i<b;i++) a[i]=L"hello";
return;
}
int main() {
PWSTR pStrings = theStrings;
foo(pStrings,4);
}
But instead of that, consider using std::vector and std::wstring and so on.
Also, anyway, consider using function result (the return) for function results, instead of in/out arguments.
Cheers & hth.,
If you are not required to use PWSTR then you can use std::vector< std::string > or std::valarray< std::string >.
If you want to store unicode strings (or wide characters) replace std::string with std::wstring.
You can see here on how to convert between CString/LPCTSTR/PWSTR to std::string: How to convert between various string types.
probably change it to something like
void foo(PWSTR * a, int b)
and
foo(&thestrings, 4);
I've tried the following:
char[10] testfunc()
{
char[10] str;
return str;
}
Best as an out parameter:
void testfunc(char* outStr){
char str[10];
for(int i=0; i < 10; ++i){
outStr[i] = str[i];
}
}
Called with
int main(){
char myStr[10];
testfunc(myStr);
// myStr is now filled
}
You have to realize that char[10] is similar to a char* (see comment by #DarkDust). You are in fact returning a pointer. Now the pointer points to a variable (str) which is destroyed as soon as you exit the function, so the pointer points to... nothing!
Usually in C, you explicitly allocate memory in this case, which won't be destroyed when the function ends:
char* testfunc()
{
char* str = malloc(10 * sizeof(char));
return str;
}
Be aware though! The memory pointed at by str is now never destroyed. If you don't take care of this, you get something that is known as a 'memory leak'. Be sure to free() the memory after you are done with it:
foo = testfunc();
// Do something with your foo
free(foo);
A char array is returned by char*, but the function you wrote does not work because you are returning an automatic variable that disappears when the function exits.
Use something like this:
char *testfunc() {
char* arr = malloc(100);
strcpy(arr,"xxxx");
return arr;
}
This is of course if you are returning an array in the C sense, not an std:: or boost:: or something else.
As noted in the comment section: remember to free the memory from the caller.
As you're using C++ you could use std::string.
With Boost:
boost::array<char, 10> testfunc()
{
boost::array<char, 10> str;
return str;
}
A normal char[10] (or any other array) can't be returned from a function.
When you create local variables inside a function that are created on the stack, they most likely get overwritten in memory when exiting the function.
So code like this in most C++ implementations will not work:
char[] populateChar()
{
char* ch = "wonet return me";
return ch;
}
A fix is to create the variable that want to be populated outside the function or where you want to use it, and then pass it as a parameter and manipulate the function, example:
void populateChar(char* ch){
strcpy(ch, "fill me, Will. This will stay", size); // This will work as long as it won't overflow it.
}
int main(){
char ch[100]; // Reserve memory on the stack outside the function
populateChar(ch); // Populate the array
}
A C++11 solution using std::move(ch) to cast lvalues to rvalues:
void populateChar(char* && fillme){
fillme = new char[20];
strcpy(fillme, "this worked for me");
}
int main(){
char* ch;
populateChar(std::move(ch));
return 0;
}
Or this option in C++11:
char* populateChar(){
char* ch = "test char";
// Will change from lvalue to r value
return std::move(ch);
}
int main(){
char* ch = populateChar();
return 0;
}
With c++17 you can use next code:
auto testfunc() {
union {
char str[14];
} res = { .str = "Hello, World!" };
return res;
}
and then use you string as
const auto str = testfunc();
std::cout << str.str;