So I have some code that works, but valgrind says that there is a conditional jump that depends on uninitialized value(s). I think I know what's causing this (see below) but I don't know of any alternatives/solutions.
class Vector{
private:
int maxLength;
int *buffer;
void error(char* msg){
cerr << "Error: " << msg << endl;
}
bool inBounds(int i){
return i>=0 && i < maxLength;
}
public:
Vector(int newLenth)
: maxLength(newLenth), buffer(new int[newLenth])
{
}
int & operator [] (int index){
if (!inBounds(index)){
error("Out of bounds");
}
return buffer[index];
}
int length(){
int count =0;
for (int i = 0; buffer[i];++i){
count +=1;
}
return count;
}
};
I think the problem is that in the for loop, buffer[i] isn't "initialized". What should I do to fix this? (At a level of a c++ novice, please)
int main(){
Vector v(10);
v[0] = 1;
cout << v.length() << endl;
}
The loop progresses until it finds zero in the buffer array, i.e. it expects the buffer to be null-terminated. You place 1 into the initial element, but the element right after it remains uninitialized.
Placing zero into it will fix the problem:
Vector v(10);
v[0] = 1;
v[1] = 0;
cout << v.length() << endl;
Note: You should make your loop safe by terminating upon reaching maxLength as well:
for (int i = 0 ; i != maxLength && buffer[i] ; ++i) {
count++;
}
This will ensure that you do not probe positions past the end of the buffer for zero.
You can initialize the buffer easily with
: maxLength(newLenth), buffer(new int[newLenth]{})
^^- note
That would make all elements (maxLength of them) in buffer initialized to int default value (which is 0).
Related
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;
The following program is intended to check if a given element is in a given array, indices of array where the element occurs and number of times the element occurs. But, it doesn't give right results. I tried to replace poscount in seqsearch function with *poscount and did further changes for this pointer data type. Then the code works well. Why this is so?
#include <iostream>
using namespace std;
const int SIZE = 100;
void seqsearch(int[], int, int, int[], short);
int main() {
int array[SIZE], indices[SIZE];
int num, value;
short count = 0;
cerr << " Give number of elements in array : ";
cin >> num;
cerr << " Key in the array elements ";
for(int i = 0; i < num; i++) cin >> array[i];
cout << endl;
cerr << " Give the value to be searched : " << endl;
cin >> value;
cout << endl;
seqsearch(array, num, value, indices, count); // void function
if(count >= 0) {
cout << value << " found in array " << count << " times"
<< " at index positions " << endl;
for(int i = 0; i < count; i++) cout << indices[i] << " ";
cout << endl;
} else
cout << value << " not found in array " << endl;
return 0;
}
void seqsearch(int arr[], int size, int elm, int pos[], short poscount) {
int i, item;
poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return;
}
The function seqsearch is supposed to return the result in pos and poscount, but the function takes poscount by-value which means that any changes you make to poscount inside the function, will be local to the function and not visible from the call site.
If you change the function to take the argument by-reference, the changes you make inside the function will actually be made to the variable used in the call to the function. Like this:
seqsearch(int arr[], int size, int elm, int pos[], short& poscount) // note short&
The int pos[] does not have the same problem because arrays decay into pointers, so it could have been int* pos instead - and that pointer points at the same array that you passed in at the call site.
Also note that the check after the call will make the program display "found in array" even if it isn't found in the array because the condition checks if count is zero or greater than zero.
if(count >= 0) { // should be if(count > 0) {
Suggestions unrelated to the problem in your question:
When the number of elements is not known at the time you compile your program, prefer to use a container which can grow dynamically, like a std::vector<int>. In your program you have a hardcoded limit of SIZE number of elements, but:
You will rarely use all of them.
You do not check if the user wants to enter more than SIZE elements and your program will gladly try to write out of bounds - which would cause undefined behavior.
Divide the program's subtasks into functions. It'll be easier to search for bugs if you can test each individual function separately.
Check that extracting values from std::cin actually succeeds.
int number;
if(std::cin >> number) { /* success */ } else { /* failure */ }
Check that the values entered makes sense too.
int wanted_container_elements;
if(std::cin >> wanted_container_elements && wanted_container_elements > 0) {
/* success */
} else {
/* failure */
}
poscount (or count in the context of the caller) in your code seems to be expected to be an output parameter.
To modify the passed value you must either have its address (a pointer) or a reference to the value.
Currently you are using "pass-by-value", meaning that poscount is a copy of count.
The original count stays untouched.
My personal favorite would be to return the value instead of using an out-parameter:
short seqsearch(int arr[], int size, int elm, int pos[]) {
int i, item;
short poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return poscount;
}
count = seqsearch(array, num, value, indices);
Alternatively you can use a reference to manipulate the out-parameter:
void seqsearch(int arr[], int size, int elm, int pos[], short& poscount) {
int i, item;
poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return;
}
seqsearch(array, num, value, indices, count);
And, as you already tried, you can also solve this by passing a pointer to the value:
void seqsearch(int arr[], int size, int elm, int pos[], short* poscount) {
int i, item;
*poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[*poscount] = i;
*poscount = *poscount + 1;
}
}
return;
}
seqsearch(array, num, value, indices, &count);
When you pass your posscount argument, you pass a copy to the count variable in main, not the variable itself. That's why it works, when you pass it by pointer. You can also pass by reference. https://www.includehelp.com/cpp-tutorial/argument-passing-with-its-types.aspx
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;
for one of my assignments I have to create a class that creates a dynamic array and has methods to add or remove a number from the array, I figured out how to do the add method and it works fine but I cannot figure out how to remove an element and make the size of the array decrease by one.
#include <iostream>
using namespace std;
class IntegerDynamicArray
{
public:
IntegerDynamicArray()
{
currentSize = 0;
maxSize = 10;
dynamicArray = new int[maxSize];
}
int add(int x);
bool remove(int x);
private:
int* dynamicArray;
int currentSize;
int maxSize;
};
int IntegerDynamicArray::add(int x)
{
if (currentSize == maxSize)
{
maxSize = maxSize * 2;
int* tempArray = new int[maxSize];
for (int i = 0; i < currentSize; i++)
{
tempArray[i] = dynamicArray[i];
}
tempArray[currentSize] = x;
currentSize++;
dynamicArray = tempArray;
}
else
{
dynamicArray[currentSize] = x;
currentSize++;
}
return currentSize;
}
bool IntegerDynamicArray::remove(int x)
{
for (int i = 0; i < currentSize; i++)
{
if (dynamicArray[i] == x)
{
//TODO need to delete the number and move all numbers "back" by one
return true;
}
}
return false;
}
int main()
{
IntegerDynamicArray intDynArray;
while (1)
{
char input;
cout << "Enter A for add or R for remove: ";
cin >> input;
if (input == 'A')
{
cout << "Enter number to add: ";
int x;
cin >> x;
cout << intDynArray.add(x) << endl;
}
else if (input == 'R')
{
cout << "Enter number to remove: ";
int x;
cin >> x;
cout << intDynArray.remove(x) << endl;
}
}
}
The add function leaks memory because you did not deallocate dynamicArray before assigning it to the new block of memory. You should also provide a destructor. Use delete[] rather than delete since you are allocating an array. The conditional within remove does not appear to be correct. I would think that x indicates the element to remove, but you are searching for an element with value == x. I would think that you would first validate that x is a valid index (less than current size), and then use x to loop from that element to the end copying all of the elements forward. Then zero initialize between currentSize and max size. That would be one way to do it. This look like homework, so I will only provide guidance and not the code. Try it. Based on what you wrote so far, I think that you can figure that out.
Update: It is true that if you add a destructor that handling copy construction and assignment (somehow) is critical.
If you really want to remove occurrences of a value rather than the element, then I suggest you do it similarly to how the remove algorithm does it. Essentially you would start at the beginning, loop and copy forward over the matched values. Since you aren't dealing with iterators you'd have to get creative and adjust your current size but the example there on cplusplus.com should be invaluable in helping you write your function. Although technically you don't have to zero initialize those "removed" slots, I think that it is a good idea so that you don't get confused while debugging. Stale data in those unused slots doesn't help but it could get confusing while looking at the data in a debugger.
This ought to do it:
bool IntegerDynamicArray::remove(int x)
{
for (int i = 0; i < currentSize; i++)
{
if (dynamicArray[i] == x)
{
int *newArray = new int[currentSize-1];
std::copy(dynamicArray, dynamicArray+i, newArray);
std::copy(dynamicArray+i+1, dynamicArray+currentSize, newArray+i);
delete[] dynamicArray;
dynamicArray = newArray;
--currentSize;
return true;
}
}
return false;
}
If you want to remove the first occurrence only you can do something like that. I didn't test the code but it should be fine.
bool IntegerDynamicArray::remove(int x)
{
for (int i = 0; i < currentSize; i++)
{
if (dynamicArray[i] == x)
{
for ( ; i < currentSize - 1; i++)
{
// Assign the next element to current location.
dynamicArray[i] = dynamicArray[i + 1];
}
// Remove the last element as it has been moved to previous index.
dynamicArray[currentSize - 1] = 0;
currentSize = currentSize - 1;
return true;
}
}
return false;
}
You can also write a function that removes all occurrences of the value or as #shawn1874 suggested you can remove the item with the given index.
I'm working on a program for Project Euler to add all the digits of 2^1000. So far I've been able to track the program segmentation faults when it reaches around 5 digits and tries to push a one onto the vector at line 61 in the function carry().
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class MegaNumber
{
vector<int> data; //carries an array of numbers under ten, would be char but for simplicity's sake
void multiplyAssign(int operand, int index); //the recursive function called by the *= operator
void carry(int index);//if one of the data entries becomes more than ten call this function
public:
void printNumber(); //does what it says on the can
void operator*=(MegaNumber operand);
void operator*=(int operand);
void operator+=(int operand);
MegaNumber(string);
unsigned long int AddAllDigits();//returns the value of all of the digits summed
};
MegaNumber::MegaNumber(string operand)
{
for(int i= operand.size()-1; i>=0;i--) //run it into the memory smallest digit first
{
data.push_back(operand[i]-48); //converts a text char to an int
}
}
void MegaNumber::printNumber()
{
int temp = data.size();
for(unsigned int i=(temp); i>0;--i)
{
cout << (int)data[i-1];
}
}
void MegaNumber::operator*=(int operand)
{
if(operand > 9)
{
cout << "function does not yet deal with large ints than 9";
}
else multiplyAssign(operand, 0);
}
void MegaNumber::multiplyAssign(int operand, int index)
{
data[index] *=operand;
if(index<data.size()) multiplyAssign(operand, index+1);
if(data[index] > 9) carry(index);
}
void MegaNumber::carry(int index)
{
int temp = (data[index] / 10); //calculate the amount to carry
if(data.size()==index+1)
{
data.push_back(temp);//if there is no upper digit push it onto the stack
}
else
{
data[index+1]+=temp; //else add it to the next digit
if(data[index+1]>9) carry(index+1); //rinse and repeat
}
data[index]-=temp*10; //remove what's been carried
}
unsigned long int MegaNumber::AddAllDigits() //does what it says on the can
{
unsigned long int Dagger = 0;
for(int i=0; i<data.size();i++) Dagger+=data[i];
return Dagger;
}
int main()
{
MegaNumber A("2");
A.printNumber();
cout << "\n";
for(unsigned int i=0; i<20; i++) A*=2;
A.printNumber();
cout << "\n";
cout << A.AddAllDigits() << "\n";
cout << "Hello world!" << endl;
return 0;
}
What may be causing this?
You use data[index] before checking if it's a valid index, in multiplyAssign:
data[index] *= operand;
if(index<data.size()) multiplyAssign(operand, index+1);
Also use '0' instead of 48. This is easier, clearer, and less bug-prone.
void MegaNumber::multiplyAssign(int operand, int index)
{
data[index] *=operand;
if(index<data.size()) multiplyAssign(operand, index+1);
if(data[index] > 9) carry(index);
}
index is 0 based, while data.size() is 1 based so to say, meaning data.size() returns number 1 greater than the largest valid index.
So looks like you intention was
if( index < data.size() - 1) multiplyAssign(operand, index+1);
Then it works.
P.S. break your code into lines, whoever has to maintain your code will thank you for that:
if (index < data.size() - 1)
{
multiplyAssign(operand, index + 1);
}
I think the problem could be here: data[index+1]+=temp;
This element could not be exist if index parameter eq. to size of data.
So, my recommendations:
Use Iterators to access std::vector
Check bound conditions if you do not use Iterators