X is used uninitialized in this function - c++

Why am i getting this warning?:
warning: 'row1[3]' is used uninitialized in this function [-Wuninitialized]
I've been googling this for some time but but i can't find any answers, probably just because i'm inept at searching answers on Google.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int setfunc(int x);
int main()
{
int row1[3]{0,0,0};
setfunc(row1[3]);
}
int setfunc(int x[])
{
string sub;
int rowset;
stringstream rs;
string snums;
int elementnum = sizeof(x) / sizeof(0);
for(int z = 1; z <= elementnum; z++)
{
int find = snums.find(",");
if(find == -1)break;
else
{
sub = snums.substr(0, snums.find(","));
rs << sub;
rs >> rowset;
snums.erase(0, snums.find(",") +1);
}
x[z] = rowset;
cout << x[z] << endl;
}
return 0;
}
All help appreciated

The behaviour of int row1[3]{0,0,0}; setfunc(row1[3]); is undefined. This is because the indexing runs from 0 to 2, so row1[3] is accessing the array outside its bounds. The compiler is helping you here, although in my opinion, the warning is a little misleading.
sizeof(x) / sizeof(0); is also incorrect. sizeof(0) is the size of an int since 0 is an int type. The normal idiom is sizeof(x) / sizeof(x[0]). But you can't do this either in your case since the function parameter x will have decayed into a pointer. You ought to pass the number of elements into the function explicitly.

Related

Can we pass an array to any function in C++?

I have passed an array of size 10 to a funtion to sort the array reversely, but it's going wrong after rightly sorting first five elements of the array.
I want to sort the array 'std' reversely here,
# include <iostream>
using namespace std;
int reverse(int a[]); //funtion prototype
int main()
{
int std[10] = {0,1,2,3,4,5,6,7,8,9};
reverse(std);
}
int reverse(int a[]) //funtion defination
{
int index = 0;
for (int i = 9; i >= 0; i--)
{
a[index] = a[i]; //swaping values of the array
cout << a[index] << " ";
index++;
}
}
There's basically three things wrong with your code.
You aren't swapping anything
You have to swap the first half of the array with the second half, not swap the whole array. If you do that then everything gets swapped twice, so that nothing changes
You should print the reversed array after you have finished the reverse, not while you are doing the reverse.
Here's some code that fixes all these problems
# include <iostream>
# include <utility>
void reverse(int a[]);
int main()
{
int std[10] = {0,1,2,3,4,5,6,7,8,9};
reverse(std);
// print the array after reversing it
for (int i = 0; i < 10; ++i)
std::cout << std[i] << ' ';
std::cout << '\n';
}
void reverse(int a[])
{
for (int i = 0; i < 5; ++i) // swap the first half of the array with the second half
{
std::swap(a[i], a[9 - i]); // real swap
}
}
Yes you can.
I usually don't use "C" style arrays anymore (they can still be useful, but the don't behave like objects). When passing "C" style arrays to functions you kind of always have to manuall pass the size of the array as well (or make assumptions). Those can lead to bugs. (not to mention pointer decay)
Here is an example :
#include <array>
#include <iostream>
// using namespace std; NO unlearn trhis
template<std::size_t N>
void reverse(std::array<int, N>& values)
{
int index = 0;
// you only should run until the middle of the array (size/2)
// or you start swapping back values.
for (int i = values.size() / 2; i >= 0; i--, index++)
{
// for swapping objects/values C++ has std::swap
// using functions like this shows WHAT you are doing by giving it a name
std::swap(values[index], values[i]);
}
}
int main()
{
std::array<int,10> values{ 0,1,2,3,4,5,6,7,8,9 };
reverse(values);
for (const int value : values)
{
std::cout << value << " ";
}
return 0;
}

Why is the function call happening for a differnet input and segfaulting?

