Why is this for loop not correct? - c++

Visual Studio is telling me that this for loop isn't correct.
Error Messages are:
type bool unexpected
ok is undeclared identifier
missing ; before }
infos:
-recordset.Select return a long -MoveNext a bool
for (size_t i = 0, bool ok = recordset.Select(Adress::getSQLStatement() + "Where A05.recid = %ld", i); ok; ok = recordset.MoveNext(), i++) {
at(i).Save(recordset);
}

It's as StenSoft said. But you can define an anonymous structure in the loops first statement, and initialize that.
#include <iostream>
using namespace std;
int main() {
for (struct {size_t i; bool ok;} s = {0, true}; s.ok; ++s.i) {
s.ok = s.i < 10;
cout << s.i;
}
return 0;
}
But IMHO, while it works, it's more trouble than it's worth. Better restructure you code.

First off, you can of course rewrite your loop like so:
{
bool ok = recordset.Select(...);
for (std::size_t i = 0; ok; ok = recordset.MoveNext(), ++i)
{
/* ... */
}
}
But the meta lesson here is that almost all loops are for-loops, and when you think your structure is different, think again. There's probably a rewrite in terms of for-loops that makes your logic clearer. Your present code doesn't distinguish an initial error from a "no more records" error later. With the new code, that's now explicitly possible:
if (bool ok = recordset.select(...))
{
for (std::size_t i = 0; ok; ok = recordset.MoveNext(), ++i) { /* ... */ }
}
else
{
// handle initial error
}
I would probably even get rid of the redundant ok variable:
if (recordset.select(...))
{
for (std::size_t i = 0; ; ++i)
{
/* ... */
if (!recordset.MoveNext()) break;
}
}
else
{
// handle initial error
}

Related

Return struct element from vector c++

I'm new to C++ and I'm trying to return a struct from a vector of structs by using 2 search criteria.
The function find_city is returning me everything from the defined range, regardless of whether it exists inside the vector of struct.
Here's my code:
struct cityLoc
{
int hRange;
int vRange;
int cityCode;
string cityName;
};
vector<cityLoc> cl1;
// the vector has already been preloaded with data
// function to return my struct from the vector
cityLoc find_city(int hRange, int vRange)
{
for (size_t i = 0; i < cl1.size(); i++)
{
if ((cl1[i].hRange = hRange) && (cl1[i].vRange = vRange))
{
return cl1[i];
}
}
}
int main()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j <= 8; j++)
{
cityLoc this_city;
this_city = find_city(i, j);
cout << this_city.hRange << ", " << this_city.vRange << endl;
}
}
return 0;
}
Also, aside from this question, I was previously looking into std::find_if and didn't understand it. If I have the following code, what is the output? How do I modify it such that it returns a struct?
auto it = find_if(cl1.begin(), cl1.end(), [](cityLoc& cl) { return cl.hRange == 1; } );
You have a bug here:
if ((cl1[i].hRange = hRange) && (cl1[i].vRange = vRange))
Those = are assignments, not comparisons! Please enable compiler warnings and you won't be hurt by such obvious typos in future.
std::find_if will return the iterator to the found struct entry if it is successful, std::vector::end() otherwise. So, you should first validate the returning iterator if it is valid or not.
For example:
auto it = std::find_if( cl1.begin(), cl1.end(),
[](const cityLoc& cl) { return cl.hRange == 1; } );
if ( it == cl1.end() )
{
// ERROR: Not found! Return error code etc.
return -1;
}
// And, if found, process it here...
std::cout << it->hRange << '\n';
std::cout << it->vRange << '\n';
The criteria (predicate) part in std::find_if is a lambda expression.

C++ successful `try` branch

