I found that the parameter I returned is different in the outer function when it's called than where it was in the local function. I set some printing out in each section of the code but still have no idea why the parameter i is not returned:
int assign_cookie(vector<int>& g, vector<int>& s){
if(s.size()==0 || g.size()==0){
cout << "size = 0, returning 0" << endl;
return 0;
}
cout << "s.size() = " << s.size() << endl;
cout << "g.size() = " << g.size() << endl;
sort(g.begin(), g.end());
sort(s.begin(), s.end());
unsigned int i, j = 0;
while(i<g.size() && j<s.size()){
if(g[i]<=s[j]) i++;
j++;
}
cout << "(assign_cookie) i = " << i << endl;
return i;
}
when I called it in the main function as follows:
int main(){
int g[] = {1,2,3};
int s[] = {1,1};
vector<int> vg (g, g+3);
vector<int> vs (s, s+2);
int result = assign_cookie(vg,vs);
cout << "result = " << result << endl;
}
I got results as follows:
s.size() = 2
g.size() = 3
(assign_cookie) i = 1
(main) result = 0
I was very confused with the result. Anyone has an idea what's going on?
Thanks in advance for your help!
You have undefined behaviour, because here
unsigned int i,j=0;
you only initialize j but not i and then you use i as index in g[i] without ever assigning it a meaningful value. Hence it is UB and anything can happen. Actually this is an interesting case of UB, as when you do
unsigned int i,j=0;
std::cout << "i = " << i << "\n";
it still prints
i = 0
(assign_cookie) i = 1
result = 0
see also here. Even if the compiler seems to initialize i to 0 it still realizes that there is UB and takes the freedom to produce garbage output.
Related
While solving a codeforces problem, I had to make a vector of size=1. Also, I needed to iterate back from the second last element of the vector, so I used the following technique to use for loop.
for(int i = vec.size()-2; i > -1; i--){
vec[i] = vec[i] + vec[i+1];
}
This technique throws runtime error at codeforces compiler.
But, using the size of the vector by precalculating it, it runs fine.
Following snippet runs successfully.
int s = vec.size();
for(int i = s-2; i > -1; i--){
vec[i] = vec[i] + vec[i+1];
}
Can someone help me understand this phenomenon?
PS: While figuring out the issue, I did
cout << vec.size()-2;
and to my surprise, the output came out to be
18446744073709551615
when the vector size was 1. The output should have been -1, right? Is this obvious, or something else. Kindly explain.
Here, you trying to access vec[-1], which leads to out of range subscript.
Try to run this and look for output:
for(int i = vec.size()-2; i >= -1; i--){
cout << i << endl; // At some point will be -1
vector<int>::size_type j = i; // Then this will be a very large unsigned number
cout << j << endl; // On my machine it is 18446744073709551615
//vec[i] = vec[i] + vec[i+1];
}
When you have vec[-1], the -1 will be converted to std::vector<T>::size_type, which is unsigned. This will lead to i in effect being a very large unsigned number, which in turn leads to faulty access via subscript.
The other version is essentially the same thing, but it may execute in some way, or may not (e.g. for me it did not went well). All due to the fact that both cases are an instance of undefined behavior.
As was noted in the comments on your question, you can look toward the at() member function of std::vector (do recommend) or try to implement explicit checks for out of range subscript yourself.
As to the update of the question:
I would suggest you to implement something like the following inspection and to run it on your platform:
for(int i = vec.size()-2; i > -1; i--){
auto a = vec[i];
auto b = vec[i+1];
std::cout << "i: " << i << "; " << "i+1: " << i+1 << std::endl;
std::cout << "a:" << a << " + " << "b:" << b << " = " << a+b << std::endl;
std::cout << std::endl;
vec[i] = a + b;
}
E.g. for input: std::vector<int> vec = {1,2,3,4,5}; it gives the following output:
i: 3; i+1: 4
a:4 + b:5 = 9
i: 2; i+1: 3
a:3 + b:9 = 12
i: 1; i+1: 2
a:2 + b:12 = 14
i: 0; i+1: 1
a:1 + b:14 = 15
This is the problem that I'm trying to solve for class in C++.
Write a function that returns a pointer to the maximum value of an array of floating-point data: double* maximum(double* a, int size). If size is 0, return nullptr.
The issues I'm having are that:
The final output is not the correct location for the maximum value in the array.
An error that says: "cannot convert 'double**' to 'double*' in the initialization".
If I use nullptr at any point in this code, CodeBlocks gives me an error.
#include <iostream>
using namespace std;
// return pointer to location from function
double * maximum(double* a, int size)
{
double maxVal = a[0]; // this is the starting max value
double* max_pos = &a; // points to the value in a[0]
// initialis]ze both variables
for(int i = 0; i < size; i++){
if(a[i] > maxVal){
maxVal = a[i];
cout << max_pos << endl;
max_pos = &a[i];
}
}
// return address
return max_pos;
}
int main()
{
double myarr[5];
int i = 0;
int arrSize = 5;
cout << "Input 5 floating point values for your array" << endl;
for(i = 0; i < arrSize; i++){ // loop to input values
cin >> myarr[i];
}
for(int j = 0; j < arrSize; j++){
cout << "Location for " << myarr[j] << " = " << &myarr[j] << endl;
}
double* maxNum = maximum( myarr, arrSize);
cout << &maxNum << endl;
return 0;
}
This is the output I'm getting after finding max_pos:
The code you showed has a few mistakes in it:
using namespace std; is bad!
you are not following your instructions to return nullptr when size is 0.
you are trying to initialize max_pos (a double*) with &a (a double**), which is a compiler error.
you are passing &maxNum (a double**) to std::cout, printing the address of the maxNum variable itself, not the address that it is pointing to (the found array element). You need to pass maxNum (a double*) if you want to print the address of the found element, or pass *maxNum (a double) if you want to print the value of the found element.
Try something more like this instead:
#include <iostream>
// return pointer to location from function
double* maximum(double *a, int size)
{
if (size == 0) return 0;
// initialize both variables
double* max_pos = a; // points to the value in a[0]
double maxVal = *max_pos; // this is the starting max value
std::cout << "max_pos = " << max_pos << " (" << maxVal << ")" << std::endl;
for(int i = 1; i < size; ++i){
if (a[i] > maxVal){
max_pos = &a[i];
maxVal = *max_pos;
std::cout << "max_pos = " << max_pos << " (" << maxVal << ")" << std::endl;
}
}
// return address
return max_pos;
}
int main()
{
const int arrSize = 5;
double myarr[arrSize];
std::cout << "Input " << arrSize << " floating point values for your array" << std::endl;
for(int i = 0; i < arrSize; ++i) { // loop to input values
std::cin >> myarr[i];
}
for(int j = 0; j < arrSize; ++j) {
std::cout << "Location for " << myarr[j] << " = " << &myarr[j] << std::endl;
}
double* maxNum = maximum(myarr, arrSize);
std::cout << "maxNum = " << maxNum << " (" << *maxNum << ")" << std::endl;
return 0;
}
Live Demo
And then, you can throw it all away and use STL algorithms instead, like std::max_element():
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
const int arrSize = 5;
double myarr[arrSize];
std::cout << "Input " << arrSize << " floating point values for your array" << std::endl;
// loop to input values
std::copy_n(std::istream_iterator<double>(std::cin), arrSize, myarr);
for(int i = 0; i < arrSize; ++i) {
std::cout << "Location for " << myarr[i] << " = " << &myarr[i] << std::endl;
}
double *maxNum = std::max_element(myarr, myarr + arrSize);
std::cout << "maxNum = " << maxNum << " (" << *maxNum << ")" << std::endl;
return 0;
}
Live Demo
The test method on the following class does not have the effect I would expect it to. I have a suspicion it is something to do with the fact that the invocation of emplace_back somehow invalidates the reference obtained via the subscript.
Either way I would expect the second print in test to result in
v[0] = 1
however both result in
v[0] = 5
suggesting that the assignment does not take place.
class FooBar {
vector<size_t> v;
public:
size_t add(size_t x) {
cout << "add(" << x << ")" << endl;
size_t K(v.size());
v.emplace_back(x);
return K;
}
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
v[idx] = add(0);
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
};
int main(int argc, char* argv[])
{
FooBar f;
f.add(5);
f.test(0);
}
I know that I can get around the problem by creating a temporary to store the result of add and then perform the assignment but I am interested as to why I cannot use just a straight assignment and why I do not get any kind of error when attempting to perform this.
Compiled and tested with MSVC (Visual Studio 2015).
The line
v[idx] = add(0);
is cause for undefined behavior. You are modifying the contents of v in add while assuming that v[idx] will be valid.
For predictable behavior, you can use:
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
size_t val = add(0);
v[idx] = val;
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
I was trying to run the fib.exe by using this command "fib 12" so it can directly print out the result in this format:
http://pastebin.com/ytR92i8f
But with my code compiled, for instance, if I use 12 to test my program, it won' t read any number and show the result in this command "fib xx" but it will run the program and let you type the number you want in the next line and then print out the result...
I have attached the link to my main.cpp below as reference.
main.cpp : http://pastebin.com/fhUAkNQR
Because main.c can not be modify so I can only use one function to get it works.
Right now I already have the correct result.
void fibonacci(int max)
{
do
{
std::cin >> max;
}
while(max < 2 && max > 46);
std::cout << " Fibonacci Fibonacci" << std::endl;
std::cout << " N number quotient" << std::endl;
std::cout << "-------------------------------------" << std::endl;
std::cout << " 0 0 N/A" << std::endl;
std::cout << " 1 1 N/A" << std::endl;
int count = max;
int fib1 = 0, fib2 = 1;
for (int i = 2; i <= count; i++)
{
int next = fib1 + fib2;
// Add statements to print here...
std::cout << std::setw(2) << i;
std::cout << std::setw(14) << next;
std::cout << std::setw(21) << std::setprecision(17) << std::showpoint;
std::cout << static_cast<double>(next) / fib2 << std::endl;
std::cout.unsetf(std::ios_base::showpoint);
fib1 = fib2;
fib2 = next;
}
return;
}
Here's and example. Problems like the Fibonacci are better dealt with recursion. I see that with your do while loops you are trying to use some sort of recursion but it's not really working
int fibonacci(int x)
{
if (x == 0)
return 0;
if (x == 1)
return 1;
return fibonacci(x-1)+fib(x-2);
}
This basically does all you've typed in your main, just supply x and enjoy. Recursion is a difficult concept but once you've got the idea it can preform very effectively but it's pretty limited in my opinion.
I'm brushing up on some beginner's algorithms as I familiarize myself with C++. There are already some bugs I have no idea where to start fixing.
1) The following gives me seg faults around the time when the fib() function returns its results. EDIT: with inputs >= 9
#include <iostream>
using namespace std;
int fib(int n) {
int fibs[] = {1, 1}; // dynamic array
int i = 2; // start at 3rd element
while(i < n) {
fibs[i] = fibs[i-2] + fibs[i-1];
cout << "DEBUG: fibs[" << i << "] = " << fibs[i] << endl;
i = i+1;
}
cout << "about to return to main()" << endl;
return fibs[n-1];
}
int main() {
cout << "\n================= Hello cruel world =================" << endl;
cout << "Enter a number: ";
int x;
cin >> x;
cout << "fib(" << x << ") = " << fib(x) << endl;
cout << "================ Goodbye cruel world ================\n" << endl;
return 0;
}
Otherwise, the code works just fine, the numbers are found correctly. But 2) when I change the function to support long integers, it starts acting weird:
#include <iostream>
using namespace std;
long fib(int n) {
long fibs[] = {1L, 1L}; // dynamic array
int i = 2; // start at 3rd element
while(i < n) {
fibs[i] = fibs[i-2] + fibs[i-1];
cout << "DEBUG: fibs[" << i << "] = " << fibs[i] << endl;
i = i+1;
}
cout << "about to return to main()" << endl;
return fibs[n-1];
}
int main() {
cout << "\n================= Hello cruel world =================" << endl;
cout << "Enter a number: ";
int x;
cin >> x;
cout << "fib(" << x << ") = " << fib(x) << endl;
cout << "================ Goodbye cruel world ================\n" << endl;
return 0;
}
Output:
================= Hello cruel world =================
Enter a number: 7
DEBUG: fibs[2] = 2
DEBUG: fibs[0] = 1
DEBUG: fibs[1] = 30071067265
DEBUG: fibs[2] = 30071067266
DEBUG: fibs[14] = 0
about to return to main()
fib(7) = 140733637791872
================ Goodbye cruel world ================
It doesn't make any sense to me. Thanks for any help.
int fibs[] = {1, 1};
is equivalent to:
int fibs[2] = {1, 1};
In another word, the array fibs(in both programs) has only two elements, it's illegal to access fibs[n] if n is bigger than 1.
In
long fibs[] = {1L, 1L};
the [] does not mean "as big as it needs to be", it means "count the number of initializers". It's the same as
long fibs[2] = { 1L, 1L };
And the comment
// dynamic array
is just plain WRONG.
The other answers explain what's wrong. To fix it, you can declare fibs as a vector instead:
vector<int> fibs(n, 1);
which will construct a vector of n integers and initialize them all to 1. Replacing that single line of code should be all you need!
Yes it will fail because fibs[2] doesn't exist!
This is not dynamic array by any mean. Its array of 2 long
long fibs[] = {1L, 1L}; // dynamic array