How can I fix an int-to-bool warning in C++? - c++

I get a warning in MSVC++ when I try to read an integer from a file and make a bool variable equal it.
accessLV[i] = FileRead(file1, i + 1);
(accessLV is an array of bools, FileRead is a function I made to decrease the syntax involved in reading from a file, i is because the statement is within a for loop)
I've tried using a static_cast:
accessLV[i] = static_cast<bool>(FileRead(file1, i + 1));
But I still get the warning. I've tried doing this (I'm not sure the exact term):
accessLV[i] = (bool)FileRead(file1, i + 1));
And the warning is still there. Is there anyway to get rid of the warning without making accessLV an array of ints?
NB: this is the syntax of FileRead, if it helps:
int FileRead(std::fstream& file, int pos)
{
int data;
file.seekg(file.beg + pos * sizeof(int));
file.read(reinterpret_cast<char*>(&data), sizeof(data));
return data;
}

How about
accessLV[i] = FileRead(file1, i + 1) != 0;

What you want to do is basically
accessLV[i] = (FileRead(file1, i + 1) != 0)

accessLV[i] = FileRead(file1, i + 1) != 0;
Above, you were casting from int to bool: if you use this, the result of the comparison is put in accessLV[i], so not type warnings occur.

As other posters have suggested, !=0 is what you need. I prefer a wrapper like this because I find it more readable:
// myutil.hpp
template< typename T >
inline bool bool_cast( const T & t ) { return t != 0; }
Which you would use in this case like this:
// yourcode.cpp
accessLV[ i ] = bool_cast( FileRead( file1, i + 1 ) );
This related question has additional discussion you might find useful.

Related

use of 'n' before deduction of 'auto' C++

I'm trying to have my function return 3 values (n, down and across) I've read online how 'auto' can be used but must be doing something wrong.
The function takes in a 2D vector of integers (as well as other variables) and checks for how many numbers are connected to board[0][0] such that they are the same number.
I've tried putting auto in front of the function inside the function itself, tried leaving it blank, tried just having chain = chainNodes(...) but I always seem to get an error. Here's the code:
tuple<int, int, int> chainNodes(vector<vector<int>> board, int originalNum,
unsigned int across, unsigned int down, int ijSum,
int n)
{
struct chain {
int n, down, across;
};
if(down + across > ijSum) {
ijSum = down + across;
} else if((down + across == ijSum) &&
((down - across) * (down - across) < (ijSum) * (ijSum))) {
ijSum = down + across;
}
board[down][across] = 0;
n += 1;
// Check below
if((down != (board.size() - 1)) && (board[down + 1][across]) == originalNum) {
down += 1;
auto [n, iPoint, jPoint] = chainNodes(board, originalNum, across, down, ijSum, n);
down -= 1;
}
// Check right, up and left (I've removed so its not too messy here)
return chain{n, down, across};
}
Sorry, I forgot to include the error message.
error: use of 'n' before deduction of 'auto'
It occurs on the line that uses auto.
Issue with
auto [n, iPoint, jPoint] = chainNodes(board, originalNum, across, down, ijSum, n);
is similar to
auto n = foo(n); // `foo(n)` uses `n` from `auto n`,
// not the one from outer scope as function parameter
The construct int a = a + 1; is legal but lead to UB as reading uninitialized variable.
That kind of construct allows legal and valid behavior void* p = &p;.
Your code has other errors and it is not clear for me expected behavior of the function.
So not sure if following is the correct fix, but you might want:
n = std::get<0>(chainNodes(board, originalNum, across, down, ijSum, n));

Finding last word in a string

