Search code examples
c++11vectorconditional-statementsbooleansize

Integer Iterator is less than Returned size of Vector (C++)


Currently writing a function to return a Pascal Triangle represented in Vectors. When writing the nested for loop within the function, I noticed that the function was returning empty vectors. Going through the debugger, I realized that the inner for loop never runs.

The code is as follows:

vector<vector<int>> generate(int numRows) {
    vector<vector<int>> res = { {1} };
    int k;
    for (int i = 0; i < numRows; i++)
    {
        vector<int> c = {};
        cout << res[i].size() << endl;
        for (k = -1; k < res[i].size(); k++)
        {
            if (k == -1 || k == res[i].size() - 1)
            {
                c.push_back(1);
            }
            else
            {
                c.push_back(res[i][k] + res[i][k + 1]);
            }
        }
        res.push_back(c);
    }

    return res;
}

I had changed the iterator variable name multiple times, and have switched the iterator type to size. However the for still does not run. I tried printing out the iterator k (revealed to be -1) and the size of the first element in the res vector (revealed to be 1). However, when running: cout << (k < res[i].size() << endl; the output was 0.


Solution

    • Take extra care when mixing signed and unsigned types.
    • As explained by @YahavBoneh in the comment above, signed types are converted to unsigned when they are both used in a comparison. In this case, a k value of -1, when converted to unsigned, turns into quite a big number (demo).
    • If possible, let your compiler warn you about it (e.g. in gcc, using -Wall -Wextra; demo).
    • Since you seem to be working only with signed types, a good way to avoid introducing unsigned types into the play, is to use std::ssize (since C++20).

    [Demo]

    #include <fmt/ranges.h>
    #include <iostream>
    #include <vector>
    
    std::vector<std::vector<int>> generate(int numRows) {
        std::vector<std::vector<int>> res{{1}};
        for (auto i = 0; i < numRows; i++) {
            std::vector<int> c{};
            auto width{ std::ssize(res[i]) };
            for (auto k = -1; k < width; k++) {
                if (k == -1 || k == width - 1) {
                    c.push_back(1);
                } else {
                    c.push_back(res[i][k] + res[i][k + 1]);
                }
            }
            res.push_back(c);
        }
    
        return res;
    }
    
    int main() {
        fmt::print("{}", fmt::join(generate(3), "\n"));
    }
    
    // Outputs:
    //
    //   [1]
    //   [1, 1]
    //   [1, 2, 1]
    //   [1, 3, 3, 1]