Let's consider some artificial C++ code:
int i = 0;
try { someAction(); }
catch(SomeException &e) { i = -1; }
i = 1;
... // code that uses i
I want this code to assign -1 to i in case of someAction() throws exception and assign 1 in case if there was no exception. As you can see now this code is wrong because i finally always becomes 1. Sure, we can make some trick workarounds like:
int i = 0;
bool throwed = false;
try { someAction(); }
catch(SomeException &e) { throwed = true; }
i = throwed ? -1 : 1;
... // code that uses i
My question is: is there anything in C++ like "successful try branch", where I do some actions in case if there were no any throws in try block?
Something like:
int i = 0;
try { someAction(); }
catch(SomeException &e) { i = -1; }
nocatch { i = 1; }
... // code that uses i
Surely, there is no nocatch in C++ but maybe there is some common beautiful workaround?
int i = 0;
try { someAction(); i = 1; }
catch(SomeException &e) { i = -1; }
Aside from the simple solution
try
{
someAction();
i = 1;
}
catch(SomeException &e)
{
i = -1;
}
you should consider what you are planning to do with the value of i further in the code - use it in if statements? That is poor design, you could simply put all the code inside the braces after try and catch respectively.

Error: not all control paths return a value

I am writing two functions in a program to check if a string has an assigned numeric code to its structure array or if the given numeric code has an assigned string in the same structure array. Basically, if I only know one of the two, I can get the other. I wrote the following:
int PrimaryIndex::check_title_pos(std::string title) {
bool findPos = true;
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
} else {
return -1;
}
}
std::string PrimaryIndex::check_title_at_pos(int pos) {
bool findTitle = true;
if (findTitle) {
for (int p = 1; p <= 25; p++) {
if (my_list[p].tag == pos) {
return my_list[p].title;
}
}
} else {
return "No title retrievable from " + pos;
}
}
However, it says not all control paths have a return value. I thought the else {} statement would handle that but it's not. Likewise, I added default "return -1;" and "return "";" to the appropriate functions handling int and string, respectively. That just caused it to error out.
Any idea on how I can keep this code, as I'd like to think it works but cant test it, while giving my compiler happiness? I realize through other searches that it sees conditions that could otherwise end in no returning values but theoretically, if I am right, it should work fine. :|
Thanks
In the below snippet, if s iterates to 26 without the inner if ever evaluating to true then a return statement is never reached.
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
}

Can I have a single-dimension array of booleans that skip indexes?

