control reaches end of non-void function - c++

This code should perfectly run and give the right result but it doesn't. I used the debugger and everything is ok. c.i and c.j have the right values before the function returns. I make sure there is always a path between start and end so that's not the problem. The path and vis array are filled with the right values too. So the only problem is when it returns. It gives random, big numbers. It works only when i put a return statement at the end of the function. But i can make a function with only one return statement placed in if clause and it works. Is there some kind of rule, so there must be any kind of return statement at the end of a function? To test it, i enter 3x3 two dimensional array with 1's. Any solutions?
Edit: I run it on ideone and it works without return statement at the end of the function. Also a friend of mine tested on his computer it also worked. I use codeblocks on windows 7. What can the problem be?
link to ideone
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
struct crd {
int i,j;
};
bool vis[50][50];
int map[50][50];
int path[50][50];
int di[4] = {1,-1,0,0};
int dj[4] = {0,0,1,-1};
int bfs(crd start, crd end, int n, int m)
{
queue<crd> q;
crd t,c;
q.push(start);
vis[start.i][start.j] = 1;
path[start.i][start.j] = 0;
while (!q.empty()) {
t = q.front();
q.pop();
for (int i=0; i<4; i++) {
c.i = t.i + di[i];
c.j = t.j + dj[i];
if (c.i >= 0 && c.j >= 0 && c.i < n && c.j < m) {
if (map[c.i][c.j] != -1 && vis[c.i][c.j] != 1) {
q.push(c);
vis[c.i][c.j] = 1;
path[c.i][c.j] = path[t.i][t.j] + 1;
if (c.i == end.i && c.j == end.j)
return path[end.i][end.j];
}
}
}
}
// if i put this: return path[end.i][end.j]; it works
}
int main()
{
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++)
cin >> map[i][j];
}
crd s,e;
s.i = s.j = 0;
e.i = e.j = 2;
int sp = bfs(s,e,3,3);
cout << sp << endl;
return 0;
}

The compiler is pretty basic - it has no way of knowing your function will always reach the return inside your if inside the if inside the other if inside the for loop inside the while loop. So it warns you that you might not return anything from the function. The easiest fix would be to return the appropriate value at the end and only break outside the loops at the point you now have your return.

If you declare a function with non-void return type, this functions should return a value. If execution reaches the end of the function, and there is no return <value>; statement there, the result of function would be undefined.

When you "fall off the edge" of a function, the return value is undefined (meaning it could be anything, including values that aren't valid for the type you were returning).
So, every function should have a return at the end. Or some way to say "I didn't expect to get here, stop now" if that's the appropriate thing (say, for example you were looking for a someting in a list, and you don't expect to NOT find it, then having something to print "I couldn't find , expected to. Stopping..." and then exit the program).
I'm not entirely sure what is the RIGHT thing to return if you don't find end.i and end.j, but you certainly should return SOMETHING.

You have two bugs.
It is fine to have no return statement at the end of a function that returns a value, but only if the end of the function can never be reached. In this case, your search algorithm could conceivably fail to find a path (depending of course on the contents of the input data), and then the outer loop will terminate without the return statement ever having been executed. You must have another return statement after the while loop, to account for this possibility. It should not return path[end.i][end.j]; Instead it should return a special value that means the search failed. This is the bug which the compiler has detected and is telling you about.
There is an error somewhere in your breadth-first search logic which is causing paths not to be found even when they do exist. You need to debug that yourself.

Related

How do you put a letter triangle in a file?

