How to solve RUN_ERROR even though it compiles normally? - c++

I am currently writing a script about finding the nearest duplicate from a user entered size array.
The array must be between 1 and 10^5 and its value has to be between 1 and 10^5 also.
It compiles normally on my computer but whenever I submit it, it returns a run_error.
Here's what I wrote.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void input (int *);
int main(){
int n;
input (&n);
int a[n];
for(int i=0;i<n;i++){
if (scanf("%d",&a[i])!=1)
return 0;
if ((a[i]>100000)||(a[i]<1))
return 0;
}
for (int i=0;i<n;i++){
if (a[abs(a[i])]>=0){
a[abs(a[i])]=-a[abs(a[i])];
} else {
printf("%d",abs(a[i]));
return 0;
}
}
return 0;
}
void input(int *x){
if (scanf("%d",x)!=1)
exit(0);
if ((*x>100000)||(*x<1))
exit(0);
}

This program is logically incorrect. There is no connection between the size of the array defined in n and the limit of the allowed elements.
Since you have allowed a[i]>100000 to go up to 10^5 with no regards to the size of the array defined by a[n], the following access will attempt to access outside the bounds of the array, a[abs(a[i])] for any a[i] > n.
Also, you can pass by reference for syntactical simplicity
input(n);
void input(int &x){
if (scanf("%d",&x)!=1)
exit(0);
if (x>100000 ||x<1)
exit(0);
}

First of all, if you are writing in C, please tag this question as C question, and not as C++ one. scanf & printf are C functions, as much as your includes stdio.h & stdlib.h & math.h. In c++ you have the include iostream, and in this case it's all you really need.
The second problem here is the way you handle the input validation when it wrong. exit is very dangerous way, and very not recommended. If you want to throw exception use throw method (Read about the difference between the two: https://stackoverflow.com/a/56406586/8038186). But, in this case I don't understand why do you need to throw exception at all. you can simply finish the program in more gentle way. Consider the following flow:
#include <iostream>
using namespace std;
// Num is moved by reference and not by pointer
bool input(int &num) { // return true if the input is good, otherwise return false.
cout << "Please enter number: " << endl; // Tell the user that he should enter a number.
cin << num;
bool is_valid = num >= 1 && num <= 1e5; // 1e5 = 100000
if (!is_valid) cout << "Invalid input." << endl;
return is_valid;
}
int main() {
int n;
if (!input(n)) {
return 0;
}
int a[n];
int i;
for (i = 0; i < n && input(a[i]); i++);
if (i < n) {
return 0;
}
for (i = 0; i < n; i++) {
// The following if is useless, the validation make sure already that all of the numbers are legal.
//if (a[a[i]] >= 0) { // You don't need abs(a[i]), a[i] > 1
if (a[i] < n)
a[a[i]] = -a[a[i]];
else cout << "Consider what do you want to do" << endl;
/*} else {
printf("%d", a[i]);
return 0;
}*/
}
return 0;
}
Read about the difference between reference and pointer: What are the differences between a pointer variable and a reference variable in C++?

Related

Selection Sort Implementation with C++ incorrect

really new to C++, trying to instantiate some basic algorithms with it. Having trouble returning the correct result for selection sort. Here is my code
#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Selection Sort :
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
return m;
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void selectionSort(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); ++i)
{
int min = findMin(arr, i);
swap(arr[i], arr[min]); // Assume a correct swap function
}
}
}
void print(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << "";
cout << endl;
}
}
}
int main()
{
vector<int> sort;
sort.push_back(2);
sort.push_back(1);
sort.push_back(7);
sort.push_back(4);
sort.push_back(5);
sort.push_back(3);
print(sort);
cout << "this was unsorted array";
cout << endl;
cout << findMin(sort, 0);
cout << "this was minimum";
cout << endl;
selectionSort(sort);
print(sort);
}
I am getting the following results:
comparison_sort.cpp:20:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
2
1
7
4
5
3
this was unsorted array
1
this was minimum
1
2
4
5
3
0
My question is: What is causing this control path error? Why is the "7" here being replaced with a "0"?
Thanks in advance! Sorry for the noob question.
I have reviewed all my current functions and nothing seems to explain why the 7 is replaced with a 0. I have tried multiple integers and it looks like the maximum number is always replaced.
The warning is very real, and it alludes to the problem that's breaking your sort as well.
You are currently returning m inside your loop body. What that means is that if the loop is entered, then the function will return m on the very first time around the loop. It only has a chance to check the first element.
And of course, if a is the last index of the array, then the loop will never execute, and you will never explicitly return a value. This is the "control path" which does not return a value.
It's quite clear that you've accidentally put return m; in the wrong place, and even though you have good code indentation, some inexplicable force is preventing you from seeing this. To fix both the warning and the sorting issue, move return m; outside the loop:
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
}
return m;
}

How do I fix this warning - "control reaches end of non-void function [-Wreturn-type]"

