C++, need help with pointers created with strcat! - c++

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]);
}

Related

C++ Assigning variables with 'compound names' using an external argument

I'm trying to read a .pdb file and hence I'm ending with a lot of variables in my code. In an effort to reduce them (and avoid Segmentation fault errors) I was wondering if I could assign array names in my code using an external argument.
The starting bit of my code foo.cpp looks like this-
/*All the relevant headers*/
using namespace std ;
int main(int argc, char *argv[])
{
ifstream input(argv[1],ios::out) ;
string first(argv[2]) ;
string second(argv[3]) ;
string "first"ATOM[1000] ;
string "second"ATOM[1000] ;
}
And I'm hoping that if I launch the program as ./foo.exe input C O, I want two arrays called CATOM and OATOM to be initialised.
If there is no second argument then the OATOM array should not get defined.
This would save me the trouble of having to make multiple arrays such as NATOM[1000], OATOM[1000] etc. since I can define them within the program.
Is this possible? For each 'O', 'C', 'N' etc there need to be about 8-10 long string arrays which is causing it to blow up.
I'm new to programming and I hope this question makes sense.
Thanks in advance!
I suggest creating a struct with array and a string variable containing the name of that array and then you just search the structs by name.
A more elegant solution is using std::map like #NathanOliver suggested. Runtime changes of variable names are not possible (or logical) within c++ as far as I know.
It is not possible to change or set variable names at run time.
However, map (also known as dictionary or associative array) is a data structure that allows you to associate key objects (such as a string) to value objects (such as an array) and it possibly fits your needs. There is an implementation of map in the standard library, that you can use.

`ncurses` function `wgetstr` is modifying my variables

