I'm fairly new to coding and c++ and was working on a base maze game and making
it more efficient across the whole thing.
My question is basically instead of writing the same thing over and over to
define multiple structs the same way can I make something with an int on the
end that increments by 1 every loop to take position of the struct name somehow
or is this not possible?
This is my code if you are still confused by my poor explanation.
for (int g = 1; g < 30; g++)
{
if ( (x == wall(g).x && y == wall(g).y)
&& (player.x + 1 == wall1.x && player.y == wall1.y))
{
}
}
Above is the approximate idea I have come up.
I have declared many structs named (wall1, wall2, wall3, etc) at the top that
need to all run this argument.
You can use an array of struct and using index you can access to your desired struct in the runtime.
You also can try using switch-case.
That's all I have to help you.
You can inherit all your structs from a single ancestor and use a base pointer.
Alternatively, if you need to know the exact struct type, you can use RTTI.
But, of course, they cant have identical name.
Related
I wanted to create a function that would define an 1d Array, calculate a sum of the elements, and display that sum. I wrote the following code however I'm unaware of the use of pointers and other advanced techniques of coding.
#include <iostream>
using namespace std;
int main()
{
int size;
int A[];
cout << "Enter an array: \n";
cin << A[size];
int sum;
int sumofarrays(A[size]);
sum = sumofarrays(A[size]);
cout << "The sum of the array values is: \n" << sum << "\n";
}
int sumofarrays(int A[size])
{
int i;
int j = 0;
int sum;
int B;
for (i=0; i<size; i++)
{
B = j + A[i];
j = B;
}
sum = B;
return(sum);
}
When attempting to compile this code, I get following error:
SumOfArrays.cpp:19:18: error: called object type 'int' is not a
function or function pointer sum = sumofarrays(size)
If only you had used a container like std::vector<int> A for your data. Then your sum would drop out as:
int sum = std::accumulate(A.begin(), A.end(), 0);
Every professional programmer will then understand in a flash what you're trying to do. That helps make your code readable and maintainable.
Start using the C++ standard library. Read a good book like Stroustrup.
Please choose Bathsheba's answer - it is the correct one. That said, in addition to my comment above, I wanted to give some more tips:
1) You need to learn the difference between an array on the stack (such as "int A[3]") and the heap (such as a pointer allocated by malloc or new). There's some degree of nuance here, so I'm not going to go into it all, but it's very important that you learn this if you want to program in C or C++ - even though best practice is to avoid pointers as much as possible and just use stl containers! ;)
2) I'm not going to tell you to use a particular indentation style. But please pick one and be consistent. You'll drive other programmers crazy with that sort of haphazard approach ;) Also, the same applies to capitalization.
3) Variable names should always be meaningful (with the possible exception of otherwise meaningless loop counters, for which "i" seems to be standard). Nobody is going to look at your code and know immediately what "j" or "B" are supposed to mean.
4) Your algorithm, as implemented, only requires half of those variables. There is no point to using all of those temporaries. Just declare sum as "int sum = 0;" and then inside the loop do "sum += A[i];"
5) Best practice is - unlike the old days, where it wasn't possible - to declare variables only where you need to use them, not beforehand. So for example, you don't need to declare B or j (which, as mentioned, really aren't actually needed) before the loop, you can just declare them inside the loop, as "int B = j + A[i];" and "int j = B;". Or better, "const int", since nothing alters them. But best, as mentioned in #4, don't use them at all, just use sum - the only variable you actually care about ;)
The same applies to your for-loop - you should declare i inside the loop ("for (int i = ....") rather than outside it, unless you have some sort of need to see where the loop broke out after it's done (not possible in your example).
6) While it really makes no difference whatsoever here, you should probably get in the habit of using "++i" in your for-loops rather than "i++". It really only matters on classes, not base types like integers, but the algorithms for prefix-increment are usually a tad faster than postfix-increment.
7) You do realize that you called sumOfArrays twice here, right?
int sum;
int sumofarrays(A[size]);
sum = sumofarrays(A[size]);
What you really meant was:
const int sum = sumofarrays(A);
Or you could have skipped assigning it to a variable at all and just simply called it inside your cout. The goal is to use as little code as possible without being confusing. Because excess unneeded code just increases the odds of throwing someone off or containing an undetected error.
Just don't take this too far and make a giant mishmash or trying to be too "clever" with one-liner "tricks" that nobody is going to understand when they first look at them! ;)
8) I personally recommend - at this stage - avoiding "using" calls like the plague. It's important for you to learn what's part of stl by having to explicitly call "std::...." each time. Also, if you ever write .h files that someone else might use, you don't want to (by force of habit) contaminate them with "using" calls that will have an effect on other peoples' code.
You're a beginner, that's okay - you'll learn! :)
enum { WITH_ZERO };
auto copy_num = [](int n, char target[NUM_LEN]) -> int {
char temp;
for (int j = NUM_LEN - 1; j >= 0; j--) {
if ((temp = n % 10 + '0') == '0') {
return WITH_ZERO;
} else {
target[j] = temp;
n /= 10;
}
}
return !WITH_ZERO;
};
if (copy_num(i, num_copy) == WITH_ZERO) {
continue;
}
if (i * 3 > MAX_NUM) {
continue;
}
copy_num(i * 2, num_double);
copy_num(i * 3, num_triple);
//edit: changed 'goto' to 'continue'
The above is part of my code, which should show in what cases I would prefer to use nested lambdas. I can achieve similar to this with macros, but they do make my codes dirtier, while the lambdas used this way look more clean, without the '\'s. The 'copy_num' function here is only used locally and not anywhere else, so this has more readability than when defining 'copy_num' as a normal function outside. Lambdas can also conveniently catch outer variables if needed, in which case I can reduce repetitive function parameters, again making clearer code.
By using lambdas this way several times, I wondered whether it is a good or bad idea to use lambdas as an entire replacement to functions. Lambdas can work perfectly well as a more flexible form of functions possible to be nested or anonymous. In cases where what the lambdas do are of no difference than what a normal function of a same form would do, the compiler will be smart enough to compile them as if being plain functions.
Or perhaps future c/c++ will allow nested functions in general?
I do not think there is anything wrong with this approach. It is certainly safer than C'ish #define's, the savings in \s being the least advantage I can think of.
Until lambda support has matured, you may see compilers struggle to generate 'optimal' code though.
Lambdas can also conveniently catch outer variables if needed, in which case I can reduce repetitive function parameters, again making clearer code.
Yes, and once needed elsewhere, the lambda + capture can easily be migrated to a class that holds state and defines some operations on it.
Or perhaps future c/c++ will allow nested functions in general?
This is fully-fleshed support for nested functions. Remember, a lambda that does not capture can decay to a function pointer.
Should I be worried about having too many levels of vectors in vectors?
For example, I have a hierarchy of 5 levels and I have this kind of code
all over my project:
rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d]
where each element is a vector. The whole thing is a vector of vectors of vectors ...
Using this still should be lot faster than copying the object like this:
Block b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
// use b
The second approach is much nicer, but slower I guess.
Please give me any suggestion if I should worry about performance issues related to this,
or else...
Thanks
Efficiency won't really be affected in your code (the cost of a vector random access is basically nothing), what you should be concerned with is the abuse of the vector data structure.
There's little reason that you should be using a vector over a class for something as complex as this. Classes with properly defined interfaces won't make your code any more efficient, but it WILL make maintenance much easier in future.
Your current solution can also run into undefined behaviour. Take for example the code you posted:
Block b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
Now what happens if the vector indexes referred to by pos.a, pos.b, pos.c, pos.d don't exist in one of those vectors? You'll go into undefined behaviour and your application will probably segfault (if you're lucky).
To fix that, you'll need to compare the size of ALL vectors before trying to retrieve the Block object.
e.g.
Block b;
if ((pos.a < rawSheets.size()) &&
(pos.b < rawSheets[pos.a].countries.size()) &&
(pos.c < rawSheets[pos.a].countries[pos.b].cities.size()) &&
(pos.d < rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks.size()))
{
b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
}
Are you really going to do that every time you need a block?!!
You could do that, or you can, at the very least, wrap it up in a class...
Example:
class RawSheet
{
Block & FindBlock(const Pos &pos);
std::vector<Country> m_countries;
};
Block & RawSheet::FindBlock(const Pos &pos)
{
if ((pos.b < m_countries.size()) &&
(pos.c < m_countries[pos.b].cities.size()) &&
(pos.d < m_countries[pos.b].cities[pos.c].blocks.size()))
{
return m_countries[pos.b].cities[pos.c].blocks[pos.d];
}
else
{
throw <some exception type here>;
}
}
Then you could use it like this:
try
{
Block &b = rawSheets[pos.a].FindBlock(pos);
// Do stuff with b.
}
catch (const <some exception type here>& ex)
{
std::cout << "Unable to find block in sheet " << pos.a << std::endl;
}
At the very least, you can continue to use vectors inside the RawSheet class, but with it being inside a method, you can remove the vector abuse at a later date, without having to change any code elsewhere (see: Law Of Demeter)!
Use references instead. This doesn't copy an object but just makes an alias to make it more usable, so performance is not touched.
Block& b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
(watch the ampersand). When you use b you will be working with the original vector.
But as #delnan notes you should be worried more about your code structure - I'm sure you could rewrite it in a more appropriate and maintable way.
You should be worried about specific answers since we don't know what the constraints are for your program or even what it does?
The code you've given isn't that bad given what little we know.
The first and second approaches you've shown are functionally identical. Both by default will return an object reference but depending on assignment may result in a copy being made. The second certainly will.
Sasha is right in that you probably want a reference rather than a copy of the object. Depending on how you're using it you may want to make it const.
Since you're working with vectors, each call is fixed time and should be quite fast. If you're really concerned, time the call and consider how often the call is made per second.
You should also consider the size of your dataset and think about if another data structure (database perhaps) would be more appropriate.
I am currently working on a tool, that will compare two files and report its differences. I want to implement a feature that will compare two methods, and report if they are identical (while ignoring variable name changes ). What i have thought of doing, is to Normalize all the variable names to (x0,x1 ..) or something similiar. Then sort the methods ( Alphabetically? ) so that the order is the same. Grap their checksums and then compare the two.
My question:
How do i normalize variable names in a C / C++ file?
or
Do you have any other ideas as to how i could implement the feature?
Regards
You can map 'tokens' (variable names) to an 'interned form', as described above, if you can come up with a repeatable & stable ordering.
This doesn't attempt to understand how the tokens resolve, merely that they are present in the same pattern in two source-files. "Tokens" would be everything other than C/C++ reserved words, no serious parsing/ lexing necessary.
Once you have done that you can convert comments & whitespace to a canonical form.
This wouldn't mostly be of utility to me, but I believe it would achieve a 99.9% or better stab at the problem -- it's conceivable that it could be fooled, but practically not very likely.
Of course, if we have macros those have to handled too.. maybe you can run the C pre-processor on them to fulfill that, if that's a requirement?
Hope this helps.
Surely this is not about normalizing the names, but about figuring out if the two methods do the same thing to the same things within a class. Which means parsing the source code and building some sort of data structure [probably a "tree"] from that. Once you have the tree, the names as such will become meaningless. You may need to track for example what OFFSET into a class member variables are referring to, and which virtual functions within a class.
I don't believe this is at all trivial (unless you restrict the code to a small subset of C++ code), since there are so many different ways to make something do the same thing, and just subtle difference will throw off anything by the most sophisticated of tools. E.g.
class A
{
private:
int arr[10];
...
public:
int sum()
{
int r = 0;
for(i = 0; i < 10; i++)
r += arr[i];
return r;
}
}
class B
{
private:
int arr[10];
...
public:
int sum()
{
int r = 0;
int *p = arr;
for(i = 0; i < 10; i++)
r += *p++;
return r;
}
....
}
These two functions do the same thing.
What about using the temporary tree representation gcc generates during compilation, gcc has a command-line-switch to preserve temporary files:
gcc -save-temps <file>
This code is somewhat simplified and names are unified. The problem is to identify the differences in the original file.
Do not use Optimization!
I'm trying to learn C++ by doing everything "the C++ way". I'm writing a program where I have all of these known values (at compile time). Here is my problem:
In my constructor I want to check to see if a passed value(an int) is one of 2,4,8,16 or 32 and throw an error elsewise. I've though about:
making a C style array or ints
creating a vector before by hand and interating through it to check
making a list? I've never used lists before though.
What I really want to do is make a const vector in a separate header file, this doesn't seem possible though.
What is the most elegant way to do this check?
Also, similarly is there any way to make a vector with a set number of known values (at compile time) in a header? If I can do const std::string a_str("a string"); I don't see why I can't use a similar technique for vectors.
What's wrong with:
if (!(n == 2 || n == 4 || n == 8 || n == 16 || n == 32))
{
// no!
}
If you want the "C++ way", a static array should do, with find:
template <typename T, size_t N>
T* endof(T (&pArray)[N])
{
return &pArray[0] + N;
}
static const int OkNumbers[] = {2, 4, 8, 16, 32};
static const int* OkNumbersEnd = endof(OkNumbers);
if (std::find(OkNumbers, OkNumbersEnd, n) == OkNumbersEnd)
{
// no!
}
Modifying this list is simple, and I'm guessing the compiler may optimize this to my previous answer.
It's a bit of a trick, but I believe this works:
if (n & (n-1) != 0)
{
// not a power of two
}
If we're talking about bit twiddling sillyness, here's my try:
if ((n & 0x3E) != n || (n & n - 1) != 0)
throw std::runtime_error("not a power of two less than or equal to 32");
Bit twiddling sillyness is VERY C/C++, but only "elegant" if by elegant you mean "as few processor cycles as absolutely possible and in as terse a syntax as possible". Use a dictionary lookup or explicit check (such as std::find in GMan's answer), otherwise.
Readability is almost always preferrable to this kind of wackyness.
If you are really looking for doing it with a vector and want nice assignment operations have a look at boost::assign.
But you just really don't want to do it with a vector ;)
Edit: I just saw your "at compile time". Consider why this can't be done: std::vector isn't a built in type. To have a mechanism to use somekind of smart assignment like that would require to built in support for it for the whole language and every user-defined type. Even if you don't need core language support and can do it with Templates this wouldn't be consistent with the overall style of the STL.
Use a normal C array, my C is rusty but here goes
int array[] = {2,4,8,16,32};
/* now loop over the array and check */
for( i = 0; i< size_of_array ; i++) {
if (array[i] == input_int)
/* you get the idea ..... */
This might not fit the context of what you're trying to do, but you can use an enum.
Since this is compile time knowledge, I'll assume that these passed values are important at compile time. Using an enum, callers aren't trying to figure out what magic number to pass into your function.
typedef enum
{
Value1 = 2,
Value2 = 4,
Value4 = 8,
Value5 = 16,
Value6 = 32
} MyMagicType;
void MyFunction(MyMagicType theType)
{
...
}
The compiler will then enforce the value to be one of the above (well, unless you cast it, but that is a different matter) and throw an error should it not be one of the defined values.