During compiling, it shows this warning - control reaches end of non-void function [-Wreturn-type]. I googled and found that this warning shows when you don't return anything in the function. But I couldn't figure out where's the error in my code.
Here's my code:
#include <iostream>
#include <algorithm>
using namespace std;
int findUnique(int *a, int n){
sort(a, a+n);
int i=0;
while(i<n){
if(a[i]==a[i+1]){
i += 2;
}
else{
return a[i];
}
}
}
int main(){
int t;
cin >> t;
while (t--){
int size;
cin >> size;
int *input = new int[size];
for (int i = 0; i < size; ++i)
{
cin >> input[i];
}
cout << findUnique(input, size) << endl;
}
return 0;
}
You have to know why this warning is shown to understand what to do about it, this warning is shown when your function has a return type but you haven't returned value from one or more exit points of a function. Now see in your function, you return a[i] but consider a situation where your code doesn't go in the else block at all. So after coming out of the while block. There is no return statement therefore compiler is throwing control reaches the end of non-void function [-Wreturn-type].
The function returns nothing in case when the array does not contain a unique number or when the parameter n is equal to 0.
So the compiler issues the warning message.
Moreover the while loop can invoke undefined behavior when i is equal to n-1 due to using a non-existent element with the index n in this if statement
if(a[i]==a[i+1]){
Also there is a logical error. The if statement
if(a[i]==a[i+1]){
i += 2;
}
else{
return a[i];
}
does not guarantee that indeed a unique number will be returned.
Using your approach when it is allowed to change the original array by calling the algorithm std::sort the function can be defined for example the following way
size_t findUnique( int *a, size_t n )
{
std::sort( a, a + n );
size_t i = 0;
bool unique = false;
while ( !unique && i != n )
{
size_t j = i++;
while ( i != n && a[i] == a[j] ) i++;
unique = i - j == 1;
}
return unique ? i - 1 : i;
}
And in main the function can be called like
size_t pos = findUnique(input, size);
if ( pos != size )
{
cout << input[pos] << endl;
}
else
{
// output a message that there is no unique number
}
Pay attention to that your program produces multiple memory leaks. You need to free the allocated memory in each iteration of the while loop.
The problem is in the function findUnique This function is supposed to return int no matter what although in your code you are returning an integer only under certain conditions
Here is a possible fix:
// return true if unique number found
// return false otherwise
bool findUnique(int *a, int n, int *unique){
sort(a, a+n);
int i=0;
while(i<n){
if(a[i]==a[i+1]){
i += 2;
}
else{
*unique = a[i];
return true;
}
}
return false;
}
Then in the main something like that:
int unique;
bool uniqueFound = findUnique(input, size &unique);
if (uniqueFound == true)
cout << unique << endl;
else
cout << "No unique number found" << endl;

Convert userInput (string) to UserInput(int) mid for loop

I am working on a program that has to do with arrays. I decided that the input the user provides to be a string to later being converted to an integer once it is determined it is one. This way the program wouldn't run into an error when words/letters are entered. The issue I am having is the conversion from string to int. I want to change that because later in the program I am going to search the array for a given value and display it and its placement in the array. This is the code I have thus far:
#include <stdio.h>
#include <iostream>
using namespace std;
//check if number or string
bool check_number(string str) {
for (int i = 0; i < str.length(); i++)
if (isdigit(str[i]) == false)
return false;
return true;
}
int main()
{
const int size = 9 ;
int x, UserInput[size], findMe;
string userInput[size];
cout << "Enter "<< size <<" numbers: ";
for (int x =0; x < size; x++)
{
cin >> userInput[x];
if (check_number(userInput[x]))
{//the string is an int
}
else
{//the string is not an int
cout<<userInput[x]<< " is a string." << "Please enter a number: ";
cin >> userInput[x];}
}
int i;
for (int i =0; i < size; i++)
{
int UserInput[x] = std::stoi(userInput[x]); // error occurs here
}
for (int x= 0; x< size; x++)
{
if (UserInput = findMe)
{
cout <<"The number "<< UserInput[x] << "was found at " << x << "\n";
}
else
{
//want code to continue if the number the user is looking for isn't what is found
}
}
return 0;
}
Made comments here and there to kinda layout what I want the code to do and whatnot. I apperciate any help you can give, thank you.
This code:
int UserInput[x] = std::stoi(userInput[x]);
declares an int array of size x, to which you are assigning a single int (the result of std::stoi), which obviously doesn't work.
You need to assign an int to a particular index of the existing array, like this:
UserInput[x] = std::stoi(userInput[x]);
Given this comparison if (UserInput = findMe), which should actually be if (UserInput == findMe), it seems you want to declare a single int which stores the result of std::stoi. In that case, you should use a different name than the array, and write something like this:
int SingleUserInput = std::stoi(userInput[x]);
Also, please indent your code consistently, and compile with all your warnings turned on. Your code will be easier to read, and the compiler will point out additional problems with your code. And please don't use using namespace std;, it's a bad habit.
I don't understand why do u even need to use another loop to convert the string value to int. stdio.h header file does provides with preinstalled functions to make your work easier...
for (int x =0; x < size; x++)
{
getline(cin,userInput1[x]);
UserInput[x]=stoi(userInput1[x]);
}
stoi() function converts the string input to int, and you can call it dynamically as soon as you enter your string input,It will make you work easier and reduce the time complexity

Run-time check: stack around variable was corrupted

I am creating a program that rewrites an array with values from a file. I have linked the code below. When running the file I get the error "Run-time check failure, stack around 'arr' variable was corrupted.
Also, the output of the program returns all the array locations with the same number,
arr[0] = -858993460
The numbers in the file, separated by a line are:
12
13
15
#include<iostream>;
#include<fstream>;
using namespace std;
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
bool getNumbers(char * file, int * a, int & size)//not done
{
int count = 0;
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
}
void testGetNumbers()
{
int arr[5];
int size = 5;
cout << "Testing init and getNumbers." << endl;
init(arr, 5, -1);
cout << "Before getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
if (getNumbers("nums.txt", arr, size))
{
cout << size << " numbers read from file" << endl;
}
else
{
cout << "Array not large enough" << endl;
}
cout << "After getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
cout << endl;
}
int main()
{
testGetNumbers();
return 0;
}
This line in the first loop looks like having error.
a[size] = v;
It causes out of array bound access and memory/stack corruption. It should be
a[i] = v;
Starting with the main function, the line
return 0;
... is not necessary because that's the default return value for main. I would remove it, some people insist on having it, I think most people don't care. But it's always a good idea to be fully aware of what the code expresses, implicitly or explicitly, so: returning 0 expresses that the program succeeded.
For an explicit main return value I recommend using the names EXIT_SUCCESS and EXIT_FAILURE from the <stdlib.h> header.
Then it's much more clear.
main calls testGetNumbers, which, except for an output statement, starts like this:
int arr[5];
int size = 5;
init(arr, 5, -1);
As it happens the init function is has Undefined Behavior and doesn't fill the array with -1 values as intended, but disregard. For now, look only at the verbosity above. Consider writing this instead:
vector<int> arr( 5, -1 );
Using std::vector from the <vector> header.
Following the call chain down into init, one finds
a[size] = v;
That attempts to assign value v to the item just beyond the end of the array.
That has Undefined Behavior.
Should probably be
a[i] = v;
But as noted, this whole function is redundant when you use std::vector, as you should unless strictly forbidden by your teacher.
Back up in testGetNumbers it proceeds to call getNumbers, in that function we find
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
Generally one should never use f.good() or f.eof() in a loop condition: use f.fail(). Also, ~never compare a boolean to true or false, just use it directly. Then the loop can look like this:
ifstream f(file);
while (!f.fail() && count < 1)
{
f >> a[count];
count++;
}
Tip: in standard C++ you can write ! as not and && as and. With the Visual C++ compiler you have to include the <iso646.h> header to do that.
Disclaimer: the fixes noted here do not guarantee that the loop is correct for your intended purpose. Indeed the increment of count also when the input operation fails, looks probably unintended. Ditto for the loop limit.
The function continues (or rather, ends) with
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
This has a big problem: what if size == count? Then the execution continues to fall off the end of the function without returning a value. This is again Undefined Behavior.
I leave it to you to decide what you want the function to return in that case, and ensure that it does that.
In your init function...
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
Nope:
a[size] = v;
Yup:
a[i] = v;

Variables being affected by 'bad' instructions

Below is my code, for solving problem 7 of PE ("find the 10001th prime"):
#include <iostream>
using namespace std;
bool isPrime(int n, int primes[], int l){
int i=0;
for (int i=0; i < l; i++){
if (primes[i] != 0 && n%primes[i] == 0){
return false;
}
}
return true;
}
int main()
{
int k=3;
int primes[10001] = {0};
primes[0]=2;
const int l=sizeof(primes)/sizeof(primes[0]);
int N=0;
while (N < l){
if(isPrime(k, primes, l)==true){
primes[++N]=k;
}
k+=2;
}
cout << primes[l-1] << endl;
return 0;
}
This code solves the problem, but there is a mistake in it: on the final iteration of the while loop, the instruction is to set primes[10001]=k;, which attempts to change a value of an element of an array that doesn't exist. If I don't declare it to be constant, and (as a means of troubleshooting) replace l by 10001 in the while loop, the value of l becomes equal to the 10002th prime at the end of the loop.
Here is the main function part of this happening:
int main()
{
int k=3;
int primes[10001] = {0};
primes[0]=2;
int l=sizeof(primes)/sizeof(primes[0]);
int N=0;
while (N < l){
if(isPrime(k, primes, 10001)==true){
primes[++N]=k;
}
k+=2;
}
cout << l << endl;
return 0;
}
My question is, why does this happen? I do know that a simple fix is to stop the loop at l-1 (or better, initialize with N=1 instead and increment N after), but I'm more interested in how this code can affect a variable that isn't being explicitly (directly?) involved in the bad part of the code.
Thank you!
The [] Operator does no bounds checking. some_array[102], will simple go 102 * sizeof(type) if thats outside your array, thats outside your array. C++ won't care.
These are some of the nastiest bugs that can generated if you are lucky you program will crash, sometimes you can just end up changing somebody else's variable.
Which is why I harp on at work about using std::array and std::vector alot because they come with .at(i) functions which have bounds checking.