Convert integer input to digit using array in C - arrays

#include <stdio.h>
void seperate(int intNum);
int main()
{
int x;
printf("Please enter an integer: \n");
scanf("%d",&x);
seperate(x);
}
void seperate(int intNum)
{
int i,count=0;
while (intNum!=0)
{
intNum/=10;
++count; //to calculate the number of digits for user input = size of array
}
int array[count];
printf("The number on seperate line as follows:\n");
for(i=count-1; i>=0; i--)
{
array[i]= intNum%10;
intNum /= 10;
}
for(i=0; i<=count-1; i++)
{
printf("%d\n", array[i]);
}
}
The expected output(it works when the array size is fixed):
Please enter an integer:
42568
The number on separate line as follows:
4
2
5
6
8
The output:
Please enter an integer:
42568
The number on separate line as follows:
0
0
0
0
0
The code works only if the array sized is fixed, how to solve this problem? Does it not work if I create an array without declaring the size?
EDIT: the value for variable intNum changed in while loop, nothing to do with the declaration of the array

Your while loop, in which you count the number of digits, is changing the given intNum variable, which will be zero at the end of that loop.
You should make a copy of intNum and use/modify that in the first (while) loop, like this:
void seperate(int intNum)
{
int i, count = 0, temp = intNum; // Make a copy to use in the "count" loop
while (temp != 0) {
temp /= 10;
++count; //to calculate the number of digits for user input = size of array
}
if (count == 0) count = 1; // To take care of the case when intNum == 0
int array[count];
printf("The number on seperate line as follows:\n");
for (i = count - 1; i >= 0; i--) {
array[i] = intNum % 10;
intNum /= 10;
}
for (i = 0; i <= count - 1; i++) {
printf("%d\n", array[i]);
}
}
Alternatively, you could save the value of intNum and restore that after the while loop has completed:
void seperate(int intNum)
{
int i, count = 0, save = intNum; // Save the original value of intNum ...
while (intNum != 0) {
intNum /= 10;
++count; //to calculate the number of digits for user input = size of array
}
intNum = save; // ... and restore it after counting the digits
if (!count) count = 1;
int array[count];
//...
EDIT: There is a much simpler and shorter solution, with only one loop, using the sprintf function to get the digits (in the right order) for you:
void seperate(int intNum)
{
char output[100];// Should be long enough for the largest integer.
sprintf(output, "%d", intNum);
printf("The number on seperate line as follows:\n");
for (char* cp = output; *cp; ++cp) {
printf("%c\n", *cp);
}
}

You could simplify this problem with a little math. First,
#include <math.h>
Then, the count of digits can be determined by calculating log10intNum. And you only need a single loop. Something like,
void seperate(int intNum)
{
printf("The number on seperate line as follows:\n");
double log10 = log(10);
while (intNum > 0) {
int count = (int) (log(intNum) / log10);
int pow10 = pow(10, count);
int digit = (int) (intNum / pow10);
printf("%d\n", digit);
intNum -= digit * pow10;
}
}

Related

Why is the code throwing segmentation fault?

The problem is to find the number i<=n, n<=500000 for which the longest collatz series exists.
Collatz series for a number n terminates at 1, and the conditions are
if n is even, next term = n/2
if n is odd, next term = 3*n + 1
Well as a matter of fact, the collatz series always terminates at 1 for all numbers.
Hence any number won't repeat in its collatz series. Using this fact, I have written the following code
LOGIC:
I start a while loop, that goes till n and for each iteration, I store the length of the series for that i.
If i occurs in the series of some n >= r > i, then i terminate the loop and add the length of i to r.
For example, say series of 3 is 3, 10, 5, 16, 8, 4, 2, 1. Now the length corresponding to 2 will already be stored in the series_length array, so I use that value.
Then the for loop next to that, finds the longest series and displays the answer.
The code works fine for n <= 1818 to be precise, but shows segmentation fault onwards (dunno why :(). Please help
CODE :
#include <stdio.h>
int length = 0, series_length[500000], maxlength = 0;
void store_length(int n) {
while(n > 1 && series_length[n] == 0) {
length++;
if(n%2 == 0) {
n = n/2;
}
else {
n = 3*n + 1;
}
}
length += series_length[n];
}
int main() {
int n, i = 1, result;
scanf("%d", &n);
series_length[1] = 1;//redundant statement
while(i <= n) {
store_length(i);
series_length[i] = length;
length = 0;
i++;
}
for(int i = 1;i <= n; i++) {
if(maxlength <= series_length[i]) {
maxlength = series_length[i];
result = i;
}
}
printf("%d %d\n", result, maxlength);
return 0;
}
INPUT-
10
OUTPUT-
9 20 (AS Expected)
INPUT-
100000
OUTPUT-
Segmentation Fault
Expected-
77031 351
Your value for n goes outside the range.
You have a line n = 3*n + 1; in the function store_length
Running this with the gdb with input as 100000 gives
Thread 1 received signal SIGSEGV, Segmentation fault.
0x0000000000401545 in store_length (n=532060) at 29_01.c:6
6 while(n > 1 && series_length[n] == 0) {
(gdb) p n
$1 = 532060
only store it if it fits
... and use it if it already has been computed
avoid global variables
prefer unsigned values
[use descriptive variable names]
#include <stdio.h>
#define THE_SIZE 500000
unsigned series_length[THE_SIZE]= {0,};
unsigned get_length(unsigned val) {
unsigned steps;
for (steps=0; val > 1 ; steps++) {
if (val < THE_SIZE && series_length[val]) { steps += series_length[val]; break; }
if(val %2 ) val = 3*val + 1;
else val /= 2;
}
return steps;
}
int main( int argc, char **argv) {
unsigned top, val , result;
unsigned best,maxlength ;
sscanf(argv[1], "%u", &top);
series_length[1] = 1;//redundant statement
best = maxlength = 0;
for(val=1;val <= top; val++) {
result = get_length(val);
// store it if it fits;
if(val<THE_SIZE) series_length[val] = result;
if (result < maxlength) continue;
best = val; maxlength = result;
}
printf("%u %u\n", best, maxlength);
return 0;
}
Finally, just for fun, make the array smaller
#define THE_SIZE 500
, and the program should give the same result for a given value. (it does)
You get the maximum value 24,648,077,896 with n = 487039.
You must thus use the type long long int for n and you should use an array of 24,648,077,896 integers to avoid a segmentation fault. Unfortunately I never succeeded in allocating a block of 100GB. Your optimization is thus not viable.
Without the array optimization I can scan all 500000 n values in 265ms.
Here is my code:
#include <stdio.h>
int collatz_length(int n) {
int length = 0;
long long int v = (long long int)n;
while (v > 1) {
if ((v&1) == 0)
v = v / 2;
else
v = v*3 + 1;
length++;
}
return length;
}
int main() {
int max_i, max_l = 0;
for (int i = 500000; i > 0; i--) {
int l = collatz_length(i);
if (l > max_l){
max_l = l;
max_i = i;
}
}
printf("i: %d l: %d\n", max_i, max_l);
return 0;
}

C program - How to check array elements [duplicate]

This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 6 years ago.
I have a function repsEqual that takes an array and integer and returns 1 if the array contains only digits of the number in the same order that appear in the same number. Otherwise it returns 0.
int repsEqual(int a[], int len, int n)
If a is {3,2,0,5,3} and n is 32053 return 1 because the array contains only the digits of the number in same order as they are in the number.
If a is {0,3,2,0,5,3} and n is 32053 return 1; we can ignore leading zeros.
I tried like this
int repsEqual(int a[], int len, int n)
{
int len = sizeof(a)/sizeof(a[0]);
//storing elements in array
for(int i=0;i<len;i++)
{
scanf("%d", &a[i]); //eg storing:3 2 0 5 3
}
//asking user integer number and storing in next array
scanf("%d",&a2[num]);//eg 32053
}
Now I need to check if a2 elements are in same order as a1, but do not know how to get started.
This is what you want
int repsEqual(int a[], int len, int n)
{
for (int i = 0; i < len; i++)
{
if (a[len - i - 1] == n % 10)
n /= 10;
else
return 0;
}
//For cases where your number-length is longer than your array length
if (n != 0) return 0;
return 1;
}
First you have your array, say like a[5] = { 5, 2, 3, 1, 4}
Basically what i do is looping the array from end to start, thats a[len - i - 1]
Then i check it with the last character of n thats n%10
So example with n = 52314, the first if statement check if (52314 % 10) which is 4 equal with a[4] which is also 4
if the 2 character match then the loop continue first by remove the last character of n: 52314 / 10 = 5231.
And the next loop will check for 5231 % 10 and a[3]
else the loop break mid-way and return 0 indicate that a mis-match is found
finally after all the character in array is checked and no mismatch is found, it will return 1, as the pattern match
Note: a function should only does what its name says
In your case, check if an array and an integer have the same pattern
User input should be put outside somewhere else, after you have the inputs (the array, the len, and n) you then pass-in to repsEqual for checking
Try matching the number (n) backwards against the array 'a'. To do this you'll want to modulus the smallest digit from 'n', by getting the remainder from dividing by 10. Then remove the smallest digit from 'n' by dividing by 10.
int repsEqual(int a[], int len, int n)
{
int i;
int temp;
if (0 == len || NULL == a)
return 0; // no array, or elements, doesn't match a real number (n).
temp = n;
for (i = len - 1; i >= 0; --i)
{
if (a[i] != (temp % 10))
return 0; // remainder mismatch against array element.
temp = temp / 10; // removes the smallest digit.
}
return 1;
}
By modulus 10 on your n you get the remainder of dividing by 10. IE 452 % 10 = 2. Then by dividing be ten we remove the smallest digit IE 452 / 10 = 45.
This seems to be some homework, haha. Anyway I gave u a quick/ugly sample to start with.
#include <stdio.h>
int repsEqual(int a[],int len , int n)
{
char str[100];
sprintf(str, "%d", n);
int i;
int nonzeroIndex;
for(i=0; i<len; i++){
if (a[i] != 0)
break;
}
nonzeroIndex = i;
printf("nonzeroIndex is %d\n", nonzeroIndex);
for(i= nonzeroIndex; i <len; i++){
if (a[i] != str[i - nonzeroIndex] - 48) {
printf("diff at %d\n", i);
return 0;
}
}
return 1;
}
int main()
{
int a[5];
a[0] = 0;
a[1] = 2;
a[2] = 0;
a[3] = 5;
a[4] = 3;
int output = repsEqual(a, 5, 2053);
printf("result: %d\n", output);
}

C program to print numbers between 100 and 1000 which sum of digit is 20

I am writing a C program which should display me all numbers between 100 and 1000 which sum of digit is 20. I tried this code down here, but it just displays 0 as an ouput when I compile it, can you help me? I also tried moving if(iVsota==20) outside of the while loop. I am using Orwell Dev C++ IDE.
#include <stdio.h>
int main (void)
{
int iVnos=0;
int iOstanek=0;
int iVsota=1;
int iStevec1=100;
for(iStevec1=100; iStevec1<1000; iStevec1++)
{
while(iStevec1>0)
{
iOstanek=iStevec1%100;
iStevec1=iStevec1/10;
iVsota=iOstanek+iVsota;
if(iVsota==20)
{
printf("%i\n", iStevec1);
}
}
}
return(0);
I hope this is better.
Your loop should look like :
for(iStevec1=100; iStevec1<1000; iStevec1++)
{
int c2 = iStevec1/100; // extract third digit
int c1 = (iStevec1%100)/10; // extract second digit
int c0 = (iStevec1%10); // extract first digit
if((c0+c1+c2)==20) // sum and verify
{
printf("%i\n", iStevec1);
}
}
This should work for you:
(Changed the variable names so it's more readable)
#include <stdio.h>
int add_digits(int n) {
static int sum = 0;
if (n == 0)
return 0;
sum = n%10 + add_digits(n/10);
return sum;
}
int main() {
int start, end;
start = 100, end = 1000;
for(start = 100; start <= end; start++) {
if(add_digits(start) == 20)
printf("Number: %d\n", start);
}
return 0;
}
EDIT:
(Your code fixed with comments as explanation)
#include <stdio.h>
int main() {
int iVnos=0;
int iOstanek=0;
int iVsota=0;
int iStevec1=100;
int temp; //temp needed
for(iStevec1=100; iStevec1<=1000; iStevec1++)
{
temp =iStevec1; //assign number to temp
iVsota=0; //set sum every iteration to 0
while(temp>0)
{
iOstanek=temp%10; //You need only % 10 to get the last digit of a number
temp = temp / 10; //'delete' last digit of the number
iVsota+=iOstanek; //add digit to sum
}
if(iVsota==20) //You only need to check the digits after sum is calculated
printf("Number %d\n", iStevec1);
}
return 0;
}
Here's a more generalised method to get the sum of all individual numbers in an integer (assumes positive integers):
int getSumOfDigits(int x)
{
int sum = 0;
while (x > 0)
{
sum += x % 10;
x = x / 10;
}
return sum;
}
int main()
{
for (int i = 100; i <= 1000; i++)
{
if (getSumOfDigits(i) == 20)
{
printf("%d\n", x);
}
}
}
The expression x % 10 is the last digit in the integer. Hence, that's what we add. Then we chop off the last digit in the integer by dividing it by 10. Repeat until we hit zero.
Alternative method, taking advantage of the specifics.
#include <stdio.h>
int main()
{
int c0, c1, c2; /* 3 digits sum to 20 */
for(c0 = 2; c0 < 10; c0++){
c1 = 11 - c0;
c2 = 9;
while(c1 < 10){
printf("%d%d%d\n", c0, c1, c2);
/* or printf("%3d\n", (c0*10+c1)*10+c2); */
c1++;
c2--;
}
}
return(0);
}
Just change 1 thing and you will get what you want
int main (void)
{
int iVnos=0;
int iOstanek=0;
int iVsota=1;
int iStevec1=100;
int temp;
for(iStevec1=100; iStevec1<1000; iStevec1++)
{
temp = iStevec1;
while(temp>0)
{
iOstanek=temp%100;
temp=temp/10;
iVsota=iOstanek+iVsota;
if(iVsota==20)
{
printf("%i\n", iStevec1);
}
}
}
return(0);
}
Enjoy Coding Enjoy Life...

Segmentation fault when initializing memory for pointer to array passed to a function

I am writing a function that creates a set of primes numbers less than the limit passed to it. For some reason, I am having trouble getting the memory-management right; I keep getting "Segmentation Fault: 11." Here is the code:
#include <stdio.h>
#include <stdlib.h>
void getPrimes(int** primes, int* limit);
int main(void){
int primeLimit = 99;
int* primes;
getPrimes(&primes, &primeLimit);
//Do stuff
free(primes);
return 0;
}
void getPrimes(int** primes, int* limit){
int multiplier; //Number used to multiply by to find numbers that do have factors
int multiple; //Stores the current multiple
int numPrimes = 0; //Number of primes (returned to caller)
int count = 0;
int* marked = (int*)malloc(*limit * sizeof(int)); //Initialize memory and sets it to 0
memset(marked, 0, *limit);
marked[0] = 1; //Set 0 and 1 to be not prime
marked[1] = 1;
for(int base = 2; base < *limit; base++){//Go through each number and mark all its multiples, start with 2
if(!marked[base]){ //If base is already marked, its multiples are marked
multiplier = 2; //Start multiple at 2
multiple = base * multiplier; //Set first multiple for loop
while(multiple < *limit){//Mark each multiple until limit reached
marked[multiple] = 1;
multiplier++;
multiple = base * multiplier;
}
}
}
//Do a sweep to get the number of primes
for(int num = 2; num < *limit; num++){//Go through each number and check if marked
if(!marked[num]){ //Number is prime
numPrimes++; //Increase count of primes if number is prime
}
}
*limit = numPrimes; //update limit to the number of primes
*primes = (int*)malloc(numPrimes * sizeof(int)); //Allocate memory for primes
//Now actually put the primes in the array
printf("Number of Primes: %d\n\n", numPrimes);
for(int num = 2; num < *limit; num++){//Go through each number and check if marked
printf("Num: %d, ", num); //Print it for debugging
printf("Count: %d\n", count);
if(!marked[num]){ //Number is prime
*primes[count] = num; //Append to primes list (returned to caller)
count++; //Increase count of primes if number is prime
}
}
free(marked); //Free the memory used to mark multiples
return;
}
The origin of your problem is :
*primes[count] = num;
It makes an attempt to reach primes[count] and it fails as soon as count>0.
To correct this :
(*primes)[count] = num;
There are some other points to get a correct result :
To initialize marker, do memset(marked, 0, *limit*sizeof(int));. The function memset() comes from string.h : it sets the first *limit*sizeof(int) bytes
In the second loop, for(int num = 2; num < *limit; num++){, *limit has changed, it is not the length of marked anymore. To remove this issue the initial value of *limit may be stored in formerlimit.
Here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getPrimes(int** primes, int* limit);
int main(void){
int primeLimit = 99;
int* primes;
getPrimes(&primes, &primeLimit);
//Do stuff
free(primes);
return 0;
}
void getPrimes(int** primes, int* limit){
int multiplier; //Number used to multiply by to find numbers that do have factors
int multiple; //Stores the current multiple
int numPrimes = 0; //Number of primes (returned to caller)
int count = 0;
int formerlimit=*limit;
int* marked = (int*)malloc(*limit * sizeof(int)); //Initialize memory and sets it to 0
memset(marked, 0, *limit);
marked[0] = 1; //Set 0 and 1 to be not prime
marked[1] = 1;
for(int base = 2; base < *limit; base++){//Go through each number and mark all its multiples, start with 2
if(!marked[base]){ //If base is already marked, its multiples are marked
multiplier = 2; //Start multiple at 2
multiple = base * multiplier; //Set first multiple for loop
while(multiple < *limit){//Mark each multiple until limit reached
marked[multiple] = 1;
multiplier++;
multiple = base * multiplier;
}
}
}
//Do a sweep to get the number of primes
for(int num = 2; num < *limit; num++){//Go through each number and check if marked
if(!marked[num]){ //Number is prime
numPrimes++; //Increase count of primes if number is prime
}
}
*limit = numPrimes; //update limit to the number of primes
*primes = (int*)malloc(numPrimes * sizeof(int)); //Allocate memory for primes
//Now actually put the primes in the array
printf("Number of Primes: %d\n\n", numPrimes);
for(int num = 2; num < formerlimit; num++){//Go through each number and check if marked
printf("Num: %d, ", num); //Print it for debugging
printf("Count: %d\n", count);
if(!marked[num]){ //Number is prime
(*primes)[count] = num; //Append to primes list (returned to caller)
count++; //Increase count of primes if number is prime
}
}
free(marked); //Free the memory used to mark multiples
return;
}
multiplier is not necessary, it may be changed for multiple+=base;
If it fails on high numbers, think about overflows.

convert an integer number into an array

I am trying to convert an integer number in C into an array containing each of that number's digits
i.e. if I have
int number = 5400
how can I get to
int numberArray[4]
where
numberArray[0] = 0;
numberArray[1] = 0;
numberArray[2] = 4;
numberArray[3] = 5;
Any suggestions gratefully received.
This would work for numbers >= 0
#include <math.h>
char * convertNumberIntoArray(unsigned int number) {
int length = (int)floor(log10((float)number)) + 1;
char * arr = new char[length];
int i = 0;
do {
arr[i] = number % 10;
number /= 10;
i++;
} while (number != 0);
return arr;
}
EDIT: Just a little bit more C style but more cryptic.
#include <math.h>
char * convertNumberIntoArray(unsigned int number) {
unsigned int length = (int)(log10((float)number)) + 1;
char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
do {
*curr++ = number % 10;
number /= 10;
} while (number != 0);
return arr;
}
Hint: Take a look at this earlier question "Sum of digits in C#". It explains how to extract the digits in the number using several methods, some relevant in C.
From Greg Hewgill's answer:
/* count number of digits */
int c = 0; /* digit position */
int n = number;
while (n != 0)
{
n /= 10;
c++;
}
int numberArray[c];
c = 0;
n = number;
/* extract each digit */
while (n != 0)
{
numberArray[c] = n % 10;
n /= 10;
c++;
}
You could calculate the number of digits in an integer with logarithm rather than a loop. Thus,
int * toArray(int number)
{
int n = log10(number) + 1;
int i;
int *numberArray = calloc(n, sizeof(int));
for ( i = 0; i < n; ++i, number /= 10 )
{
numberArray[i] = number % 10;
}
return numberArray;
}
Try this,
void initialise_array(int *a, int size, int num) {
for (int i = 0; i < size; ++i, num /= 10)
a[(size - 1) - i] = num % 10;
}
If you need to take negative numbers into account, you might need some extra logic. In fact, when playing around with arrays you don't know the size of upfront, you may want to do some more safety checking, and adding an API for handling the structure of the data is quite handy too.
// returns the number of digits converted
// stores the digits in reverse order (smalles digit first)
// precondition: outputdigits is big enough to store all digits.
//
int convert( int number, int* outputdigits, int* signdigit ) {
int* workingdigits = outputdigits;
int sign = 1;
if( number < 0 ) { *signdigit = -1; number *= -1; }
++workingdigits;
for ( ; number > 0; ++ workingdigits ) {
*workingdigits = number % 10;
number = number / 10;
}
return workingdigits - outputdigits;
}
void printdigits( int* digits, int size, int signdigit ) {
if( signdigit < 0 ) printf( "-" );
for( int* digit = digits+size-1; digit >= digits; --digit ){
printf( "%d", *digit );
}
}
int main() {
int digits[10];
int signdigit;
printdigits( digits, convert( 10, digits, &signdigit ), signdigit );
printdigits( digits, convert( -10, digits, &signdigit ), signdigit );
printdigits( digits, convert( 1005, digits, &signdigit ), signdigit );
}
#include <stdio.h>
#include <string.h>
int main(void)
{
int i, inputNumber;
char* charArray;
printf("\nEnter number: ");
scanf("%d", &inputNumber);
/* converts int to print buffer which is char array */
sprintf(charArray, "%d", inputNumber);
int size = strlen(charArray);
int intArray[size];
for (i = 0; i < size; i++)
{
intArray[i] = charArray[i] - '0';
}
return 0;
}
C code:
/* one decimal digit takes a few more than 3 bits. (2^3=8, 2^4=16) */
int digits[(sizeof (int) * CHAR_BIT) / 3 + 1],
*digitsp = digits;
do {
*digitsp++ = number % 10;
number /= 10;
} while(number > 0);
You will see how many digits you converted by taking the difference
digitsp - digits
If you want to put it into a function:
#define MIN_DIGITS_IN_INT ((sizeof (int) * CHAR_BIT) / 3 + 1)
int to_array(int number, int *digits) {
int *digitsp = digits;
do {
*digitsp++ = number % 10;
number /= 10;
} while(number > 0);
return digitsp - digits;
}
int main() {
int number = rand();
int digits[MIN_DIGITS_IN_INT];
int n = to_array(number, digits);
/* test whether we're right */
while(n-- > 0)
printf("%d", digits[n]);
}
printf(" = %d\n", number);
}
I prefer automatic arrays to dynamic memory allocation in this case, since it's easier to do it right and not leak accidentally.
using vadim's code, I came up with this test program:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char * convertNumberIntoArray(unsigned int number) {
unsigned int length = (int)(log10((float)number)) + 1;
char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
do {
*curr++ = number % 10;
number /= 10;
} while (number != 0);
return arr;
}
int main(void)
{
int InputNumber;
int arr[5];
printf("enter number: \n");
scanf("%d", &InputNumber);
convertNumberIntoArray(InputNumber);
printf("The number components are: %d %d %d\n", arr[0],arr[1],arr[2]);
system("PAUSE");
return 0;
}
but the output is garbage. Can anyone advise if I have done something stupid here?
/***** output *****/
enter number:
501
The number components are: 2009291924 2009145456 -1
Press any key to continue . . .
--dave

Resources