So this is for some homework I am working on.
I've been working on this for days now. I need to print a letter triangle,
example
a
aa
aaa
to a file I create in the code. I have gotten the triangle part down using a for loop but cannot figure out how to get it into a file. here is what I have so far.
#include <iostream>
#include <fstream>
using namespace std;
char loop()
{ for (int i = 1; i <=15; i++){
for (int j = 1; j <= i; j++){
cout << "a";
}
cout << endl;
}
}
int main()
{
ofstream week2 ("week2assignment.txt");
if (week2.is_open()){
char result = loop();
{
week2 << loop() + "\n";
}
}
week2.close();
else cout << "file wasnt created";
return 0;
}
This is my first post on here and I am in my second week of learning C++ so any help would be appreciated immensely. Thank you all in advance.
You just need to replace cout with week2 everywhere, since cout is the terminal and week2 is your file.
Given the current structure of your code, where you write to cout in a function, you'll need to pass week2 as an argument to that function to use it there.
First of all, don't build a habit of using using namespace std
std::endl will put a linebreak, but it will also flush your stream. Put easily, outputting something is a really costly (=takes a long time) action in regard to other actions. To account for this, streams are buffered and once the buffer is full it will be flushed automatically. When you use std::endl the buffer might be flushed prematurely and this will tank performance. This is of course not really an issue in this small exercise, but I think it's still good to know. You can use \n instead. Although it might not look like it, it will provide a platform independend linebreak and should virtually always be used instead of std::endl.
Then consider what your function loop should do. Right now, you said it has return type char but it's not returning something. Therefore you should correct this and specify that this function is not returning anything, but just performing an action, hence return type void.
As suggested by John Zwinck, if you pass the stream as an argument, your function becomes more powerful and works with any kind of outgoing stream (i.e. std::ostream).
We can make the function even more generic, but I'll leave it to you to understand the code (if not, feel free to post a comment for clarification). Please note also, that loop is not a descriptive name. I have no idea what loop does. Always give your functions a name that makes it clear what they are doing.
#include <iostream>
#include <fstream>
void print_letter_triangle(std::ostream& out, char c = 'a', int count = 15)
{
for( int i = 0; i < count; i++ ){
for( int j = 0; j < i; j++ )
{
out << c;
}
out << '\n';
}
}
int main()
{
// for testing purposes
print_letter_triangle(std::cout);
print_letter_triangle(std::cout, 'b');
print_letter_triangle(std::cout, 'c', 7);
std::ofstream week2("week2assignment.txt");
if( week2.is_open() )
{
print_letter_triangle(week2);
week2.close();
}
else
{
std::cout << "Error: File wasn't created.\n";
}
return 0;
}
Lastly: Try to build an early habit of how you want to format your code, positions of curly braces, spaces around operators. Right now it was a little bit inconsistent (which might as well have been caused by putting it on StackOverflow).
There are a couple more nitpicks one can offer (for example, I changed the loop to start from 0 and used the < instead of the <= operator, you can convince yourself that this does not change the number of loop iterations. However, it is common in programming languages to start from 0 (as counter-intuitive as that might be at first). Finally, since negative counting values do not make sense in this loop, one might change int to unsigned int, but I felt that might have been a little too much. Feel free to do so on your own, if you wish).
I suggest you use this code:
#include <iostream>
#include <fstream>
using namespace std;
const char* loop()
{ for (int i = 1; i <=15; i++){
for (int j = 1; j <= i; j++){
return "a";
}
return "\n";
}
}
int main()
{
ofstream week2 ("week2assignment.txt");
week2 << loop() << "\n";
return 0;
}
You must return a value from your loop() function.

Having to redeclare an int for a second for loop

