I'm working on my new project now and I'm facing a weird problem. The problem seems to have two solutions - the first one which would take me, let's say, about 5 minutes, and the second one which would require some copying and pasting and take a lot of time.
However, I am not sure if the first solution is possible or not, and mainly, how it's possible.
I wasn't even able to briefly describe my problem to Google, but I'll try to describe it to you.
Let's say I have an variable x. Then I have another variable $9$ (it's name is 9, for example). I want variable $9$ to change it's value, when the value of variable x is equal to 9. The code:
int x = 9
char $9$ = 0
$x$ = 1 //this in not correct. This is just my idea. This line should do; char variable with the name which is equal to the value of int x changes its value to 1..
I can't use if (if (x == 9) $9$ = 1;) or switch because there are actually 600 possible values for int x and therefore also 600 char $value of x$ variables.. (well, thats the second solution).
I hope atleast somebody understood my issue, any ideas? Thank you very much for any help. Also, I'm sorry for my beginner's english, for being new to C++ and for being unable to google it. :D
It sounds like you want some sort of key-value store. That is, you have a runtime determined key, and you want to lookup / change some value based on that key. There's a few options included in C++ that can do this relatively easily.
Because your key is an int that is relatively restricted in range, we can use an array. We can also use a std::unordered_map (a hash table) or a std::map (a binary tree).
So... given one of these objects:
std::array<int, 600> data;
std::unordered_map<int, int> data;
std::map<int, int> data;
We could do:
int x = 9;
data[x] = 1;
Related
This question already has answers here:
How to write a switch statement for strings in Qt?
(3 answers)
Closed 6 years ago.
At this website I found an interesting way to create a switch statement with strings. However, this seems really long and drawn out. I wanted to know if it's possible to turn a particular string into an integer that can be used in a switch statement.
So psuedo code would be something like this
QString str = "spinbox_1";
switch stoi( str )
case 1543:
//code here
case 2343:
//code here
case 3424:
//code here
As #Slava mentioned it is not easily possible. The solution provided by author in mentioned link is probably the most practtical solution. But if you for some reason really need to do it other way and convert string into decimal number, you can use hashing metod. Please refer to below cityhash which is widely used (obviously you can use any other hashing function).
https://github.com/google/cityhash
This may be duplicate of:
How can I hash a string to an int using c++?
Try to look at this solution:
https://github.com/Efrit/str_switch/blob/master/str_switch.h
Unfortunately the description of this solution is avaliable only in Russian (at least I can't find one in English). It is based on computing hash of the string in compile-time. The only limitation it has is it supports strings with 9 character maximum length.
If I ever find myself in a similar situation, I use a map to define a specific int from the given string.
For Example:
// The string you want to convert to an int
std::string myString = "stringTwo";
// The mapping that you set for string to int conversions
std::map<std::string, int> stringToInt = \
{{"stringOne" , 1},
{"stringTwo" , 2},
{"stringThree", 3}};
// Here, myInt is define as 2
int myInt = stringToInt[myString];
Now you could put myInt into a switch case.
No, it is not possible to map a string to an integer uniquely in general - there are simply more strings than integers. You may calculate hash which unlikely to collide for 2 different string and then compare them, but it is still possibility that 2 different strings have the same hash, so you have to compare that strings after you check their hashes. This is how std::unordered_set or std::unordered_map are implemented (aka hash_set and hash_map) so you can use them. But you would not use switch() statement.
I am trying to create a C++ program that will move an X on a 4x4 grid and display each move. We are not allowed to use arrays because we haven't learned how yet. I know that I am supposed to use 16 if/else statements, but I am not sure what to do from there. I know there is an easier way than mapping out each possible option because that would take forever!!! What do I do???
EDIT: It is only allowed to move up/down/left/right. And what I mean by display each move it is first supposed to display the user's starting point (which I've already set up) and then it is supposed to print grids with successive moves on them including all of the previous moves until it reaches the end point.
Note: I originally wrote this answer based on assumptions about the task that turned out to be wrong. However, I'll leave the answer up as I believe it might still contain useful information for the OP.
When you have x different possible situations, you don't always need an if/else with x branches. The trick is to find a way to use the same computation (typically one or more mathematical expressions, and possibly loops) to handle all or most of the situations.
In this case, there are indeed 16 different positions on a 4x4 grid, and one way to represent a position is to store its row and column number (each a value between 0 and 3). By using two loops, one inside the other (nested loops), you can generate all 16 combinations of row and column position. I'll assume now that you're supposed to print e.g. . on the empty cells of the grid. Inside the inner loop, you need to figure out whether you should print a . or an X. What question should you ask in order to figure that out? Simply "is the row and column number that the nested loops are currently at the same row and column number as the location of the X?"
Edit after seeing your update: Even when working with a grid, arrays are only needed when you have to store information about every cell, so one can sometimes get away without an array if you can generate the grid information from fewer pieces of information (such as the position of the X). However, if you need to keep track of the previous positions, you need an array (either one- or two-dimensional) in order to do it elegantly. I would say that the "no arrays" restriction of this task is not educational, as it forces an unnatural and very cumbersome way to solve this task. :-( (However, if your instructor subsequently gives the same task and allows you to use loops, it will be a good demonstration of why loops are useful.)
What you could do is to use 16 bool variables (all set to false initially) with names such as grid00, grid01, grid02, grid03, grid10, ..., grid33. Then make two methods, bool isOccupied(int row, int column) and void occupy(int row, int column) that use 16-way if/else statements to allow you to easily read and change the variable that corresponds to a given position.
I know that I am supposed to use 16 if/else statements, but I am not
sure what to do from there.
If this is a constraint on your solution given to your by your instructor, that means that you will need to handle each of the 16 possible grid locations in a separate {} block. You'll have to have an enum representing each of the pairs. like:
e_1_1, e_1_2, e_1_3, e_1_4,
e_2_1, e_2_2, e_2_3, e_2_4,
e_3_1, e_3_2, e_3_3, e_3_4,
e_4_1, e_4_2, e_4_3, e_4_4,
and you'll have to manually update the current position to a new one in the switch statement. Keep track of your current position in a variable called something like 'position'.
I know there is an easier way than mapping out each possible option
because that would take forever!!!
Welcome to programming. ;-)
Copy and paste is your friend and this problem of having to write a lot of similar but slightly different code is fairly common to many programming tasks. Becoming a good programmer means learning how to avoid largely duplicate code when possible. You are not there yet, or you wouldn't have to ask. So this first step will be an important lesson for you. A bit of pain will help you appreciate how much better the approach you will use the next time will be.
But this isn't that much work. An experienced C++ programmer could knock this out in less than 5 to 10 minutes. Moderately experienced, perhaps 20 to 30. It might take a learning programmer a few hours or more.
There are more concise ways to handle this problem without requiring 16 separate blocks, however, none of them are easier to understand. If this a requirement for a class learning project, then you will find it beneficial to do it first this way, then as a next step, try to do it with more complex logic.
Suggestions
An experienced programmer would define the move possibilities as an enum. Then the moves would be handled inside the {} blocks for the if statements using a switch statement that handled each of the four enums corresponding to the four moves. If you don't know the switch statement yet you can use an if ... else if ... else if ... that checks for each of the four moves.
Start with handling just the first upper left corner position moves for a smaller 2 x 2 grid. Then add each of the other three positions for the 2 x 2 grid. Once you have that working you should be able to understand easily how to extend the solution to a 4 x 4 and arbitrarily larger grid.
You'll want to have a function that prints the position array that gets called after every move. For now, you'll have to check the value of the enum and print manually. Something like:
Is position == e_1_1? print '* else print '_'
Is position == e_1_2? print '* else print '_'
Is position == e_1_3? print '* else print '_'
Is position == e_1_4? print '* else print '_'
print a newline
Is position == e_2_1? print '* else print '_'
Is position == e_2_2? print '* else print '_'
Is position == e_2_3? print '* else print '_'
Is position == e_2_4? print '* else print '_'
etc.
Some pointers for easy debugging:
Set the values for an enum for up, down, left, and right to something you can print out and follow easily, i.e. e_up = 'u' and e_down = 'd'. That will make it easier to debug if you don't have an IDE that will let you easily see the enum values, and you can print out the moves directly in the beginning.
Make your changes to the code in small increments. Run the code and once you know that the part you added works, move on. If you add too much at once it is much harder to figure out where things are broken, especially when you are new.
Future Solution with Arrays
Some hints: You'll want to use a two-dimensional array.
Try this on a 2 x 2 array first to make your life simpler. Then when the logic works, change the array size. To make this process easier use a const integer to define a value that you use to define the arrays and the printing using a for loop so that when you change the constant from:
const int array_size = 2
to
const int array_size = 4
the rest of the code will just work. For extra credit, support arrays of differing height and width by using separate constants for array_height and array_width. Learn to do it well and the way a pro would do it and you'll develop pro habits and earn pro wages much more quickly.
Remember to use a for loop for printing the rows and columns that uses the constants you defined.
You'll want to have the code running a loop looking for input, then processing the move, then printing out the new grid.
I am using scintilla's lexing capabilities and I want to do something a bit out of the box.
Please mind that even though i have a bit of experience in other languages I am a beginner C++ coder.
I am looking for pointers on how to save specific information about a line for later used.
The first idea that came to mind is to create an array and filling the corresponding array field for our line number, eg:
int lineOpt[];
...
lineOpt[20] = 20;
lineOpt[21] = 20;
lineOpt[372]= 75;
...
But something doesnt seem right here. I am not sure if this is the correct way to it not only because of the 'unlimited' size array i just created but also because of the 'gaps' that will be present.
Only a few specific lines will have those options set (depending on some text present in them) and again I have a feeling that this could be done another way.
Any help or pointers to some article would be appreciated.
It sounds like you need an associative container structure, not an array. Arrays are always of a fixed length set at compile time; you cannot change their size at run time. Your declaration int lineOpt[] is not legal.
Consider std::map<unsigned int, unsigned int> or std::unordered_map<unsigned int, unsigned int>.
I need to append a number at the end of the word flare depending on how many I have. That part works great. My problem is when I go to print it to the screen. I would like the program to output the value of what (Camera::Table[Id]->sensor->flare1) sensor is pointing at, in this case, flare one. If the program were to continue it would output the value pointing at flare2, flare3, flare4,... until the limit is reached.
What I get as the output is the following:
lens_pos1=¨Camera::Table[Id]->sensor->flare1¨
lens_pos2=¨Camera::Table[Id]->sensor->flare2¨ .......
How can I output the value of flare1 instead of pasting the string?
What I want is the following:
lens_pos1=¨10.3¨ lens_pos2=¨12.4¨.....
Where the values 10.3, 12.4 would be those of flare1 and flare2 respectively taken from a seperate C file.
for(int i = 1; i <= nbflares; i++)
{
char integer_string[32];
sprintf(integer_string, "%d", i);
char flare[100] = "Camera::Table[Id]->sensor->flare";
strcat(flare,integer_string);
fprintf(yyout, "lens_pos%d=\"%s\" ",i,flare);
}
You can't access a variable like that in C/C++. You have to redesign the "sensor" structure to contain an array instead of individual flares, and access the array by index: Camera::Table[Id]->sensor->flare[1], Camera::Table[Id]->sensor->flare[2], etc.
That can't be done in C++. Some interpreted languages might allow such things because the text of the source code still exists while the program is running. But in C++, when you compile a program all the names of classes and variables and such are essentially lost. When it gets to the point of a running executable, the actual machine instructions are just working with offsets and memory addresses.
So you need re-design how the data is stored.
Is there a way to access them without the use of arrays?
Technically, yes. But only by using a more complicated scheme that would involve a more complicated data structure (such as a linked list or map).
Why would you want to avoid arrays anyway? Right now you have a series of variables of the same type that you want to distinguish by the number are the end of their names. And an array is a series of variables of the same type that are distinguished by their index in the array. It's pretty much a perfect match.
For example, if you had a flares array, then you could simply do something like:
for(int i = 0; i < nbflares; i++)
{
fprintf(yyout, "lens_pos%d=\"%f\" ", i, Camera::Table[Id]->sensor->flares[i]);
}
I've got a list of number that I need to keep track of. The numbers are loosely related, but represent distinctly different items. I'd like to keep a list of the numbers but be able to refer to them by name so that I can call them and use them where needed easily. Kind of like an inventory listing, where the numbers all refer to a part ID and I'd like to call them idPart1, idPart2, idPart3 so their purpose is easily identifiable when they are used.
What would be the best way to do this?
1)Define a structure. Say, Inventory. A number of int members will be included, part1, part2 etc. To use, an instance of the structure will be created, values assigned to the members, and the numbers will be used by saying struct.member as needed.
2)Define an enumeration. Use part1, part2 as the enum literals. Store the actual values in a vector or list, each one at the index corresponding to the value of the number's name within the enum. Use the enum literals to retrieve the values, list[enumLit].
3)Something completely different
There's nothing else I need to do with the numbers - just look them up every once in a while. Since there's no processing, I kind of think a new class for them is overkill, but I'm willing to be convinced otherwise.
Any suggestions?
Let me try to rephrase what you're trying to do here. You want developers who use your code to be able to refer to a pre-defined set of numeric values:
using intuitive names
that will be validated at compile time
and that the IDE will recognize for the sake of code completion.
If the values will not change at run-time, and they are integer values, you can use an enum as Mark Ransom showed.
If the values will not change at run-time, and they are non-integer values, you can use either #define or const variables:
#define PART1 1.3
#define PART2 "1233-456"
or
namespace PartNumbers
{
const double Part1 = 1.3;
const char* Part2 = "123-456"
}
If the values may change at run-time, you can use either of the two options you identified. Both of these options have the drawback of requiring an object to be instantiated which holds the current part number values. The other options are simpler to implement and don't require any run-time lookup. Everything is resolved at compile time.
All of these options require users of your code to recompile if they are to access new part types. Your first option may require existing code to be recompiled when new part types are added, even if the existing code doesn't access them; it's more prone to memory layout changes.
You can use a map with a string as the key.
std::map<string,int> mymap;
mymap["part1"] = value1;
cout << mymap["part1"];
You could use the:
std::map<string, int> someMapName;
with the key as the string and the actual number as the int. That way you could do you could use
someMapName["idPart1"]
to grab the number.'
EDIT:
If you are ok with Enumerations then option 2 would work perfectly with the std::map just instead of string, the key would be your enum type obviously.
Based on your comments to the other answers, I'd say enums are the way to go, but I'd structure them a little differently.
namespace id {
enum {
part1 = 123,
part2 = 456,
part3 = 987,
...
};
}
cout << id::part1;
Use a database.
Specifically, a table like the following:
+------------------+-------------------+
| Item Name | Item Number |
+------------------+-------------------+
Internally, this can be represented as:
std::map<std::string, // The item name
unsigned int> // The number.
When you want the number, retrieve it using the name:
std::map<std::string, unsigned int> index_by_name;
//...
std::string part_name = "Part0123";
unsigned int part_number = 0;
part_number = index_by_name[name];
Seriously, use a database. Check out SQLite and MySQL.