Basically I am trying to make an array which will get larger every time the user enters a value. Which means I never know how long the array will be. I don't know if this is something to do with my class or anything.
#pragma once
#include <iostream>
#include <string>
#define dexport __declspec(dllexport)
//Im making an DLL
using namespace std;
class dexport API {
private:
string users[] = {"CatMan","ManCat"}; //Line With Error Incomplete Type Is Not Allowed
public:
string getAllUsers(string list[]) {
for (unsigned int a = 0; a < sizeof(list) / sizeof(list[0]); a = a + 1) {
return list[a];
}
}
};
It gives me an error Incomplete type is not allowed. I really have no idea what to do.
Compiler Error
There are a few things wrong with your code. For starters, an array has a fixed size, so, even if your code did compile, it wouldn't work. Normally, the compiler would infer the size of your array from the length of the initializer; but you are creating a class, and it needs to know it, hence the error.
This will solve your compilation problem:
string users[2] = {"CatMan","ManCat"};
But then your array has a fixed size, and that is not what you want, so you need an std::vector:
#include <vector>
[...]
vector<string>users = {"CatMan","ManCat"};
Now you can use the '[]' operator to access the strings, and users.push_back to add new users.
The next problem you need to solve is the way you are trying to return your value: you shouldn't use an argument as an out value (although you can, with either a reference or a pointer). You should decide whether you want to return a reference to your vector, a copy of your vector, or a const reference, for example:
// Returning a copy
vector<string> getAllUsers() {
return users;
}
// Returning a reference
vector<string>& getAllUsers() {
return users;
}
Finally, you are creating a library: you should know that if you want to share memory between different processes, you need to use some kind of shared memory. Currently, every program will keep its own copy of the API.
What you are looking for is an std::vector.
You can find more info here.
It's somewhat similar to an array, except that it allows variable length.
You can use std::vector. It allocate and copy elements to new place if it got out space.
If you wanna make the class yourself for educational reason here is what you should try as a basic solution:
You allocate some memory up front and store its length as capacity. You need a variable(size) to store the number of elements already entered to the class e.g. via a push_back function. Once the size reached capacity, you need to reallocate memory copy over all the elements and then delete the old memory.
Related
I have an assignment that is due about a week from now. It is about making a letter counter (cases don't matter) of text file in the directory the source file is. Then the output of the letters should be, first, according to the letter with highest number of occurrences of it, and, second, if there are letters with the same number of occurrences, then sorting will be according to the alphabetical order. The assignment page is here: http://www.cs.sfu.ca/CourseCentral/135/tjd/a1.html. I already did a program that has the same output (here it is: https://drive.google.com/file/d/0BxuBN4fpoq5LNHIwR2U2elVkdVE/view?usp=sharing). The thing is, as what you can see from the assignment page, is that my proffisor is insisting that we use a vector, Freq_table, that has pointers to a structure, char_count. I tried to do simple code to add elements to the vector, like this:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <vector>
using namespace std;
struct char_count {
char c;
int count;
};
typedef vector<char_count*> Freq_table;
int main () {
char_count A_count = {'A', 0};
Freq_table.push_back (A_count);
}
But the compiler always gives this message:
error: expected unqualified-id before '.' token
Freq_table.push_back (A_count);
I can't seem to solve this error. All I need for now is to know what is the syntax of adding elements to a vector that has pointers to a structure.
Regards.
What you are doing is wrong, you are doing something like
int.push_back(A_count);
Furthermore, you tell your vector that you want to store a pointer to a char_count-variable, but you store the variable itself, therefore resulting in another error.
Before you can push values into a vector, you have to declare it. A possible (untested) solution would be
Freq_table newTable;
newTable.push_back(&A_count);
You've declared Freq_table as a type, not an instance, so change:
typedef vector<char_count*> Freq_table;
to:
vector<char_count*> Freq_table;
To add to the table, you have to pass the address of a char_count instance. One way is:
char_count* A_count = new char_count; // allocate a new instance...returns the address.
A_count->c = 'A';
A_count->count = 0;
Freq_table.push_back(A_count);
Don't forget you will have to delete the instances in the vector if allocated with new or you will have memory leaks.
The only redeeming part of that assignment is that you aren't actually required to use dynamic memory. You can use the vector of pointers for only the one purpose it is reasonably well-suited, namely for getting the letters sorted by descending frequency.
The pointers in the vector will be non-owning pointers. It is appropriate to use a raw pointer for non-owning pointers, since that can't cause a memory leak.
Something like this:
int main(void)
{
char_count dictionary_order[26];
for( int i = 0; i < 26; ++i ) dictionary_order[i] = {'A'+i, 0};
/* read the input, count letters.
Notice that the matching letter is always at index ch-'A' */
Freq_table frequency_order;
for (auto& item : dictionary_order) frequency_order.push_back(&item);
sort(frequency_count.begin(),
frequency_count.end(),
[](char_count* a, char_count* b) -> bool
{
return (a->count == b->count)? (a->c < b->c) : (a->count > b->count);
}
);
/* print them out */
}
No dynamic allocation, therefore no leaks. And because C++ destroys local variables in the opposite order of declaration, the pointed-to objects will exist longer than the pointers themselves do.
If you needed to accommodate a variable number of items, you could have a vector<char_count> that manages the memory, and store pointers to those in your mandated vector of pointers. Of course, pointers become invalid if the vector is resized, so you'd build the entire "real" vector before starting to fill the pointer vector.
I apologize if this question has been asked/answered elsewhere, but I didn't find anything since I'm not entirely sure what/how to ask this...
What I'm attempting to do is set up some kind of container; list, array, vector, what-ever, that will allow me to place and remove objects from specific indices.
Something like this:
[empty][empty][object][empty][object][object][empty]
I'm going to be moving objects from a vector into a specific index of this container and from this container to another vector.
What would be the best way to represent this and what kind of container would be best suited? I was originally using a vector, but the built in functions didn't seem to give me enough control over where the object ended up. It was either the front or the back.
I need to figure out the best way to hold those "empty" indices and move objects in and out of each element freely.
A simple, definitely sub-optimal, but quite effective solution could be to use a vector in the following way:
#include <iostream>
#include <vector>
using namespace std;
struct Your_Object
{
Your_Object& operator=(const Your_Object& other)
{
// Write a proper assignment operator here if you want to assign or swap values
cout << "hello from assignment operator"<<endl;
return *this;
}
};
int main() {
Your_Object nullObj;
std::vector<Your_Object> vec;
vec.reserve(10); // Creates 10 empty objects calling default constructors. Notice that this will NOT affect the vector's size, for that use resize()
Your_Object space5, space3; // Two objects to put in space5 and space3
// Put objects in space 5 and 3
vec[5] = space5;
vec[3] = space3;
// Move object in space 5 to another place
vec[1] = vec[5];
return 0;
}
http://ideone.com/YDu6LC
If you manage to write a proper copy-assignment operator (perhaps with move semantics if you're using C++11) which does a deep-copy of your object and if of course this proves to be not too burdensome for you, the above might be a simple working system for what you need to do.
Just remember to resize (or reserve, for the difference take a look here: https://stackoverflow.com/a/7397862/1938163) the space you need in advance.
If I understand your question correctly you want to place data in your vector according to a certain pattern.
You can use a simple vector and implement functions yourself to place your data.
For example if you want to place data in every third place :
void placeItem(std::vector<int> my_vector, int element, unsigned int index){
my_vector[((index+1)*3)-1]=element;
}
int retreiveItem(std::vector<int> my_vector, unsigned int index){
return my_vector[((index+1)*3)-1];
}
Then you can use placeItem and retreiveItem with indexes starting at 0.
If you simply meant that you want to place your data in arbitrary locations then you can use the [] syntax directly.
I'm trying to create an array and pass it to functions, which then return it, but I don't know the correct way of returning.
I've been looking around tutorials and trying stuff out, but haven't managed to solve this.
I'm new to C++ and thought it would be similar to Java, but apparently it isn't.
This is where I've gotten:
class MainClass {
public:
static int countLetterCombinations(string array[], int numberOfWords) {
// Code
return totalCombos;
}
// This is the function I'm having trouble with.
static string** sortCombos(string combinations[][3]) {
// Do something
return combinations; // This gives converting error.
}
};
int main() {
// Code
int numberOfCombinations = MainClass::countLetterCombinations(words, numberOfWords);
string combinations[numberOfCombinations][3];
combinations = MainClass::sortCombos(combinations);
// Further code
}
Anyone know how to fix this?
You need to use a vector. C++ stack-based arrays cannot be dynamically sized- oh, and you can't convert [][] to **, the conversion only works for the first dimension. Oh, and you can't assign to arrays, either.
The simple rule is, in C++, never use primitive arrays- they're just a headache. They're inherited from C, which actually defined a lot of it's array behaviour for source compatibility with B, which is insanely old. Use classes that manage dynamic memory for you, like std::vector, for dynamically sizable arrays.
std::vector<std::array<std::string, 3>> combinations(numberOfCombinations);
static void sortCombos(std::vector<std::array<std::string, 3>>& combinations) {
// Do something
} // This function modifies combinations in-place and doesn't require a return.
Oh, and you really don't have to make functions static class members- they can just go in the global namespace.
Your sortCombos method can modify the array parameter in-place, and the caller will see those changes directly. Because you doesn't need to return anything, you should change the return type to void.
Even if you could return input array, you can't assign to combinations.
Sorry if the title is not clear but I ll explain now my problem. I am new in C++.
I have created a class in C++. Instances of that class are the input of the program and they have to be stored in an array to perform the calculations. The problem is that the number of instances of that class that have to be defined by the user is fixed for a single run but can vary from run to run. Here an example:
#include <<blablah>blahblah>
int main()
{
int number_of_instances = 3;
MyClass first_instance(one_parameter_1, another_parameter_1);
MyClass second_instance(one_parameter_2, another_parameter_2);
MyClass third_instance(one_parameter_3, another_parameter_3);
///////////////////
NOW I HAVE TO STORE ALL THREE IN AN ARRAY LIKE
MyClass array[number_of_instances] = {first_instance, second_instance, third_instance};
THE PROBLEM IS THAT I DO NOT KNOW BEFORE HAND HOW MANY OF THEM ARE THE USER IS GOING TO INPUT
///////////////////
performCalculations(array);
return 0;
}
Thanks a lot in advance.
The typical C++ solution is to use a vector.
vector<MyClass> v;
v.push_back(first_instance); //add an already instantiated object to the end of the vector
v.push_back(second_instance);
v.push_back(third_instance);
You won't have to worry about memory management and you are able to access the vector like you would a normal array:
v[0].classMember
You can also add items to the vector in a loop if needed like so:
for(int i = 0; i < 5; i++){
v.push_back( MyClass(i, param2) );
}
And all the objects will be destructed when the vector goes out of scope if you're storing the objects directly in the vector.
One of the downsides to storing the objects directly in the vector is passing the vector as a parameter to a function. This will be a slow operation since the vector (and all the objects it holds) will have to be copied.
If you know the number of instances before you read them all in then you can allocate an array on the heap using new[]. (Don't forget to delete[] them when you've finished.) Note that this requires that the object have a default constructor.
you should use std::vector in this case rather than a built-in array.
#include <vector>
...
std::vector<MyClass> v = {first_instance, second_instance, third_instance};
...
v.push_back(fourth_instance);
If you don't know how many elements the array will contain, I would use a std::vector instead of a plain array as the vector will grow to accommodate the additional elements.
What you want is the Vector class from the standard template library, it behaves like an array but it will re-size itself if you fill it's internal allocation. If you do not need random access to it (i.e. use the [] opperator) you may want to use the List class instead. If you use List you will need to create an enumerator to step through it.
use std::vector<MyClass>, vector template can be found in <vector> header. YOu must learn a little bit to code well, before coding use any of online available c++ FAQs
I'm reading in values from a file which I will store in memory as I read them in. I've read on here that the correct way to handle memory location in C++ is to always use new/delete, but if I do:
DataType* foo = new DataType[sizeof(DataType) * numDataTypes];
Then that's going to call the default constructor for each instance created, and I don't want that. I was going to do this:
DataType* foo;
char* tempBuffer=new char[sizeof(DataType) * numDataTypes];
foo=(DataType*) tempBuffer;
But I figured that would be something poo-poo'd for some kind of type-unsafeness. So what should I do?
And in researching for this question now I've seen that some people are saying arrays are bad and vectors are good. I was trying to use arrays more because I thought I was being a bad boy by filling my programs with (what I thought were) slower vectors. What should I be using???
Use vectors!!! Since you know the number of elements, make sure that you reserve the memory first (by calling myVector.reserve(numObjects) before you then insert the elements.).
By doing this, you will not call the default constructors of your class.
So use
std::vector<DataType> myVector; // does not reserve anything
...
myVector.reserve(numObjects); // tells vector to reserve memory
You can use ::operator new to allocate an arbitrarily sized hunk of memory.
DataType* foo = static_cast<DataType*>(::operator new(sizeof(DataType) * numDataTypes));
The main advantage of using ::operator new over malloc here is that it throws on failure and will integrate with any new_handlers etc. You'll need to clean up the memory with ::operator delete
::operator delete(foo);
Regular new Something will of course invoke the constructor, that's the point of new after all.
It is one thing to avoid extra constructions (e.g. default constructor) or to defer them for performance reasons, it is another to skip any constructor altogether. I get the impression you have code like
DataType dt;
read(fd, &dt, sizeof(dt));
If you're doing that, you're already throwing type safety out the window anyway.
Why are you trying to accomplish by not invoking the constructor?
You can allocate memory with new char[], call the constructor you want for each element in the array, and then everything will be type-safe. Read What are uses of the C++ construct "placement new"?
That's how std::vector works underneath, since it allocates a little extra memory for efficiency, but doesn't construct any objects in the extra memory until they're actually needed.
You should be using a vector. It will allow you to construct its contents one-by-one (via push_back or the like), which sounds like what you're wanting to do.
I think you shouldn't care about efficiency using vector if you will not insert new elements anywhere but at the end of the vector (since elements of vector are stored in a contiguous memory block).
vector<DataType> dataTypeVec(numDataTypes);
And as you've been told, your first line there contains a bug (no need to multiply by sizeof).
Building on what others have said, if you ran this program while piping in a text file of integers that would fill the data field of the below class, like:
./allocate < ints.txt
Then you can do:
#include <vector>
#include <iostream>
using namespace std;
class MyDataType {
public:
int dataField;
};
int main() {
const int TO_RESERVE = 10;
vector<MyDataType> everything;
everything.reserve( TO_RESERVE );
MyDataType temp;
while( cin >> temp.dataField ) {
everything.push_back( temp );
}
for( unsigned i = 0; i < everything.size(); i++ ) {
cout << everything[i].dataField;
if( i < everything.size() - 1 ) {
cout << ", ";
}
}
}
Which, for me with a list of 4 integers, gives:
5, 6, 2, 6