I am playing around on edabit.com C++ challenges to refresh myself and I was presented with a challenge where I needed to write a function that would, given a vector, return true if all even indices are even and all odd indices are odd. Otherwise return false. The logic and everything of the function was fine. I know there's a few ways to do this but came up with a (I think) creative solution where instead of running through one for loop with a check if the index is odd or even, I instead wrote two subsequent for loops that increment by two each. One starting at 0 and the other starting at 1. Once it finds a mismatch it returns false. Otherwise at the end it will return true. I am coming from JavaScript where you would not need to redeclare the index variable (if using var not let) but this code failed to compile:
bool isSpecialArray(std::vector<int> arr) {
for(int i = 0; i < arr.size(); i = i + 2){
if(arr[i] % 2 == 1){
return false;
}
}
for(i = 1; i < arr.size(); i = i + 2){
if(arr[i] % 2 == 0){
return false;
}
}
return true;
}
Stating:
error: use of undeclared identifier 'i'
for(i = 1; i < arr.size(); i = i + 2){
^
And of course declaring int in the second for loop cleared the error and the program executed as expected. I'm guessing this is due to garbage collection, but is there a specific rule in the standard that defines this? Or is this maybe a per compiler thing? My understanding of the garbage collection was that the variable once declared is not cleared from memory until is no longer being used in the current function it is defined in. Is this different due to the scope of the for loop, similar to JavaScript's let?
Firstly, JS and C++ have very different models of scopes, and JS is known (sorry) for its bad practices. In C++ the rule is more consistent: the variable is destroyed whenever the program exits the scope. That means that in this code:
for (int i = 0; ; ) {
}
the variable i is defined just for this scope, it cannot be reused in another (not nested) loop, is not seen elsewhere, and the name can be reused or redefined in the inner scopes. This gives you the advantage that it is much easier to control the data flaw and to have less side effects. So the solution for you is to declare another variable i in the second loop:
for(int i = 1; i < arr.size(); i = i + 2){
if(arr[i] % 2 == 0){
return false;
}
}
As long as you are from the JS world I would give you more recommendations. First, do not pass the vector by value (unless you realize what you are doing). Pass it by reference or even better by const reference:
bool isSpecialArray(const std::vector<int> &arr) {
// ...
}
Next, a potentially more efficient and more idiomatic way to increase the index is i += 2.
And the final observation: there is no "creativity" in your solution, but there are drawbacks. This code becomes less cache friendly, and this may be considered as a bad practice.
There is no garbage collection in C++, and even if there were, it wouldn't explain your error. The actual cause is simple: variables declared as part of a for loop go out of scope after the loop.
variable i in your program was declared inside a block or curly braces ({ }). So, variable i is a local variable which can be used only inside that block.
bool isSpecialArray(std::vector<int> arr) {
int i;
for(i = 0; i < arr.size(); i = i + 2){
if(arr[i] % 2 == 1){
return false;
}
}
for(i = 1; i < arr.size(); i = i + 2){
if(arr[i] % 2 == 0){
return false;
}
}
return true;
}
This is the correct way to do it.
c++ does not have garbage collection. Instead, it does deterministic destruction of objects such as i. The way the compiler does this is by cleaning up the object once the scope it's in has ended, and then not allowing you to use that object afterwards.
int main()
{
{
int i;
} // scope of i ends
cout << i; // error, can't access i here
}
for loops have their own scope, so in your example, the i in the first loop is not accessible in the second loop.

why is the sort() changing my input array?

i am stuck on a problem where, after taking input of an array and sorting it and not doing any operation on it at all, the output shows a different array?
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;
cin>>t;
while(t--){
int n;
cin>>n;
long long int c[n],h[n],a[n];
for(int i=0;i<n;i++){
cin>>c[i];
}
for(int i=0;i<n;i++){
cin>>h[i];
}
sort(h,h+n);
for(int i=0;i<n;i++){
a[i]=0;
}
int i=0;
int begin=(i+1)-c[i];
int end = (i+1)+c[i];
int j=begin;
while(i<n){
a[j-1]++;
j++;
if(j>end){
i++;
begin=(i+1)-c[i];
end= (i+1)+c[i];
j=begin;
}
}
sort(a,a+n);
for(int i=0;i<n;i++){
cout<<h[i]<<" ";
}
}
return 0;
}
input for h[]={8,8,8,8,8}..n=5
output h[]={10,10,9,9,8}
Here is a version of your code written in reasonably decent C++. I didn't touch the loop in the middle because I have no clue what it's doing. You're using obscure variable names and no comments and doing all kinds of bizarre things with indexes and mixing them up with user input.
Now, reading indexes from user input and using them isn't bad, though in a real program you'd want to be doing lots of bounds checking on that input to make sure people weren't feeding you bad data. But doing all that stuff with such poorly named variables with no explanation is going to leave anybody looking at it scratching their head. Don't do that.
Also, avoid the use of begin and end as variable names, especially if they hold indexes. In most cases it will confuse things terribly as begin and end are important identifiers in the standard library and always refer to iterators, which are sort of like indexes, but most definitely not indexes, adding greatly to the confusion. beginidx and endidx could be acceptable substitutes in this case.
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using ::std::vector;
using ::std::sort;
using ::std::copy_n;
using ::std::copy;
using ::std::fill;
using ::std::istream_iterator;
using ::std::ostream_iterator;
using ::std::cin;
using ::std::cout;
int main() {
// your code goes here
using vec_el_t = long long int;
int t;
cin >> t;
while (t--) {
int const n = []() { int n; cin >> n; return n; }();
vector<vec_el_t> c{n}, h{n}, a{n};
copy_n(istream_iterator<vec_el_t>{cin}, n, c.begin());
copy_n(istream_iterator<vec_el_t>{cin}, n, h.begin());
// Suggested debugging code:
// cout << "h before sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
sort(h.begin(), h.end());
// Suggested debugging code:
// cout << "h after sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
fill(a.begin(), a.end(), 0);
// Weird, unexplained algorithm begins here
int i = 0;
int begin = (i + 1) - c[i];
int end = (i + 1) + c[i];
int j = begin;
while (i < n) {
a[j - 1]++;
j++;
if (j > end){
i++;
begin = (i + 1) - c[i];
end = (i + 1) + c[i];
j = begin;
}
}
// Weird unexplained algorithm ends here
sort(a.begin(), a.end());
copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
}
return 0;
}
Changes made... Use vector not a variable length array, which isn't valid C++ anyway and will only work in g++ and clang. Don't use explicit loops if there is an algorithm that will do the job. Try to make as many things const as you can so you can make sure that the compiler catches it if you try to change things you didn't mean to change. Avoid using std; and if you want to import names from ::std import exactly the ones you need. Don't use compiler or library implementation specific header files and use the ones from the standard instead (i.e. no bits/stdc++.h).
As for your problem, I have no idea. I suspect that the index manipulation combined with looping isn't doing what you expect. If you print out the arrays before and after sorting, you will discover that sort only alters order, and not content.
As a general rule, always suspect your own code first and make absolutely sure it's correct. And if you really think it's the library code, prove it beyond a shadow of a doubt before coming here to ask why the library isn't doing what it says it does.
The complicated code I didn't touch looks rife with opportunities for out-of-bounds access, and that results in undefined behavior, which means your program might do absolutely anything in that case. You might change uses of operator [] with calls to the at function (one of the many perks of using vector) instead. That way, attempts at out-of-bounds access will throw an exception.
Within these lines you are accessing a outside its limits:
int i=0;
int begin=(i+1)-c[i]; // begin = 1 - c[0]; <<-- this could be arbitrarily small!
int end = (i+1)+c[i]; // unrelated
int j=begin; // also equal to 1-c[0]
while(i<n){
a[j-1]++; // increment a[-c[0]] which is UB unless c[0]==0
This means undefined behavior (UB), i.e., it could do nothing, it could segfault, or (what apparently happened in your case) access elements of an adjacent data structure.

Not declared in scope. Multiple errors

For some reason, I keep getting a scope error. I continue to get multiple scope errors as well as.
#include<iostream.h>
#include<fstream.h>
#include<assert.h>
void ScanInFile(int ScanInValues[], int *total)
{
int i=0;
while(!cin>>&ScanInValues[i].eof()){
i++;
*total = i;
}
}
void SortFile(int DataSetValues[], int TotalValues)
{
int i, j, temp;
for(i = 0; i < (TotalValues - 1); i++){
for(j=0; j < TotalValues - i -1; j++){
if(DataSetValues[j] > DataSetValues[j+1]){
temp = DataSetValues[j];
DataSetValues[j] = DataSetValues[j+1];
DataSetValues[j+1] = temp;
}
}
}
}
int main(void)
{
int i, AmountOfValues=0;
int values[100]={ 0 };
ScanInFile(values, &AmountOfValues);
SortFile(values, AmountOfValues);
for(i=0; i < AmountOfValues; i++){
cout<<values[i];
}
cout<<endl;
return 0;
}
For some reason G++ wont compile the program. I continue to get an error for saying endl and cout, and eof are not not in the scope. Where have I gone wrong?
Those objects are declared inside std namespace. Either you prepend std:: before them(std::cout << ...) or add using namespace std; at the beginning of your cpp file.
After you fix your eof error, you also want to check for out of bound access on your array since you never check size before writing.
In addition to what Eric has said, there are more problems in your code that have yet to be pointed out. There's one in your ScanInFile function in which you wrote this line:
while (!cin >> &ScanInValues[i].eof())
This line will compile, but it will do something very different than what you expect. I'm assuming you're performing extraction on this line but want to execute these extractions while the end-of-file has not been reached. There's no need for the .eof() as the stream will analyse the stream state itself through an implicit conversion to boolean. This is done as:
while (cin >> ScanInValues[i])
I don't want to overcompilcate my explanation, but I just want to stress that this is the preferred way of performing extraction. Using !eof() as a condition for extraction is almost always the wrong way to go.

Why is my program not printing perfect integers?

I am new to C++ programming and have a problem with one of my programs
#include <iostream>
using namespace std;
bool IsPerfect(int n);
int main ()
{
for(int i=1; i<100; i++){
IsPerfect(i);
}
return 0;
}
bool IsPerfect(int n){
int sum;
for(int x=1; x<n; x++){
if(n%x==0){
sum+=x;
return true;
cout <<n;
}
else{
return false;
}
}
}
I am trying to create a program that will list perfect numbers but I can't find the bug as to why it would not print.
I see 3 issues:
Your algorithm is wrong. Your loop terminates on the first time a number is evenly divisible by any factor (including 1). See Wikipedia for an explanation of the algorithm.
You have an uninitialized variable with int sum; Also, you only ever write to it, you don't read it in a useful manner ever.
You have unreachable code. Your cout << n; in the loop will never be hit.
Try the following corrected code:
#include <iostream>
#include <cassert>
using namespace std;
bool IsPerfect(int n)
{
int sum = 1;
for(int x = 2; x < n; ++x)
{
if(n % x == 0)
sum += x;
}
return sum == n;
}
int main ()
{
for(int i=1; i<100; i++){
if (IsPerfect(i))
cout << i << endl;
}
assert(IsPerfect(6));
assert(IsPerfect(28));
assert(IsPerfect(496));
return 0;
}
You have a return statement before you output statement here:
return true;
cout <<n;
you need to swap the order of these statements, you also probably want to add a comma or some other separator:
std::cout << n << ", " ;
return true;
I am not sure that is where you want to return from since you will exit the first time you enter that if statement, which will happen when x is 1.
If you want to capture perfect numbers - numbers which are equal to the sum of their divisors, correct? - you need to allow the loop to proceed (and the sum to actually, well, sum) without returning. Take your print statement and your return statements and place them after the end of your loop; you should be checking then if the sum you have calculated is equal to n.
All these answers are telling you to write the number before returning. But that's ignoring the poor design here: you have a function that decides whether a number is perfect; it should not be that function that also decides what to do with this information (print it, store it, send it over the network, ...).
This will also make your code more readable, because the name IsPerfect is misleading - it tells the reader that this function just returns whether the number is perfect. Thus, the loop in the main function reads as, "for the integers 1 to 100, ask whether it is perfect and ignore the answer". This is not a useful program.
Remove the cout line from IsPerfect completely and put it in main instead:
for (int x = 1; x < 100; ++x) {
if (IsPerfect(x)) {
std::cout << x << '\n';
}
}
Try this
if(n%x==0){
sum+=x;
cout <<n;
return true;
}
The issue is in here:
if(n%x==0){
sum+=x;
return true;
cout <<n;
}
the keyword return immediately ends the function and returns the appropriate value (true). This means that all statements following it won't be executed. Try the following:
if(n%x==0){
sum+=x;
cout <<n;
return true;
}
In addition to the problems others have pointed out, you will never compute the right answer because you didn't initialize your sum variable.
Change
int sum;
to
int sum=0;