This is a c++ program to convert decimal number to binary number. Well there are many possible ways to implement this but as I learned about the static variable I thought to make a use of it. So the program is
#include <iostream>
using namespace std;
int **binary(int num, int &k) {
static int *p;
int i = 0;
while (num > 0) {
*p = num % 2;
p++;
num = num / 2;
k++;
}
return &p;
}
int main() {
int n;
int k = 0;
cout << "\n Enter the number to be converted into binary : ";
cin >> n;
int **ptr;
ptr = binary(n, k);
cout << "\n The number of bytes in the binary number is : " << k << endl;
cout << "\n The binary code is : \n";
for (int i = 0; i < k; i++)
cout << **(ptr+i);
return 0;
}
Output:
Enter the number to be converted into binary : 33
Segmentation fault
After debugging this code I'm getting seg fault at line 9:9
i.e
*p = num % 2;
I don't know why this is leading me to access an unoccupied memory space in the stack.
The reason there is a crash is that p is initialized to nullptr. Dereferencing an uninitialized variable is undefined behavior, hence you get the crash.
Disclaimer: The following code is intended to fix your code. It is not intended to illustrate a proper way of doing this, or show a good way to code in general.
If you wish to play with function-static variables, and your function must return a pointer to pointer, initialize p by pointing it to another static variable which provides you with a buffer:
static int pVal[100];
static int * p;
p = pVal; // This should be done in an assignment, not in initializer
Note: Returning pointers to static storage makes your code non-reentrant, which is generally a very bad practice. This code is fine as a learning exercise, but it's not something one should use in production code.
static int * p; is never set. It is initialized to NULL, dereferencing it invokes undefined behavior. Using a static buffer is not recommended, it is better to pass an array to the function and return the number of bits. Furthermore, you should output these bits in the reverse order.
Since you are interested in static local variables, here is a corrected version of your code:
#include <iostream>
using namespace std;
int *binary(int num, int &k) {
static int bits[sizeof(int) * 8];
int *p = bits;
k = 0;
while (num > 0) {
*p = num % 2;
p++;
num = num / 2;
k++;
}
return p;
}
int main() {
int n;
int k = 0;
cout << "\n Enter the number to be converted into binary : ";
cin >> n;
int *ptr = binary(n, k);
cout << "\n The number of bits in the binary number is : " << k << endl;
cout << "\n The binary code is : \n";
for (int i = 0; i < k; i++)
cout << ptr[k - i];
return 0;
}
Here is a version that does not use a static buffer:
#include <iostream>
using namespace std;
int binary(unsigned int num, int *dest) {
for (int i = 0;;) {
dest[i++] = num & 1;
if ((num >>= 1) == 0)
return i;
}
}
int main() {
unsigned n;
int bits[sizeof(n) * 8];
cout << "\nEnter the number to be converted into binary: ";
cin >> n;
int k = binary(n, bits);
cout << "\nThe number of bits in the binary number is: " << k << endl;
cout << "\nThe binary code is: ";
for (int i = k; i-- > 0;)
cout << bits[i];
cout << endl;
return 0;
}
The code has numerous problems:
binary() does not initialise the pointer p to anything.
binary() dereferences the initialised p and modifies the value.
The conversion writes from LSB to MSB and the outputs writes in that order too.
You need to allocate a buffer to receive the conversion. This is safest done by the caller. Since ultimately you output the characters 1 or 0, your conversion may as well write those character values directly to a string.
Related
The strange problem appears in my program. It is working, but in debugging it shows the "Exception thrown" in random places at the outputting
cout<<"Average value:"<<u3.apr();
_getch();
Sometimes, it even throws this error after the main function (Behind the {})
It is quite annoying because the program just closes after 3 seconds because of these errors.
(Maybe that's because of class, but I'm trying to learn it ;) )
Have tried already changing lines order, rewriting class name and array name.
#include <iostream>
#include <conio.h>
using namespace std;
class vid
{
private:
int i, j;
double rez, sum=0;
public:
int size;
double *arr = new double[size];
double apr()
{
for (i = 0; i < size; i++)
{
sum += (*(arr + i));
}
return sum / size;
}
};
int main()
{
vid u3;
cout << "Enter array length:";
cin >> u3.size;
for (int i = 0; i < u3.size; i++)
{
cout << "Enter array's " << i << " element:" << endl;
cin >> *(u3.arr+i);
}
cout << "Your array:" << endl;
for (int i = 0; i < u3.size; i++)
{
cout << *(u3.arr + i) << "\t";
}
cout << endl;
cout<<"Average value:"<<u3.apr();
_getch();
}
Thanks for any help ;)
arr is initialised when u3 is constructed.
But you didn't populate u3.size until later.
So, your array has indeterminate length (which is already UB), and your accesses later may be invalid.
You're going to have to manage your class's member a bit more cleverly!
Such classes generally have a "resize" function that performs the allocation per the requested size. Don't forget to safely kill any prior allocation, transplanting data if necessary. You can find online plenty of examples of a vector implementation.
Certainly renaming classes and randomly re-ordering the lines of your program's source code is not going to solve anything.
u3.size is not set until after u3 is constructed. By setting u3.size you can avoid this compiler-time error.
It seems that as an alternative solution, you might want to consider how to get rid of the new call and the need to write a destructor that will delete arr.
By creating a constructor that takes a size parameter AND by switching arr to a std::vector, you can allow the class to hold the vector and handle memory allocation and deallocation:
#include <iostream>
#include <vector>
using namespace std;
class vid
{
private:
int i, j;
double rez, sum=0;
public:
int size;
std::vector<double> arr;
// constructor requires size to be passed in;
// constructor initializes the arr array with the passed in size to zeroes.
vid(int argSize) : size(argSize), arr(argSize, 0.0){ }
double apr()
{
for (i = 0; i < size; i++)
{
sum += arr[i];
}
return sum / size;
}
};
int main()
{
uint size;
cout << "Enter array length:";
cin >> size;
vid u3(size);
for (int i = 0; i < u3.size; i++)
{
cout << "Enter array's #" << i << " element:" << endl;
cin >> u3.arr[i];
}
cout << "Your array:" << endl;
for (int i = 0; i < u3.size; i++)
{
cout << u3.arr[i] << "\t";
}
cout << endl;
cout<<"Average value:"<<u3.apr();
char ch;
cin >> ch;
}
I have this code which intends to explain how "for loops" work.
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Input a positive integer: ";
cin >> n;
int factorial = 1;
for (int i = 1; i <= n; ++i)
factorial *= i;
cout << "factorial(" << n << ") is << factorial << "\n ";
return (0);
}
What does the line int factorial =1 do? Why is it needed?
int factorial = 1;
defines a variable with the identifier factorial and the type int. It is intended to hold the temporary results of the factorial calculation throughout all iterations of the for-loop and to hold the final result.
It is explicitly initialized with 1 because
It has to be initialized somehow; otherwise, undefined behavior will be the result as an uninitialized memory location will be accessed.
0 would be bad because 0 * x = 0 for all real numbers while 1 * x = x for all real numbers.
So I have written a function that should simply add the values of each element stored in two separate arrays, and save them to a third array.
I don't understand what the issue is, I am simply adding together the value of the int stored at the location referenced by each of my pointers, and saving it to my third, empty, array.
My code compiles just fine, but when I loop to print the contents of my third array (which should contain the sum of the two previous arrays elements at their respective indexes) it just prints a bunch of memory addresses. What gives?
EDIT: I fixed my while loop to perform the arithmetic, and everything is working well. My working code is below. Hope it helps someone else.
#include<iostream>
#include<stdlib.h>
using namespace std;
void arrayAdd(int firstArray[], int secondArray[], int targetArray[], int size){
int *firstPtr = firstArray;
int *secondPtr = secondArray;
int *tragetPtr = targetArray;
while (firstPtr <= &firstArray[size - 1] ){
//add the first two array elements
*tragetPtr = (*firstPtr + *secondPtr);
// point to the next location
*firstPtr++;
*secondPtr++;
*tragetPtr++;
}
}
int main() {
int totalElements;
const size_t ARRAY_SIZE = 50;
int firstIntegerArray[ARRAY_SIZE];
int secondIntegerArray[ARRAY_SIZE];
int thirdIntegerArray[ARRAY_SIZE];
cout << "Please enter the total number of elements for your array: ";
cin >> totalElements;
for(int i = 0; i < totalElements; i++){
cout << "Please enter a value for the first array at index " << i << ": ";
cin >> firstIntegerArray[i];
}
for(int i = 0; i < totalElements; i++){
cout << "Please enter a value for the second array at index " << i << ": ";
cin >> secondIntegerArray[i];
}
//run our arrayAdd function
arrayAdd(firstIntegerArray, secondIntegerArray, thirdIntegerArray, totalElements);
cout << "The conents of your two arrays added together is; " << endl;
for(int i = 0; i < totalElements; i++){
cout << thirdIntegerArray[i] << ", ";
}
return 0;
}
A local array decays to a pointer when it is passed to a function, so you can't use sizeof on it anymore. Indeed this:
void arrayAdd(int firstArray[]) {
int *firstPtr = firstArray;
std::cout << "sizeof(firstArray) == " << sizeof(firstArray) << std::endl;
std::cout << "sizeof(firstPtr) == " << sizeof(firstPtr) << std::endl;
}
int main() {
int test[] = {1,2,3,4,5,6,7,8,9,0};
arrayAdd(test);
return 0;
}
Prints:
sizeof(firstArray) == 8
sizeof(firstPtr) == 8
on my 64 bit machine.
Casting int[] to int* doesn't change anything since it already became a pointer as an argument. You should pass the size of the array to the method or, since you are working with C++, use an std::array or std::vector which will just solve any problem.
I was trying to write a program in which I take an input number,
example 891 and input each of these number in an array for example
x[0] = 8, x[1] = 9 and x[2] = 1
I was trying to use recursion to implement my method:
void calc(int val, int k)
{
static int number = val;
if((val/10))
{
calc(val/10, k--);
}
int x = number - val*pow(10, k);
cout << x << ", k = " << k << " and number = " << number << endl;
}
int main()
{
//write a program that converts a number to string
int number;
cout << "Enter a number: ";
cin >> number;
number = 891;
int k = 0;
//while(number/10 != 0)
k = 2;
calc(number, k);
}
Basically I'm trying to use my recursive function to try to break the
number down in its finer parts, however I get an output of (in val):
91, 1, -8019. Is there a way I can improve on this, but maintaining
the structure?
Both putting your data into an array and solving this problem recursively requires a bit of pointer arithmetic.
You'll need to allocate your array ahead of time, which means you need to know the number of digits. You'll also need to pass around the pointer to the array so that recursive calls can assign to it.
Below is a shortish solution that fits both of these requirements.
#import <math.h>
#import <iostream>
using namespace std;
void calc(int num, int* digs) {
if (num > 0) {
calc(num/10, digs-1); //recursive call, doing head recursion
*digs = num %10; //assigning this digit
}
}
int main() {
//Get number from user
int inputNumber;
cout << "Input a number: ";
cin >> inputNumber;
int numDigits = log10(inputNumber) + 1;
int outputArray[numDigits];
//I give a pointer to the end of the array
//This is because we are receiving digits from the end
//So we traverse backwards from the end of the array
calc(inputNumber, outputArray+numDigits-1);
//Following is not logic, just printing
for (int i=0; i < numDigits; i++) {
cout << outputArray[i] << " ";
}
cout << endl;
}
void calc(int val)
{
cout << "digit:"<<val % 10<< " and number = " << val << endl;
if((val/10))
{
calc(val/10);
}
}
This will print out each digit (which looks like what you are trying to do in the function).
I designed a C++ code for checking machine's endian.
It works well. But, it cannot print out each bytes' contents in a 4-byte int.
#include<iostream>
using namespace std;
bool f()
{
int a = 1;
char *p = (char*)&a;
for (int i = 0 ; i < 4 ; ++i)
cout << "p[" << i << "] is " << hex << *p++ << " ";
cout << endl ;
p -= 4;
if (*p == 1) return true ; // it is little endian
else return false; // it is big endian
}
int main()
{
cout << "it is little endian ? " << f() << endl ;
return 0 ;
}
output:
p[0] is p[1] is p[2] is p[3] is
it is little endian ? 1
Why the output is empty ?
thanks
the issue is that the type of *p is char, so the stream attempts to print the value of it as an ASCII character (which is likely not the value of a visible character). If you cast it to an int you will get what you expect:
cout << "p[" << i << "] is " << hex << static_cast<int>(*p++) << " ";
printf suggested is OK but also an alternative is using shift operators <<,>> to investigate individual bytes of the int.
I coded the following to print every byte of an int array. Each int was 4 bytes long.
Hope this helps in some way.
#include <iostream>
#include<math.h>
#include<string.h>
using namespace std;
int main()
{
int length = 5;
unsigned int* array = new unsigned int[length];
for(int i=0; i<length; i++)
array[i] = 16843009;
for(int i=0;i<=4;i++)
{
int new_dividend=0,k=0,l=0;
double bytevalue=0;
int bits[32];
int number=array[i];
//Initializing
for(int c=0;c<=31;c++)
{
bits[c]=0;
}
//convert to binary
while(number!=1)
{
new_dividend=number/2;
bits[k]=number%2;
number=new_dividend;
k++;
}
bits[k]=1;
//Pad with zero if needed
if(k!=31)
{
for(int ctr=k+1;ctr<=31;ctr++)
{
bits[ctr]=0;
}
}
for(int counter=0;counter<=31;counter++)
{
//Print value of each byte.Also Reset values after each bytevalue has been printed.
if(l==8)
{
l=0;
cout<<bytevalue;
bytevalue=0;
}
//calculate value of each byte
bytevalue=bytevalue+(pow(double(2),l))*bits[counter];
++l;
}
if(l==8)
{cout<<bytevalue;
}
}
delete[] array;
return 0;
}
Expected Output = 11111111111111111111 for an array[i] = 16843009 where i may be any range.