I'm trying to return the last word in a string but am having trouble with the for loops. When I try to test the function I am only getting empty strings. Not really sure what the problem is. Any help is much appreciated.
string getLastWord(string text)
{
string revLastWord = "";
string lastWord = "";
if(text == "")
{
return text;
}
for(size_t i = text.size()-1; i > -1; i--)
{
if((isalpha(text[i])))
{
revLastWord+=text[i];
}
if(revLastWord.size()>=1 && !isalpha(text[i-1]))
{
break;
}
}
for(size_t k = revLastWord.size()-1; k > -1; k--)
{
lastWord+=revLastWord[k];
}
return lastWord;
}
I was coding up another solution until I checked back and read the comments; they are extremely helpful. Moreover, the suggestion from #JustinRandall was incredibly helpful. I find that find_last_of()
and substr() better state the intent of the function--easier to write and easier to read. Thanks! Hope this helps! It helped me.
std::string get_last_word(std::string s) {
auto index = s.find_last_of(' ');
std::string last_word = s.substr(++index);
return last_word;
}
/**
* Here I have edited the above function IAW
* the recommendations.
* #param s is a const reference to a std::string
* #return the substring directly
*/
std::string get_last_word(const std::string& s) {
auto index = s.find_last_of(' ');
return s.substr(++index);
}
The other answers tell you what's wrong, though you should also know why it's wrong.
In general, you should be very careful about using unsigned value types in loop conditions. Comparing an unsigned type like std::size_t and a signed type, like your constant -1, will cause the signed to get converted into an unsigned type, so -1 becomes the largest possible std::size_t value.
If you put some print statements throughout your code, you'll notice that your loops are never actually entered, because the conditional is always false. Use an int when performing arithmetic and especially when signed numbers are compared with.

Character pointers messed up in simple Boyer-Moore implementation

I am currently experimenting with a very simple Boyer-Moore variant.
In general my implementation works, but if I try to utilize it in a loop the character pointer containing the haystack gets messed up. And I mean that characters in it are altered, or mixed.
The result is consistent, i.e. running the same test multiple times yields the same screw up.
This is the looping code:
string src("This haystack contains a needle! needless to say that only 2 matches need to be found!");
string pat("needle");
const char* res = src.c_str();
while((res = boyerMoore(res, pat)))
++res;
This is my implementation of the string search algorithm (the above code calls a convenience wrapper which pulls the character pointer and length of the string):
unsigned char*
boyerMoore(const unsigned char* src, size_t srcLgth, const unsigned char* pat, size_t patLgth)
{
if(srcLgth < patLgth || !src || !pat)
return nullptr;
size_t skip[UCHAR_MAX]; //this is the skip table
for(int i = 0; i < UCHAR_MAX; ++i)
skip[i] = patLgth; //initialize it with default value
for(size_t i = 0; i < patLgth; ++i)
skip[(int)pat[i]] = patLgth - i - 1; //set skip value of chars in pattern
std::cout<<src<<"\n"; //just to see what's going on here!
size_t srcI = patLgth - 1; //our first character to check
while(srcI < srcLgth)
{
size_t j = 0; //char match ct
while(j < patLgth)
{
if(src[srcI - j] == pat[patLgth - j - 1])
++j;
else
{
//since the number of characters to skip may be negative, I just increment in that case
size_t t = skip[(int)src[srcI - j]];
if(t > j)
srcI = srcI + t - j;
else
++srcI;
break;
}
}
if(j == patLgth)
return (unsigned char*)&src[srcI + 1 - j];
}
return nullptr;
}
The loop produced this output (i.e. these are the haystacks the algorithm received):
This haystack contains a needle! needless to say that only 2 matches need to be found!
eedle! needless to say that only 2 matches need to be found!
eedless to say that eed 2 meed to beed to be found!
As you can see the input is completely messed up after the second run. What am I missing? I thought the contents could not be modified, since I'm passing const pointers.
Is the way of setting the pointer in the loop wrong, or is my string search screwing up?
Btw: This is the complete code, except for includes and the main function around the looping code.
EDIT:
The missing nullptr of the first return was due to a copy/paste error, in the source it is actually there.
For clarification, this is my wrapper function:
inline char* boyerMoore(const string &src, const string &pat)
{
return (const char*) boyerMoore((const unsigned char*) src.c_str(), src.size(),
(const unsigned char*) pat.c_str(), pat.size());
}
In your boyerMoore() function, the first return isn't returning a value (you have just return; rather than return nullptr;) GCC doesn't always warn about missing return values, and not returning anything is undefined behavior. That means that when you store the return value in res and call the function again, there's no telling what will print out. You can see a related discussion here.
Also, you have omitted your convenience function that calculates the length of the strings that you are passing in. I would recommend double checking that logic to make sure the sizes are correct - I'm assuming you are using strlen or similar.

Invalid use of auto

In this code:
for ( ;(auto i = std::find(some_string.begin(),some_string.end(),'%')) != some_string.end();)
{
}
I'm getting error from gcc 4.7.1:
error: invalid use of 'auto'|
any ideas why? shouldn't that be correctly compiled?
I think it has nothing to do with auto. You just cannot declare variables in random places, for example this will not compile either - an equivalent of what you were trying to do, but without auto:
int main() {
for ( ; (int i = 0) != 1; ++i)
;
return 0;
}
If this is in a loop, you'll only ever find the first '%'. You need to resume searching from i, not some_string.begin() to find subsequent '%'.
auto i = std::find(some_string.begin(), some_string.end(), '%'));
while (i != some_string.end()) {
// Your code here.
i = std::find(i, some_string.end(), '%')); // Find next '%'.
}