I'm pretty new to Arduino programming, but am getting the hang of it. I've got a pretty strong PHP & Javascript background, so that's where I'm coming from.
I've been working on a project with an LCD touchscreen, with grids of buttons that I expect other developers to customize to their needs. There's an array that a developer can freely add items to, and additional pages of buttons are added dynamically. Clicking one simply sends that button's index to a receiver.
Now I want to make some buttons "sticky" so they stick on until turned off. My idea was to set up a simple array of booleans, like so:
boolean stickyTriggers[1] = 1;
boolean stickyTriggers[2] = 0;
boolean stickyTriggers[3] = 0;
boolean stickyTriggers[9] = 1;
What I'd expect is that buttons 1, 2, 3, and 9 are sticky, and buttons 1 and 9 are "on" by default. I figured when I'm rendering the buttons, I can simply say something like:
if (stickyTriggers[i]) {
// highlight button
}
The error I'm getting on compile is:
array must be initialized with a brace-enclosed initializer
I sort of realize I'm re-declaring the variable 3 times here, but I've tried other ways and got other errors.
What is the correct way to hold a simple array of flags? I want to be able to look up a key and get a true or false (or null), without having to hard-code an array length. I'm sure it's all possible, but is there a simple way?
Thanks
Clarification: The key here is that triggers 4-8 are NOT in the stickyTriggers array at all, since they are NOT sticky. I want to be able to skip indexes, or use arbitrary IDs as keys, as the title suggests. Most of the answers miss this.
I think you need somethig like this
#include <iostream>
using namespace std;
int main()
{
bool b[5] = {true, false, true, false, true};
cout << "Hello World" << endl;
for (int i=0; i < 5; i++) {
if (b[i]) {
cout<< "Index " << i << " is true" <<endl;
} else {
cout<< "Index " << i << " is false"<<endl;
}
}
return 0;
}
Try this:
#define ARRAY_SIZE 10
#define BOOL unsigned int
#define TRUE 1
#define FALSE 0
int main()
{
BOOL stickyTriggers[ARRAY_SIZE] = { FALSE };
stickyTriggers[1] = TRUE ;
stickyTriggers[9] = TRUE ;
return 0;
}
Yes, you are re-defining the array several times.
In C++, you may want to use bitset, check this link
http://en.cppreference.com/w/cpp/utility/bitset
You can try vector (which can dynamically change its size) too, like this
#include<iostream>
#include<vector>
using namespace std;
enum trigger_status {ON, OFF, NON_STICKY};
int main(){
vector<trigger_status> sticky_triggers(251, trigger_status::OFF); // you can add element to it dynamically, default all to off
sticky_triggers[0] = trigger_status::ON;
sticky_triggers[9] = trigger_status::ON;
sticky_triggers.push_back(trigger_status::ON); // sticky_triggers[251] = true, now u have 252 elements
}
Maybe I should have left out the C++ tag, to only invite Arduino-specific solutions.
But here's what I found, which solves my problem:
Alexander Brevig's HashMap Library:
http://playground.arduino.cc/Code/HashMap
As discussed here: http://forum.arduino.cc/index.php?PHPSESSID=q7rt05n43aa4enp6hepri50pi1&topic=42114.msg305435#msg305435
#include <HashMap.h>
const byte HASH_SIZE = 5;
HashType<int,boolean> hashRawArray[HASH_SIZE];
HashMap<int,boolean> hashMap = HashMap<int,boolean>(hashRawArray, HASH_SIZE);
void setup() {
Serial.begin(9600);
hashMap[0](1,true);
hashMap[1](2,false);
hashMap[2](3,false);
hashMap[3](4,false);
hashMap[4](9,true);
Serial.println(hashMap.getValueOf(1));
Serial.println(hashMap.getValueOf(2));
Serial.println(hashMap.getValueOf(9));
}
I can add a quick wrapper to add items to the hashMap without having to hard-code the index, but this gives me an easy way to set up an associative array of booleans, using arbitrary integers as the keys.
Thanks for trying everyone, sorry none of the answers worked on Arduino.
You might be able to use this it does not quite fulfil your desire to have no references to non-sticky triggers but it is fast and only uses 64 bytes of memory to map out 256 triggers.
I already had it in single boolean mode so I adapted it to make two maps and renamed it to suit your question..
Basically it is a bitmap.
Compiles and tests run OK for Arduino Duo.
// bitmapped booleans
const int IntBits = 16;
const int NumTriggers = 256;
const int idxSticky = 0;
const int idxDown = 1;
unsigned int TriggerMap[NumTriggers/IntBits][2];
void setup() {
Serial.begin(9600);
clearTriggerMap; // set all to not sticky and not down
// tests
setStickyTrigger(1, true, true);
setStickyTrigger(2, true, false);
setStickyTrigger(3, true, false);
setStickyTrigger(9, true, true);
setStickyTrigger(30, true, true);
setStickyTrigger(128, true, true);
setStickyTrigger(255, true, true);
}
void loop() {
// tests
Test(0);
Test(1);
Test(2);
Test(3);
Test(9);
Test(30);
Test(128);
Test(255);
delay(5000);
}
void Test( int ATrigger) {
// testing
if (IsStickyTrigger(ATrigger)) {
Serial.print( "Trigger ");
Serial.print(ATrigger);
Serial.print(" is sticky");
if (IsStickyTriggerDown(ATrigger)) {
Serial.print(" and it is down");
}
}
Serial.println();
}
void clearTriggerMap() {
for (int i = 0; i < NumTriggers/IntBits; i++) {
for (int j = 0; j < 2; j++){
TriggerMap[i][j] = 0;
}
}
}
void setStickyTrigger(int AIndex, boolean ASticky, boolean IsDown) {
unsigned int o;
unsigned int b = 1;
o = AIndex / IntBits;
b = b << (AIndex % IntBits);
if (ASticky) {
TriggerMap[o][idxSticky] = TriggerMap[o][idxSticky] | b;
} else {
b = ~b;
TriggerMap[o][idxSticky] = TriggerMap[o][idxSticky] & b;
}
if (IsDown) {
TriggerMap[o][idxDown] = TriggerMap[o][idxDown] | b;
} else {
b = ~b;
TriggerMap[o][idxDown] = TriggerMap[o][idxDown] & b;
}
}
boolean IsStickyTrigger(int AIndex) {
unsigned int b = 1;
b = b << (AIndex % IntBits);
return (TriggerMap[AIndex / IntBits][idxSticky] & b) != 0;
}
boolean IsStickyTriggerDown(int AIndex) {
unsigned int b = 1;
b = b << (AIndex % IntBits);
return (TriggerMap[AIndex / IntBits][idxDown] & b) != 0;
}

