I'm pretty new to coding and stumbled upon this issue when trying to code a program that prints the biggest number in an array.
Basically, if I don't include cout<<i;, the printf() will print the array location instead of the number 20. Any ideas why? (I'm guessing it is something stupid I overlooked, so sorry in advance).
#include <iostream>
using namespace std;
int maxinlst(int lst[], int size) {
int maxNum;
for (int i = 0; i < size; i++) {
cout << i;
if (lst[i] == lst[0])
int maxNum = lst[i];
else if (maxNum < lst[i]) {
maxNum = lst[i];
}
}
return maxNum;
}
int main() {
int lst[] = {-19, -3, 20, -1, 5, -25};
printf("%i", maxinlst(lst, 6));
}
You shadow maxInt by declaring another variable with the same name. See my comments here:
int maxinlst(int lst[], int size) {
// First declaration
int maxNum;
for (int i = 0; i < size; i++) {
cout << i;
if (lst[i] == lst[0])
// Second declaration
int maxNum = lst[i];
else if (maxNum < lst[i]) {
maxNum = lst[i];
}
}
return maxNum;
}
This is legal in C++, and in most languages with block scope. The second declaration creates a new variable, but it's never used because it goes out of scope immediately, so the whole assignment, along with the conditional, can be eliminated by the compiler. If you enable compiler warnings, you should get a warning about the second declaration because that variable is never used again:
test.cpp: In function ‘int maxinlst(int*, int)’:
test.cpp:8:17: error: unused variable ‘maxNum’ [-Werror=unused-variable]
int maxNum = lst[i];
^~~~~~
This also means that the value of the outer maxNum after the first iteration of the loop is indeterminate and reading it could be undefined behavior so the second loop iteration is either going to (a) use an indeterminate value since the outer maxNum was never assigned or (b) something else entirely because of UB.
If the second conditional is never true (assuming an indeterminate value and not UB) then the value returned by this function will also be indeterminate -- whatever unpredictable number maxNum happened to be.
The correction here would be to remove int in the second declaration.
You could also rewrite this to avoid the first in-loop conditional:
int maxinlst(int lst[], int size) {
// First declaration
int maxNum = lst[0];
for (int i = 1; i < size; i++) {
if (maxNum < lst[i]) {
maxNum = lst[i];
}
}
return maxNum;
}
As far as why cout << i changes the value you see, that's exactly the nature of using indeterminate values / undefined behavior. You can't reason about what's happening. Adding or removing other code could also change the value returned by the function. You may even see different values if you run the program multiple times without making any changes to it.
You actually have two variables called maxNum. Inside your if statement, int maxNum = lst[i] defines a new variable called maxNum which hides the outer maxNum variable. The inner, newly defined maxNum is destroyed as soon as the program exits the if statement.
What makes you think that the array location is being print?
maxNum is not set to a particular value when it is defined. Because of that it's just going to have whatever was stored in the memory before.
If that value in memory is large, then maxNum will be larger than all the values in your array, then maxNum will never change and it will keep the garbage value.
So, when you get to your printf statement, the garbage value will be output. I doubt that the location of the array is being output. I bet that it's just whatever garbage was in memory.
Related
i am trying to pass my array through my assign and draw functions. the assign function only exists to take the wins array and assign a value of 0 for all of the elements in the array. my draw function fills the array with random numbers 1-100 with 20 numbers in the array. when i try to compile i end up with a runtime error stating that the stack around my variable (array) wins is corrupted. where should i go from here?
#include<iostream>
#include <ctime>
using std::cout; using std::cin; using std::endl;
void draw(int a[]);
void assign(int a[]);
int sizeofarray = 20;
int main() {
int wins[20] = {};
assign(wins);
cout << "compiled!" << endl;
}
void assign(int a[20]) {
a[20] = {};
draw(a);
}
void draw(int a[])
{
srand(time(nullptr));
int rannum = (1 + rand() % 100);
for (int i = 0; i < 20; i++) {
a[i] = 1 + rand() % 100;
}
}
When you get an error with information as helpful as this, you should immediately be thinking "I have a buffer overflow". Then go looking for it.
Sure enough, here it is:
void assign(int a[20]) {
a[20] = {}; // <--- BOOM!
draw(a);
}
Your array can only store 20 elements. When you store something at the 21st element, you have undefined behavior.
Just adding some more information here. It's possible that you thought the offending line would zero-initialize the entire array (like it does when defining the variable). However, outside of an array definition, this is not the case. a[20] = {} is an assignment.
If you wish to zero the array, use std::fill as follows:
std::fill(a, a+20, 0);
I should point out, however, that there's no point zeroing the array in the context of your code as written. It's already zeroed on entry, and the draw function initializes every element anyway.
I am a C++ beginner and my task is as follows:
Define and initialise a single-dimensional integer array. Next, define a pointer that points to the first element in the array and passes the pointer to a function.
Using only pointer variables (and looping constructs), print only the array values that are exact multiples of 7 from start to finish to standard output. The only program output should be the numbers, one per line with no white space.
I have tried:
void print_sevens(int* nums, int length)
{
int array[5] = { 5,8,21,43,70 };
int* ptr = array;
int* num = array;
for (int i = 0; i < length; i++)
{
*num++;
if (num[i] % 7 == 0) {
cout << num[i] << endl;
}
}
}
int main()
{
int array[5] = { 5,8,21,43,70 };
int* ptr = array;
print_sevens(ptr, 5);
}
It compiles but does not output anything.
I am also confused about passing the pointer to a function. Should this be done in the main file or in the function file?
You are creating an additional array in the print_sevens function, which is unnecessary as you already passed the pointer to the first element of the array created in the main()(i.e. array).
Removing that unnecessary array and related codes from the function will make the program run perfectly. (See online)
void print_sevens(int* nums, int length)
{
for (int i = 0; i < length; i++)
{
if (nums[i] % 7 == 0)
std::cout << nums[i] << std::endl;
}
}
and in the main you only need to do the follows, as arrays decay to the pointer pointing to its first element.
int main()
{
int array[5]{ 5,8,21,43,70 };
print_sevens(array, 5);
}
Note that,
num++ increments the pointer, not the underline element it is
pointing to (due to the higher operator precedence of operator++ than operator*). If you meant to increment the element(pointee) you
should have (*num)++.
Secondly, do not practice with using namespace std;. Read more:
Why is "using namespace std;" considered bad practice?
You are modifying the contents of your array when you do *num++.
Why does the value of variable n2 get changed to 0 in the below code after the execution of the statement arr[26]={0}; ,(I realised this while debugging)
while memset(arr,0,sizeof(arr)); works perfectly.
#include<bits/stdc++.h>
using namespace std;
int main()
{
long int n1,n2;
int count=0,flag;
int arr[26] = {0};
cin>>n1>>n2;
string box1[n1];
string box2[n2];
for(int j=0;j<n1;j++)
cin>>box1[j];
for(int j=0;j<n2;j++)
cin>>box2[j];
count=0;
for(int i=0;i<n1;i++)
{
for(int j=0;j<n2;j++)
{
arr[26]={0}; // after the execution of this statement, n2 changes to 0.. WHY???
//memset(arr,0,sizeof(arr)); // If i use memset , things work correctly
cout<<n2<<endl; //n2 becomes zero
for(int k=0;k<box1[i].length();k++)
arr[box1[i][k]-'A']++;
for(int k=0;k<box2[j].length();k++)
arr[box2[j][k]-'A']++;
for(int k=0;k<26;k++)
{
if(arr[k]>=1)
continue;
else
{
flag=1;
break;
}
}
}
}
printf("%d",count);
return 0;
}
Can anyone explain what's wrong with :
arr[26] = {0};
You declare arr as:
int arr[26] = {0};
Which means valid indexes for it are 0-25, making 26 spots total. Then when you write to arr[26], you are actually writing outside of the array, and overwriting memory that your compiler assigned to n2.
If you want to be able to index to 26, you need to declare space for 27 ints:
int arr[27] = {0};
Also the code:
arr[26]={0}; // after the execution of this statement, n2 changes to 0.. WHY???
Only assigns to element 26 in the array. It does not zero out the entire array or anything like that. The way to zero the entire array at runtime is with arr = {0} or using the memset code you already have.
I am practicing pointers by creating a Big Number struct, which has numDigits (number of digits) and digits (contents of the big number).
I create a function called removeZero(). After passing the integer array and the size n into it, because of passing by reference, I am supposed to cut down the leading zeros for my input. It works, when the integer array is in main function. However, when I pass an array that is in readDigits, it does not return with a non-leading-zero version. Why? How to fix it?
struct BigNum{
int numDigits;
int *digits; //the content of the big num
};
int main(){
int A[] = {0,0,0,0,0,0,1,2,3};
int n=9;
int *B=A;
//removeZero(A,n); If I use this, it cannot compile
//error: invalid initialization of non-const reference of type ‘int*&’ from an rvalue of type ‘int*’
removeZero(B,n);
for (int i=0; i<n; i++){
std::cout << *(B+i) << std::endl;
}
BigNum *num = readDigits();
return 0;
}
BigNum* readDigits(){
std::string digits;
std::cout << "Input a big number:" << std::endl;
std::cin >> digits;
//resultPt in heap or in stack?
int *resultPt = new int[digits.length()]; //in heap
int n = digits.length();
toInt(digits,resultPt);
removeZero(resultPt,n);
//Output the leading zeros, why?
for (int i=0; i<n; i++){
std::cout << *(resultPt +i) << std::endl;
}
BigNum *numPtr = new BigNum();
numPtr->numDigits = n;
numPtr->digits = resultPt;
return numPtr;
}
void toInt(std::string& str, int *result){
for (int i=0;i<str.length() ;i++ ){
result[str.length()-i-1] = (int)(str[i]-'0');
}
}
void removeZero(int* &A,int& n){
int i=0;
while (A[i]==0){
i++;
}
A=A+i; //memory leak?
n=n-i;
}
bool areDigits(std::string num){
for(int i=0;i<num.length();i++){
if(num[i]<'0' || num[i] >'9'){
return false;
}
}
return true;
}
Note that an array and a pointer are two different things. When you pass an array to a function, it degrades to a const pointer. This means that you cannot pass an array to a function which expects a int*&.
It could be the problem of scope of numPtr.numPtr is local variable of function readDigits(). Instead of returning pointer. Pass num to readDigits().
The signature of your removeZero function is:
void removeZero(int* &A,int& n);
That means the forst parameter is a reference of a pointer but the pointer is a non-const one, and you cannot therefore pass an array there, as array is a constant pointer (starting address cannot be changed).
In fact you are changing the starting address within removeZero.
With removeZero, the while loop shopuld be changed from:
while (A[i]==0){
to:
while ((A[i]==0) && (i<n)){
You have a logic error in toInt.
void toInt(std::string& str, int *result){
for (int i=0;i<str.length() ;i++ ){
// This stores the digits in the reverse order.
result[str.length()-i-1] = (int)(str[i]-'0');
}
}
That line should be
result[i] = (int)(str[i]-'0');
If you intend to keep the digits in reverse order, then removeZero has to be changed keeping that in mind.
`
When you say
int *B=A;
you are just creating a pointer to point to the same memory
of the Array A. Just by incrementing the pointer(*B) within the function
removeZero
A=A+i;
you are not deleting anything but you are just incrementing the pointer(*B)
to point to subsequent memory location within the array.
The original array memory pointed to by A remains the same, since you
have not changed any contents of the array, but you have just
incremented a pointer pointing to the same memory location as that of the array.
Also there are so many problems, like "Debasish Jana" mentioned,
you have to change your while loop. ""Code-Apprentice" gave you the reason for your
compilation error when you uncomment your commented code.
Also within "removeZero" you are incrementing A by i instead of "1" like
A=A+1;
This is one of the reason for the strange behavior you experience
Even after changing all this, you cannot see your array getting changed,
since you are not modifying any of the contents of your array.
If you really want to delete the contents of the array and change it dynamically,
you have to go for Vector<>. With static memory allocation you cannot cut the
array size short by removing some elements here and there. Learn Vector<>!
I have written this piece of code:
#include <iostream>
using namespace std;
double function(int i)
{
static int Array[5] = {0};
for(int j = i ; j <= i ; j++)
{
Array[j+1] = Array[j]+1;
}
return Array[i+1];
}
int main()
{
for(int i = 0 ; i <= 4 ; i++)
{
cout << function(i) << endl;
}
return 0;
}
Which outputs 1,2,3,4,5
I am wondering why elements of Array at each call of function(i) doesn't become zero despite this piece of code :
static int Array[5] = {0};
The array is static, which means it gets initialized just once (the first time function is called). It keeps its existing items thereafter. If you remove the static keyword you will get 1, 1, 1, 1, 1 instead.
By the way, the for loop inside function is redundant (it's guaranteed to only execute exactly once).
When you use static keyword for declaring a variable inside a function. Then:
The variable is created when the function is called first time.
Thereafter the variable remains alive throughout the lifetime of the program &
The value of the variable persists between function calls.
What you observe is this property of the keyword static at work.
The Array is statics. static variables only initialize once. Therefor, Array becomes zero only on the first call.
if you remove the static keyword it will become zero on every call.
by the way the following code is very strange:
for(int j = i; j <=i ; j++)
because it only runs for j=i. So you can change the whole function by the following:
double function(int i)
{
static int Array[5] = {0};
Array[i+1] = Array[i]+1;
return Array[i+1];
}