SOLUTION Apparently, the wgetstr function does not make a new buffer. If the second argument is called data and has size n and you give an input of more than n characters, it will access and overwrite parts in memory that do not belong to data, such as the place in memory where cursorY is stored. To make everything work, I declared data with char data[] = " "; (eight spaces) and wrote wgetnstr(inputWin, data, 8);.
--------------------------------------------------------------------------------------------------------------
It seems that the ncurses function wgetstr is literally changing the values of my variables. In a function called playGame, I have a variable called cursorY (of type int) which is adjusted whenever I press the up- or down-arrow on my keyboard (this works fine).
Please take a look at this code (inputWin is of type WINDOW*):
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
wgetstr(inputWin, data);
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
Suppose I move the cursor to the 6th row and then press Enter (which causes this piece of code to be executed). There are two things I can do:
Input just 1 character. After both refresh calls, the value 6 is shown on the screen (at position (0, 0)).
Input 2 or more characters. In this case, after the first refresh call I simply get 6, but after the second, I magically get 0.
The first two lines after the code above are
noecho();
_theView -> _theActualSheet -> putData(cursorY-1, cursorX/9 - 1, data);
(don't worry about the acutal parameters: the math regarding them checks out). While I'm in putData, I get a Segmentation fault, and gdb says that the first argument of putData was -1, so then cursorY had to be 0 (the first two arguments of putData are used to access a two-dimensional array using SheetCells[row][column], where row and column are, respectively, the first and second formal parameter of putData).
Clearly, wgetstr modifies the value of cursorY. The name of the latter variable doesn't matter: changing it to cursorrY or something weird like monkeyBusiness (yes I've tried that) doesn't work. What sort of works is replacing the piece of code above with
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
int a = cursorY;
wgetstr(inputWin, data);
cursorY = a;
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
In both cases I see 6 at the top-left corner of my screen. However, know the string is acting all weird: when I type in asdf as my string, then move to the right (i.e., I press the right key on my keyboard), then type in asdf again, I get as^a.
So basically, I would like to know two things:
Why the HELL is wgetstr changing my variables?
Why is it only happening when I input more than 1 character?
What seems to be wrong with wgetstr in general? It seems terrible at handling input.
I could try other things (like manually reading in characters and then concatenating data with them), but wgetstr seems perfect for what I want to do, and there is no reason I should switch here.
Any help is much appreciated. (Keep in mind: I specifically want to know why the value of cursorY is being changed. If you would recommend not using wgetstr and have a good alternative, please tell me, but I'm most interested in knowing why cursorY is being altered.)
EDIT The variable data is of type char[] and declared like so: char data[] = "". I don't "clear" this variable (i.e., remove all "letters"), but I don't think this makes any difference, as I think wgetstr just overrides the whole variable (or am I terribly wrong here?).
The buffer you provide for the data, data, is defined as being a single character long (only the null-terminator will be there). This means that if you enter any input of one or more characters, you will be writing outside the space provided by data, and thus overwrite something else. It looks like cursorY is the lucky variable that got hit.
You need to make sure that data is at least big enough to handle all inputs. And preferably, you should switch to some input function (like wgetnstr) that will let you pass the size of the buffer, otherwise it will always be possible to crash your application by typing enough characters.
wgetstr expects to write the received characters to a preallocated buffer, which should be at least as long as the expected input string. It does not allocate a new buffer for you!
What you've done is provide it with a single byte buffer, and are writing multiple bytes to it. This will stomp over the other variables you've defined in your function after data, such as cursorY, regardless of what it is called. Any changes to variables will in turn change the string that was read in:
int a = cursorY;
wgetstr(inputWin, data);
cursorY = a;
will write an int value into your string, which is why it is apparently getting corrupted.
What you should actually do is to make data actually long enough for the anticipated input, and ideally use something like wgetnstr to ensure you don't walk off the end of the buffer and cause damage.

String array unusable after setting it to 0 using memset

I have a class property which is an array of strings (std::string command[10]). When I assign some string value to it, it stop the program execution. As you can see below I've a string variable tempCommandStr which I assign to my property. I don't know what the error could be, but I've the print statement after assignment which is never executed, while the one preceding it is.
//Declared in class header
std::string command[10];
// Part of function which is causing problem.
string tempCommandStr(commandCharArray);
printf("%s\n", tempCommandStr.c_str()); // Prints fine.
this->command[i] = tempCommandStr; // Something goes wrong here. i is set to some correct value, i.e. not out of range.
printf("%s\n", this->command[i].c_str()); // Never prints. Also program stops responding.
// I noticed that getting any value from the array also stops the execution.
// Just the following statement would stop the program too.
printf("%s\n", this->command[i].c_str());
It's not just this property, I also have another array which has the same problem. What could be causing this? What's actually going wrong (look at edit)? Is there another better way to do this?
I'm running the program on an MBED so I've limited debugging options.
EDIT:
I found the problem, I was cleaning the array before using to remove any previous values by memset(command, 0, sizeof(command));. This is was causing the problem. Now I use the clear function on each item in array as following. This fixed the execution problem.
for (int i = 0; i < sizeof(command)/sizeof(*command); i++){
command[i].clear();
}
Question: Why does setting the string array to 0 using memset makes it unusable?
Why does setting the string array to 0 using memset makes it unusable?
Because you're obliterating the values held in the string class, overwriting them all with 0s. A std::string has pointers to the memory where it's storing the string, character count information, etc. If you memset() all that to 0, it's not going to work.
You're coming from the wrong default position. Types where 'zeroing out' the memory is a meaningful (or even useful) operation are special; you should not expect any good to come from doing such a thing unless the type was specifically designed to work with that.

C++ - evaluating an input string as an internal code variable

Is there a way to take a string as an input argument to a c++ function and evaluate it as an internal argument e.g. the name of a structure or other variable?
For example (written in pseudo code)
int myFunction(string nameStructure){
nameStructure.field = 1234
}
The "take away" point is converting the input string as a variable within the code.
Mark
This type of question is often a symptom of a XY problem so consider other options first. That being said, there's no such default mechanism in C++ but there is a simple workaround I can think of - use a dictionary (std::map / std::unordered_map) to store all your objects:
std::map<std::string, MyAwesomeObject> objects;
...
int myFunction(std::string nameStructure)
{
objects[nameStructure].field = 1234
}
The names of local variables are just artifacts of the human-readable code and have no meaning in the compiled binary. Your int myIntVar's and char* myCharP's get turned into instructions like "four bytes starting at the location of the base pointer minus eight bytes, interpreted as a four-byte integer". They no longer have names as such.
If you export symbols from your binary, you can at runtime to look into export table according to your binary format and find the variable you want. But i bet you want something like access to local variable and that is not possible.
If you really need this funcionality, take a look at more dynamic interpreted languages as php
http://php.net/manual/en/language.variables.variable.php

remove escape characters from a char

I've been working with this for about 2 days now. I'm stuck, with a rather simple annoyance, but I'm not capable of solving it.
My programs basicly recieves a TCP connection from a PHP script. And the message which is send is stored in char buffer[1024];.
Okay this buffer variable contains an unique key, which is being compared to a char key[1024] = "supersecretkey123";
The problem itself is that these two does not equal - no matter what I do.
I've been printing the buffer and key variable out just above eachother and by the look they are 100% identical. However my equalisation test still fails.
if(key == buffer) { // do some thing here etc }
So then I started searching the internet for some information on what could be wrong. I later realized that it might be some escape characters annoying me. But I'm not capable of printing them, removing them or even making sure they are there. So that's why I'm stuck - out of ideas on how to make these equal when the buffer variable matches the key variable.
Well the key does not chance, unless the declaration of the key is modified manually. The program itself is recieving the information and sending back information "correctly".
Thanks.
If you're using null terminated strings use proper api - strcmp and its variants.
Additionally size in declaration char key[1024] = "supersecretkey123"; is not needed - either compiler will reduced it or stack/heap memory will be wasted.
If you are using C++ use std::string instead of char []. You cannot compare two char [] in way you try to do this (they are pointers to memory), but it's possible with std::string.
If it's somehow mandatory to use char[] in your case, use strcmp.
Try with if(!strncmp(key,buffer,1024)). See this reference on strncmp.