This is my code for finding the longest collatz sequence between 1 and n. And obviously for t test cases. Here, I have also used memoization and thus malloced 'v'. But as the input to the function cycles(int x) goes beyond 4254, ie. 4255, there is something peculiar happening. The function is being input a number 6053452 instead of 4255. And due to this, the program segfaults, as we have only allocated space for 5000000 integers. What have I done wrong?
Note: The program works pleasantly till n = 4254! (not the factorial)
#include <iostream>
#include <cstdlib>
#define RANGE 5000000
using namespace std;
int *v = (int*)malloc(sizeof(int)*RANGE);
int cycles(int x){
int c = 1;
while(x!=1){
if(v[x]!=0){
c = c + v[x];
break;
}
if(x%2){
x = 3*x + 1;
}else{
x/=2;
}
c++;
}
v[x] = c;
return c;
}
void solve(int n){
int mx = 0;
int mx_cnt = 0;
int c;
for(int i=1;i<=n;i++){
c = cycles(i);
if(c >= mx_cnt){
mx = i;
mx_cnt = c;
}
}
cout << mx << endl;
}
int main(){
int t,n;
cin >> t;
while(t--){
cin >> n;
solve(n);
}
return 0;
}
The main problem that you observe is that you access v out of bounds. You also use the mallocd memory uninitialized which makes the program have another problem. Both results in undefined behavior.
int cycles(int x){
int c = 1;
while(x!=1){
if(v[x]!=0){ // <- x >= RANGE
c = c + v[x];
break;
}
// ...
To find problems like this I suggest using a vector instead and, at least when developing the program, use the vector::at() bounds checking member function.
std::vector<int> v(RANGE);
int cycles(int x){
int c = 1;
while(x!=1){
// The below use of `v.at(x)` may result in an exception like:
// what(): vector::_M_range_check:
// __n (which is 6053452) >= this->size() (which is 5000000)
if(v.at(x)!=0){
c = c + v[x];
break;
}
// ...
To catch the exception, you could rewrite main like this:
#include <exception>
int main() {
int t, n;
try {
std::cin >> t;
while(t--) {
cin >> n;
solve(n);
}
} catch(const std::exception& ex) {
std::cout << "Exception: " << ex.what() << '\n';
}
}
If you have a modern 64 bit computer, allocating a lot more shouldn't be a problem. I did this and it solved 4255 fine:
constexpr size_t RANGE = 6810137;
v points to a malloced array and malloc does no initialization. You have if(v[x]!=0) and c = c + v[x]; operating on an uninitialized variables. Embrace C++ and replace the malloced array with a std::vector. vector initializes its contents.
This might not be the only bug, just the most obvious.
Correction based on point raised by molbdnilo in the comments: I reached for too complicated a tool. int v[RANGE]; will allocate and zero-initialize the array. Since the array never changes size, a vector's dynamic array is unnecessary. Use std::array<int, RANGE> v; and you'll have a zero-initialized fixed-size array and still get useful functions like at for debugging.

Compiler error: invalid conversion from 'int' to 'int*' [-fpermissive]

I am having a problem with a program, and I'm getting the error above. However, when I search up the error, everyone else has some sort of int * variable whereas I don't have that all compared to them and is still getting this error.
#include <iostream>
#include <fstream>
const int VALUES = 250;
using namespace std;
void minFinder(int nums[]);
void maxFinder(int nums[]);
void arithmeticMeanFinder(int nums[]);
void geometricMeanFinder(int nums[]);
void standardDeviationFinder(int nums[]);
int main()
{
ifstream file;
int number, counter;
int nums [VALUES];
counter = 0;
file.open("F://Yes/Untitled.txt");
file >> number;
while (!file.fail()){
counter++;
nums [counter-1] = number;
file >> number;}
arithmeticMeanFinder(nums[VALUES]);
file.close();
system("pause");
return 0;
}
void arithmeticMeanFinder (int nums[VALUES])
{
ifstream file;
int ct, holder;
double counter, mean;
double accum = 0;
for (ct = 0; ct < VALUES; ct++){
holder = nums[ct];
accum = accum + holder;
counter++;}
mean = (accum * 1.0) / counter;
cout << counter << " is the arithmetic mean" << endl;
}
This code: arithmeticMeanFinder(nums[VALUES]); index into nums to retrieve the (nonexistent) item at the offset VALUES.
I'd guess you want it to be more like: arithmeticMeanFinder(nums);
The rest of the code isn't exactly what I'd like (e.g., it requires that the number of values in the file be exactly equal to VALUES, or it'll fail miserably), but that's the source of the specific problem the compiler is citing.
In your code, you have:
void arithmeticMeanFinder (int nums[VALUES])
Because of the rules of C++, this is equivalent to:
void arithmeticMeanFinder (int nums[])
And also because of the rules of C++, this is equivalent to:
void arithmeticMeanFinder (int *nums)
So when you call this function, you need to write:
arithmeticMeanFinder(nums); // pass the pointer to first element
Instead of:
arithmeticMeanFinder(nums[VALUES]);
In the call to arithmeticMeanFinder above, by expression nums[VALUES], you pass the VALUES-th element, which is an int, as the argument.
As the array nums has only VALUES items (maximum index is VALUE - 1),
this is an out-of-bound access.

Modify a variable passed by reference

I'm working on a function that finds the smallest element in an array. I'm trying to modify the variable s using pass by reference. I'm brand new to C++ and I'm not sure if I have done pass-by-reference correctly. Can anyone confirm that this is the correct way to do this, or suggest better ways to approach a min value function with pass by reference?
#include <cstdlib>
#include <stdlib.h>
#include <iostream>
using namespace std;
int smallestElm(int numArray[], int length, int &smallest);
int main() {
int n[3] = {2,5,3};
int s = 0;
int length = 0;
cout << smallestElm(n, length, s) << endl;
}
int smallestElm(int numArray[], int length, int &smallest) {
smallest = numArray[0];
length = sizeof (numArray) / sizeof (int);
for (int i = 1; i < length; i++) {
if (numArray[i] < smallest) {
smallest = numArray[i];
}
cout << smallest << endl;
return 0;
}
}
Yes this is correct, as you should be able to tell by yourself, by modifying your main function like this:
int main() {
int s = 0;
// call your function
cout << s << endl; // Here you print 's', thus you confirm whether you are right or not
}
If s wouldn't change its value, then your pass by reference won't be correct (since s does change its value inside the body of the function).
As for the function, it's wrong, since it will return before checking all the elements! So, change that to something like this to check all the elements of the array before saying for certain which the smallest element is:
#include <stdlib.h>
#include <iostream>
using namespace std;
void smallestElm(int numArray[], size_t length, int &smallest);
int main() {
int n[] = {2,5,3}; // size is not needed, it's automatically computed by the compiler
int s = 0;
size_t length = 3;
smallestElm(n, length, s);
cout << "smallest element = " << s << endl;
return 0;
}
void smallestElm(int numArray[], size_t length, int &smallest) {
smallest = numArray[0];
for (int i = 1; i < length; i++) {
if (numArray[i] < smallest) {
smallest = numArray[i];
}
cout << smallest << endl;
}
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
2
2
smallest element = 2
Don't forget that STL provides min_element, that you could use like this:
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int n[] = {2,5,3};
int *s = std::min_element(n, n + 3); // 3 size of the array
cout << "smallest element = " << *s << endl;
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
smallest element = 2
Can anyone confirm that this is the correct way to do this
Yes, that is the correct way to declare a reference argument. And yes, you can modify objects through a reference.
or suggest better ways to approach a min value function ...
A better way would arguably be to return the min value, instead of modifying an argument. Right now the function always returns 0, which seems useless.
... with pass by reference
That's a silly idea, but your approach is correct way to pass by reference. The function itself has multiple bugs.
It seems to always return after the first iteration, so it'll always find one of the first 2 element to be "smallest".
The value of int length argument is never used. It is overridden before use.
sizeof (numArray) returns the size of the pointer numArray which is not in any way related to the size of the pointed array.
The function always uses numArray[0] so it will have undefined behaviour if length == 0.
It's correct your code, but there is another way: Using a pointer to int, into the function argument and invoke this with the address of memory of variable s, as the below sample shows:
#include <stdlib.h>
#include <iostream>
using namespace std;
void smallestElm(int numArray[], size_t length, int *smallest);
int main() {
int n[] = {2,5,3}; // size is not needed, it's automatically computed by the compiler
int s = 0;
size_t length = 3;
smallestElm(n, length, &s);
cout << "smallest element = " << s << endl;
return 0;
}
void smallestElm(int numArray[], size_t length, int *smallest) {
*smallest = numArray[0];
for (int i = 1; i < length; i++) {
if (numArray[i] < *smallest) {
*smallest = numArray[i];
}
cout << *smallest << endl;
}
}

c++ two errors while compiling

I'm a beginner in c++ and I'm getting two errors in my code and I don't know how to fix them...
the first one
illegal indirection
and the second one is
'=' left operand must be a I-value. (in the line: ((ArrayPtr +i)+j)=rand()%55+1 )
Does anyone have an idea how to fix them? That's my code:
#include <iostream>
#include <math.h>
#include <time.h>
#include<iomanip>
#include<array>
#include <algorithm>
using namespace std;
const int AS = 6;
void FillingRandomly(int (*)[AS]);
void printing(int (*)[AS]);
int c;
int main()
{
int funny = 0;
int timpa = 0;
int counter = 0;
int Array[AS][AS];
srand(time(0));
FillingRandomly(Array);
cout << "The unsorted array is" << endl << endl;
printing(Array);
cout << "The sorted array is" << endl << endl;
printing(Array);
system("PAUSE");
return 0;
}
void FillingRandomly(int *ArrayPtr)
{
for(int i=0;i<AS;i++)
{
for (int j=0;j<AS;j++)
{
*(*(ArrayPtr +i)+j)=rand()%55+1;
}
}
}
void printing(int *Array)
{
for(int i=0;i<AS;i++)
{
for (int j=0;j<AS*AS;j++)
{
int counter = 0;
cout<<((Array[i] +j))<<setw(5);
if ((Array[i] +j)%AS == 0)
cout << endl << endl;
}
}
}
void forsorting(int *Brray, int funny)
{
int dice = 0;
int super = 0;
int space=0;
//Sorting Array[][] which is treated like Array[]
{
for (int pass = 0; pass < AS - 1; pass++) {
for (int k = 0; k < AS - 1; k++) {
int temp;
if(*(Brray+k)==*(Brray+k+1))
{
temp=*(Brray+k);
*(Brray+k)=*(Brray+k+1);
*(Brray+k+1)=temp;
}
}
}
}
}
By
*(*(ArrayPtr +i)+j)=rand()%55+1;
it seems you want
ArrayPtr[i][j] = (rand() % 55) + 1;
You can try something along the line of
int const offset = AS * i + j;
int const elem = (rand() % 55) + 1;
*(ArrayPtr + offset) = elem;
Your function signature is:
void FillingRandomly(int *ArrayPtr)
where you are telling to compiler that you are passing a simple pointer, but in the line:
*(*(ArrayPtr +i)+j)=rand()%55+1;
you are doing a double derreference, which is illegal and causing the compiler to complain
COMPLEMENT
I was seeing the comments in the other answer and, as what I need to write is bigger than the reserved commentary space, I decided to complement my own answer.
You defined Array as:
int Array[AS][AS];
Indeed, what you are doing is a promise to compiler that you will use Array as defined, but the compiler doesn't believe in you too much, so that any time you use Array the compiler will make sure that it is being used as declared.
The problem arises when you declare your FillingRandomly function. Here you are broking your promise and are trying to use Array by declaring a differente type. Note how you declare your function:
void FillingRandomly(int *ArrayPtr)
Due the fact that c++ supports function overloading, the compiler doesn't warn you until it initiate the linking phase, when it is unable to find a function whose signature is:
void FillingRandomly(int ArrayPtr[][AS])
note that both are different.
Once you are a beginner, the best way to keep your programs correctly is to keep your promise immutable. Bellow I show you a piece of your own code, correcting those issues for FillingRandomly function (you have to correct it for the others functions too):
const int AS = 6;
void FillingRandomly(int [][AS]); // Note that I've changed your prototype here
....
void FillingRandomly(int ArrayPtr[][AS]) // Keep your function signature the same as your prototype signature
{
for(int i=0;i<AS;i++)
{
for (int j=0;j<AS;j++)
{
ArrayPtr[i][j]=rand()%55+1; // Note how ArrayPtr is being used exactly as your promised early
}
}
}