I'm having some scope issue (unidentified identifier error after a for loop)

I'm using visual studio 2008 to do some problems and brusg up on using c++. I have an error and I don't know why it occurs. Here's all the code. The error occurs on the line :
cout<<levels[0][0]->left->value;
with error:
error C2065: 'levels' : undeclared identifier
a shorthand of what's happening to levels is this:
//declaring it
binaryValNode*** levels;
levels = new binaryValNode** [size];
//adding arrays to the array:
for(int i = 0;i<size;i++){
levels[i] = new binaryValNode* [size];
//adding the objects
for(int k = 0; k <= i ; k++)
{
levels[i][k] = new binaryValNode();
}
//I tested cout here and it works fine
}
//but loses scope here(?)
binaryValNode is a struct with int value,binaryValNode* left and binaryValNode* right.
thanks!
code:
#include <iostream>
#include <fstream>
#include "binaryValNode.h"
using namespace std;
int main() {
int length = 0;
int size = 0;
ifstream myReadFile;
myReadFile.open("input.txt");
char* c = new char[3];
if (myReadFile.is_open()) {
while (myReadFile.getline(c,(size+1)*3)) {
size++;
c = new char[(size+1)*3];
}
binaryValNode*** levels;
levels = new binaryValNode** [size];
myReadFile.clear();
myReadFile.seekg(0);
for(int i = 0;i<size;i++){
levels[i] = new binaryValNode* [size];
c = new char[(i+1)*3];
myReadFile.getline(c,(i+1)*3);
for(int k = 0; k <= i ; k++)
{
levels[i][k] = new binaryValNode();
if(c[3*k] != '0')
{
levels[i][k]->value = ((int) c[(3*k)+1]-48) + 10*((int) c[(3*k)]-48);
}
else
{
levels[i][k]->value = (int) c[(3*k)+1]-48;
}
//
if(i!=0){
if(k==0){//only left parent
levels[i-1][k]->left = levels[i][k];
}
else if(k==i){//only right parent
levels[i-1][k-1]->right = levels[i][k];
}
else{
levels[i-1][k]->left = levels[i][k];
levels[i-1][k-1]->right = levels[i][k];
}
}
}
}
}
myReadFile.close();
cout<<levels[0][0]->left->value;
cin.get();
return 0;
}
Fix your indentation (for example, gg=G in Vim).
Right now you have
int main() {
// ...
if (myReadFile.is_open()) {
// ...
binaryValNode*** levels;
// ...
}
// ...
cout << levels[0][0]->left->value;
// ...
}
where levels is very clearly out of scope.
This needs to be moved to before the conditional:
binaryValNode*** levels;
Sort out your indentation - it will show that you have one too may closing }, and hence the problem line occurs after the end of main().
Try edit/advanced/format-selection