How should I correct this code that causes "value computed not used" warning?

I have an array of doubles and need to do a calculation on that array and then find the min and max value that results from that calculation. Here is basically what I have:
double * array;
double result;
double myMin;
double myMax;
// Assume array is initialized properly...
for (int i = 0; i < sizeOfArray; ++i) {
result = transmogrify(array[i]);
if (i == 0) {
myMin = result;
myMax = result;
}
else if (result < myMin) {
myMin = result;
}
else if (result > myMax) {
myMax = result;
}
}
I'm getting a warning that the value computed for result is never used, and since we treat all warnings as errors, this doesn't compile. How can I fix this code to avoid the warning? I'm using g++ for my compiler.
Here's the warning text:
cc1plus: warnings being treated as errors
foo.cc:<lineno of transmogrify call>: error: value computed is not used
Edit: I don't understand the down votes, but I've got things working now. Thanks to everyone for taking the time to help me out.
Assuming you don't need result outside of the loop, you could declare result inside the loop thusly:
for( int i=0; i < sizeOfArray; ++i ) {
double result = transmogrify( array[i] );
...
}
I'm getting a warning that the value computed for result is never used because (theoretically) it's possible that none of the if/else branches will be selected
That can't be the reason for the warning, because result is also used in the if conditions. Even if none of the branches are taken, result is still used to decide that they should not be taken.
Initialize myMin and myMax with DBL_MAX and DBL_MIN respectively and get rid of the first time through the loop check.
result = [...]
if (i == 0) {
[... do something with result ...]
}
else if (result < myMin) {
In both branches of the if(), result is used. In the 1st case it's assigned to a variable, in the 2nd it's used in a comparison. So the compiler shouldn't warn.
I suspect you might have misdiagnosed the problem. Please can you say exactly what the error message is (copy-paste it). Also, please try to post the smallest piece of code you can that actually compiles and gives the warning? (Simply trying to do that will probably let you find the problem)
EDIT: Is it possible that transmogrify() is a macro that uses result internally?
Before the "if" statement:
result = 0.0;
or some other value. It is always good form to set a variable to some value before using it.
I'm getting a warning that the value computed for result is never used because (theoretically) it's possible that none of the if/else branches will be selected, and since we treat all warnings as errors, this doesn't compile. How can I fix this code to avoid the warning? I'm using g++ for my compiler
The value used for result is always used. If not assigned it's used in the comparator. Therefore the compiler is faulty.
I don't think the code as posted should produce the error, unless the compiler is doing some phenomenal flow analysis. It certainly compiles OK with g++, but I'm not sure that g++ even supports the warning you are getting.
The following adaptation of your code, which preserves its structure, produces no error with g++:
int main() {
double * array;
double result;
double myMin;
double myMax;
double t(double);
// Assume array is initialized properly...
for (int i = 0; i < 10; ++i) {
result = t(array[i]);
if (i == 0) {
myMin = result;
myMax = result;
}
else if (result < myMin) {
myMin = result;
}
else if (result > myMax) {
myMax = result;
}
}
}
A quick solution might be to unroll the first iteration, like this:
double * array;
double result = transmogrify(array[0]);
double myMin = result;
double myMax = result;
int i;
for (i = 1; i < sizeOfArray; ++i) {
result = transmogrify(array[i]);
if (result < myMin) {
myMin = result;
}
if (result > myMax) {
myMax = result;
}
}
EDIT: I'll expand a bit on this. You haven't given any detailed information on sizeOfArray, but my guess is that it's a signed integer type.
I believe you've misunderstood the cause of the warning, result might be unused because sizeOfArray might be less than or equal to zero, not because of the if..else clauses inside the loop. In the code above, it might be a bit clearer why you need careful handling of the case (sizeOfArray <= 0), but it's equally important in the original code snippet as well.
Removing the first else only impacts the running time of the first run through the loop. I'd eliminate it rather.
if (i == 0) {
myMin = result;
myMax = result;
}
if (result < myMin)
myMin = result;
else if (result > myMax)
myMax = result;