a function that works with array elements - c

I need to write a function that subtracts digits.
If user inputs 2345, the output should be 111 (5-4, 4-3, 3-2); another example would be 683, where the output should be 25 (3-8(abs value is taken), 8-6).
I have wrote the following code which works only when the size of the array is declared.
int subtraction(int arr[], int size) {
int sub = 0;
for (int i = 0; i < size-1; i++) {
sub = sub * 10 + abs(arr[i] - arr[i+1]);
}
return sub;
}
However, the number that the user inputs is random and can have various digits, so I don't know what limit to put in the for loop.
For example:
int arr[] = {1, 2, 55, 56, 65, 135}, i;
subtraction(arr, 6);
for (i=0; i<6; i++)
printf("%d ", arr[i]);
expected output: 0 0 0 1 1 22
The function is supposed to subtract the second-to-last digit from the last one, by the way , / from right to left / from a random number that the user inputs ; for example if the input is 5789, the output is supposed to be 211 (9-8, 8-7, 7-5); if user inputs a negative number, the program should take it's absolute value and then do the subtracting. If user input is a one digit number the result should be 0.
The function I wrote only works when the size of the array is declared. I don't know how to make it work when the size is undeclared (pointers and malloc are required I believe, as that's what I managed to find out by googling for ages, but unfortunately, I don't know how to do it).
please help?

You are not actually changing any values, here is the line you need to look at.
sub = sub * 10 + abs(arr[i] - arr[i+1]);
As you are printing the array you actually need to store the calculated value in the array again.

#include <stdio.h>
#include <stdlib.h>
int subtract(int n)
{
int factor = 1;
int total = 0;
int lastPlace = n%10;
n /= 10;
while (n>0)
{
total += (factor * abs((n%10) - lastPlace));
factor *= 10;
lastPlace = n%10;
n /= 10;
}
return total;
}
void subtractArray(int* arr, unsigned int size)
{
for (int i=0; i<size; ++i)
{
if (arr[i] < 0)
arr[i] = abs(arr[i]);
arr[i] = subtract(arr[i]);
}
}
int main()
{
int arr[] = {1, 2, 55, 56, 65, 135};
int size = sizeof(arr)/ sizeof(arr[0]);
subtractArray(arr, size);
for (int i=0; i<size; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}

Here is a simple code that solve your problem :)
#include <stdio.h>
#include <stdlib.h>
int *subtraction(int arr[], int size)
{
int *sub = calloc(sizeof(int*) , size), i = 0, rev; //allocating memory
for (i = 0; i < size; i++)
{
rev = 0;
arr[i] = abs(arr[i]);
for (int a = 0; arr[i] != 0; arr[i] /= 10)
rev = (rev * 10) + (arr[i] % 10);
for (i; (rev / 10) != 0; rev /= 10) //the loop ends when rev = 0
sub[i] = ((sub[i] * 10) + abs( (rev % 10) - ((rev / 10) % 10) )); //easy math => for example rev = 21 > sub[i] = (0 * 10) + ( (21 % 10) - ((21 / 10) %10)) = abs(1 - 2) = 1;
}
return sub;
}
int main()
{
int arr[] = {-9533, 7, -19173}, i;
int len = sizeof(arr)/sizeof(arr[0]); //size of arr
int *sub = subtraction(arr, len);
for(int i = 0; i < len; i++) //for test
printf("%d ", sub[i]);
return 0;
}
output for {1, 2, 55, 56, 65, 135}:
0 0 0 1 1 22
output for {987654321, 123456789, 111111111} :
11111111 11111111 0
output for {38279}:
5652
output for {-9533, 7, -19173}:
420 0 8864

Well as for the array of undefined size. What you probably want is a dynamically allocated array.
Here we get the number of array elements based on user input, within limits, of course.
first we're gonna get the number from the user using fgets() which will give us a string, then we'll use strtol() to convert the number part to scalar (int). you can use scanf("%d", &n) if you want.
Then we can count the digits from that number, and that value will be the number of elements of our array.
#include <stdio.h>
#include <stdlib.h> //for strtol(), malloc() and NULL guaranteed
//you may also want to add
#include <limits.h>
#include <errno.h>
#define MAX_STRLEN 12 // can hold all digits of INT_MAX plus '\0' and a posible, AND very likely, '\n'
#define DEC 10 // for strtol base argument
/*
* I'm lending you my old get_n_dits() function that I used to count decimal digits.
*/
int get_n_dits(int dnum) {
unsigned char stop_flag = 0; //we'll use to signal we're done with the loop.
int num_dits = 1, dpos_mult = 1; //num_dits start initialized as 1, cause we're pretty sure that we're getting a number with at least one digit
//dpos_mult stands for digital position multiplier.
int check_zresult; //we'll check if integer division yields zero.
/**
* Here we'll iterate everytime (dnum / dpost_mult) results in a non-zero value, we don't care for the remainder though, at least for this use.
* every iteration elevates dpost_mult to the next power of ten and every iteration yielding a non-zero result increments n_dits, once we get
* the zero result, we increment stop_flag, thus the loop condition is no longer true and we break from the loop.
*/
while(!stop_flag) {
dpos_mult *= 10;
check_zresult = dnum / dpos_mult;
(check_zresult) ? num_dits++ : stop_flag++;
}
return num_dits;
}
int main(void) {
int num, ndits; //we'll still using int as per your code. you can check against INT_MAX if you want (defined in limits.h)
int *num_array = NULL; //let's not unintentionally play with an unitialized pointer.
char *num_str = malloc(MAX_STRLEN); //or malloc(sizeof(char) * MAX_STRLEN); if there's any indication that (sizeof(char) != 1)
printf("please enter a number... please be reasonable... or ELSE!\n");
printf(">>> ");
if(!fgets(num_str, MAX_STRLEN, stdin)) {
fprintf(stderr, "Error while reading from STDIN stream.\n");
return -1;
}
num = (int)strtol(num_str, NULL, DEC); //convert the string from user input to scalar.
if(!num) {
fprintf(stderr, "Error: no number found on input.\n");
return -1;
}
ndits = get_n_dits(num);
if(ndits <= 0) {
fprintf(stderr, "Aw, crap!\n");
return -1;
}
printf("number of digits: %d\n", ndits);
num_array = malloc(sizeof(int) * ndits); //now we have our dynamically allocated array.
return 0;
}

Related

How do I save the return array from a function?

I'm currently learning c (just starting), and I'm trying to create a program that finds all the integers with 10 digits, with the conditions:
the first digit can be divided by 1;
the number represented by the first two digits can be divided by 2;
etc.
For example, the number 1295073846 doesn't make the cut, because 1295 is not divisible by 4 (but 1 is divisible by 1, 12 by 2, and 129 by 3).
I understand how this can be done, but I'm still struggling to manipulate arrays and pointers. Here is my code (only numToArr and the beginning of findn() should be relevant):
int numToArr(long num) { // splits a given number into an array of 10 digits
int arr[10];
int i = 9;
do {
arr[i] = num % 10;
num /= 10;
i--;
} while (num != 0);
printf("%d%d%d\n", arr[0], arr[1], arr[2]);
return *arr;
}
int join(char s[3], int n1, int n2) { // so I can get the combination of digits
snprintf(s, 3, "%d%d", n1, n2);
int n12 = atoi(s);
return n12;
}
int findn() { // the output will be the list of numbers, but I'm testing with 1292500000
long nmin = 1000000000;
long nmax = 9999999999;
int *arr;
for(int i = nmin; i <= nmax; i++) {
*arr = numToArr(1292500000l);
// I know I can optimize this part, will work on it later
if(arr[0] % 1 != 0) // if the first digit is not divisible by one, skip to the next number
continue;
else { // if it is, check for the combination of the first two digits
char s12[3];
int n12 = join(s12, arr[0], arr[1]);
printf("%d\n", n12);
break;
...
When I do
*arr = numToArr(1292500000l);
the array doesn't have the correct digits (arr[0] should be 1, arr[1] should be 2 (but it's zero)).
I've tried messing with pointers and everything I could find online to solve this issue, but nothing works. Any help would be appreciated!
Thank you.

How to see if numbers have same digits in array?

I'm a bit stuck on one of my problems not because I don't know, but because I can't use more complex operations.(functions and multiple arrays)
So I need to make a program in C that ask for an input of an array(max 100 elements) and then program needs to sort that matrix by numbers with same digits.
So I made everything that I know, I tested my program with sorting algorithm from minimum to maximum values and it works, only thing that I can't understand is how should I test if the number have same digits inside the loop? (I can't use functions.)
So I know the method of finding if the number have the same digits but I don't know how to compare them. Here is an example of what I need.
This is what I have for now this sorts numbers from min to max.
#include <stdio.h>
int main() {
int matrix[100];
int i,j;
int temp,min;
int elements_number=0;
printf("Enter the values of matrix-max 100 elements-type -1 to end: ");
for(i=0;i<100;i++){
scanf("%d",&matrix[i]);
elements_number++;
if(matrix[i]==-1){
elements_number--;
break;
}
}
for (i=0; i<elements_number; i++) {
min=i;
for (j=i+1; j<elements_number; j++) {
if (matrix[j] < matrix[min])
min = j;
}
temp = matrix[i];
matrix[i] = matrix[min];
matrix[min] = temp;
}
for(i=0;i<elements_number;i++){
if(i!=elements_number-1){
printf("%d,",matrix[i]); }
else printf("%d.",matrix[i]);
}
return 0;
}
I need this output for these numbers:
INPUT :
1 22 43 444 51 16 7 8888 90 11 -1
OUTPUT:
1,22,444,7,8888,11,43,51,16,90.
Integers with 1 digit count as "numbers with same number of digits" like 7 and 1 in this example.
Hope that you can help.
After processing the array, the single-digit numbers should all be in the left part of the array, the other numbers in the right part. Within each part, the original order of the elements should be preserved. This is called a stable partition. It is different from sorting, because the elements are only classified into two groups. Sorting means that there is a clear relationship between any two elements in the array.
This can be done by "filtering" the array for single-digit numbers and storing the other numbers that were filtered out in a temporary second array. Then append the contents of that second array to the (now shorter) first array.
Here's how that could work:
#include <stdlib.h>
#include <stdio.h>
void print(const int *arr, int n)
{
for (int i = 0; i < 10; i++) {
if (i) printf(", ");
printf("%d", arr[i]);
}
puts(".");
}
int is_rep_digit(int n)
{
int q = n % 10;
n /= 10;
while (n) {
if (n % 10 != q) return 0;
n /= 10;
}
return 1;
}
int main()
{
int arr[10] = {1, 22, 43, 444, 51, 16, 7, 8888, 90, 11};
int aux[10]; // auxliary array for numbers with several digits
int i, j, k;
print(arr, 10);
j = 0; // number of single-digit numbers
k = 0; // number of other numbers
for (i = 0; i < 10; i++) {
if (is_rep_digit(arr[i])) {
arr[j++] = arr[i]; // pick single-digit number
} else {
aux[k++] = arr[i]; // copy other numbers to aux
}
}
k = 0;
while (j < 10) { // copy aux to end of array
arr[j++] = aux[k++];
}
print(arr, 10);
return 0;
}
Edit: I've just seen your requirement that you can't use functions. You could use Barmar's suggestion to test divisibility by 1, 11, 111 and so on. The tricky part is to find the correct divisor, however.
Anyway, the point I wanted to make here is that you don't need a full sorting algorithm here.

Finding numbers with unique digits in C

I have to write a program that finds every number (except 0) which can be factored by numbers from 2-9.
For example first such a number would be number 2520 as it can be divided by every single number from 2 to 9.
It also has to be a number that contains only 1 type of digit of its own (no multiple digits in a number). So for example 2520 will not meet this requirement since there are two same digits (2). The example of a number that meets both requirements is number 7560. That is the point I don't how to do it. I was thinking about converting value in an array to string, and then putting this string in another array so every digit would be represented by one array entry.
#include <stdio.h>
#include <math.h>
int main() {
int i, n, x, flag, y = 0;
scanf("%d", &n);
double z = pow(10, n) - 1;
int array[(int)z];
for (i = 0; i <= z; i++) {
flag = 0;
array[i] = i;
if (i > 0) {
for (x = 2; x <= 9; x++) {
if (array[i] % x != 0) {
flag = 1;
}
}
if (flag == 0) {
y = 1;
printf("%d\n", array[i]);
}
}
}
if (y == 0) {
printf("not exist");
}
return 0;
}
This should give you a base:
#include <stdio.h>
#include <string.h>
int main()
{
char snumber[20];
int number = 11235;
printf("Number = %d\n\n", number);
sprintf(snumber, "%d", number);
int histogram[10] = { 0 };
int len = strlen(snumber);
for (int i = 0; i < len; i++)
{
histogram[snumber[i] - '0']++;
}
for (int i = 0; i < 10; i++)
{
if (histogram[i] != 0)
printf("%d occurs %d times\n", i, histogram[i]);
}
}
Output:
Number = 11235
1 occurs 2 times
2 occurs 1 times
3 occurs 1 times
5 occurs 1 times
That code is a mess. Let's bin it.
Theorem: Any number that divides all numbers in the range 2 to 9 is a
multiple of 2520.
Therefore your algorithm takes the form
for (long i = 2520; i <= 9876543210 /*Beyond this there must be a duplicate*/; i += 2520){
// ToDo - reject if `i` contains one or more of the same digit.
}
For the ToDo part, see How to write a code to detect duplicate digits of any given number in C++?. Granted, it's C++, but the accepted answer ports verbatim.
If i understand correctly, your problem is that you need to identify whether a number is consisted of multiple digits.
Following your proposed approach, to convert the number into a string and use an array to represent digits, i can suggest the following solution for a function that implements it. The main function is used to test the has_repeated_digits function. It just shows a way to do it.
You can alter it and use it in your code.
#include <stdio.h>
#define MAX_DIGITS_IN_NUM 20
//returns 1 when there are repeated digits, 0 otherwise
int has_repeated_digits(int num){
// in array, array[0] represents how many times the '0' is found
// array[1], how many times '1' is found etc...
int array[10] = {0,0,0,0,0,0,0,0,0,0};
char num_string[MAX_DIGITS_IN_NUM];
//converts the number to string and stores it in num_string
sprintf(num_string, "%d", num);
int i = 0;
while (num_string[i] != '\0'){
//if a digit is found more than one time, return 1.
if (++array[num_string[i] - '0'] >= 2){
return 1; //found repeated digit
}
i++;
}
return 0; //no repeated digits found
}
// test tha function
int main()
{
int x=0;
while (scanf("%d", &x) != EOF){
if (has_repeated_digits(x))
printf("repeated digits found!\n");
else
printf("no repeated digits\n");
}
return 0;
}
You can simplify your problem from these remarks:
the least common multiple of 2, 3, 4, 5, 6, 7, 8 and 9 is 2520.
numbers larger than 9876543210 must have at least twice the same digit in their base 10 representation.
checking for duplicate digits can be done by counting the remainders of successive divisions by 10.
A simple approach is therefore to enumerate multiples of 2520 up to 9876543210 and select the numbers that have no duplicate digits.
Type unsigned long long is guaranteed to be large enough to represent all values to enumerate, but neither int nor long are.
Here is the code:
#include <stdio.h>
int main(void) {
unsigned long long i, n;
for (n = 2520; n <= 9876543210; n += 2520) {
int digits[10] = { 0 };
for (i = n; i != 0; i /= 10) {
if (digits[i % 10]++)
break;
}
if (i == 0)
printf("%llu\n", n);
}
return 0;
}
This program produces 13818 numbers in 0.076 seconds. The first one is 7560 and the last one is 9876351240.
The number 0 technically does match your constraints: it is evenly divisible by all non zero integers and it has no duplicate digits. But you excluded it explicitly.

How to check whether a no is factorial or not?

I have a problem, then given some input number n, we have to check whether the no is factorial of some other no or not.
INPUT 24, OUTPUT true
INPUT 25, OUTPUT false
I have written the following program for it:-
int factorial(int num1)
{
if(num1 > 1)
{
return num1* factorial(num1-1) ;
}
else
{
return 1 ;
}
}
int is_factorial(int num2)
{
int fact = 0 ;
int i = 0 ;
while(fact < num2)
{
fact = factorial(i) ;
i++ ;
}
if(fact == num2)
{
return 0 ;
}
else
{
return -1;
}
}
Both these functions, seem to work correctly.
When we supply them for large inputs repeatedly, then the is_factorial will be repeatedly calling factorial which will be really a waste of time.
I have also tried maintaining a table for factorials
So, my question, is there some more efficient way to check whether a number is factorial or not?
It is wasteful calculating factorials continuously like that since you're duplicating the work done in x! when you do (x+1)!, (x+2)! and so on.
One approach is to maintain a list of factorials within a given range (such as all 64-bit unsigned factorials) and just compare it with that. Given how fast factorials increase in value, that list won't be very big. In fact, here's a C meta-program that actually generates the function for you:
#include <stdio.h>
int main (void) {
unsigned long long last = 1ULL, current = 2ULL, mult = 2ULL;
size_t szOut;
puts ("int isFactorial (unsigned long long num) {");
puts (" static const unsigned long long arr[] = {");
szOut = printf (" %lluULL,", last);
while (current / mult == last) {
if (szOut > 50)
szOut = printf ("\n ") - 1;
szOut += printf (" %lluULL,", current);
last = current;
current *= ++mult;
}
puts ("\n };");
puts (" static const size_t len = sizeof (arr) / sizeof (*arr);");
puts (" for (size_t idx = 0; idx < len; idx++)");
puts (" if (arr[idx] == num)");
puts (" return 1;");
puts (" return 0;");
puts ("}");
return 0;
}
When you run that, you get the function:
int isFactorial (unsigned long long num) {
static const unsigned long long arr[] = {
1ULL, 2ULL, 6ULL, 24ULL, 120ULL, 720ULL, 5040ULL,
40320ULL, 362880ULL, 3628800ULL, 39916800ULL,
479001600ULL, 6227020800ULL, 87178291200ULL,
1307674368000ULL, 20922789888000ULL, 355687428096000ULL,
6402373705728000ULL, 121645100408832000ULL,
2432902008176640000ULL,
};
static const size_t len = sizeof (arr) / sizeof (*arr);
for (size_t idx = 0; idx < len; idx++)
if (arr[idx] == num)
return 1;
return 0;
}
which is quite short and efficient, even for the 64-bit factorials.
If you're after a purely programmatic method (with no lookup tables), you can use the property that a factorial number is:
1 x 2 x 3 x 4 x ... x (n-1) x n
for some value of n.
Hence you can simply start dividing your test number by 2, then 3 then 4 and so on. One of two things will happen.
First, you may get a non-integral result in which case it wasn't a factorial.
Second, you may end up with 1 from the division, in which case it was a factorial.
Assuming your divisions are integral, the following code would be a good starting point:
int isFactorial (unsigned long long num) {
unsigned long long currDiv = 2ULL;
while (num != 1ULL) {
if ((num % currDiv) != 0)
return 0;
num /= currDiv;
currDiv++;
}
return 1;
}
However, for efficiency, the best option is probably the first one. Move the cost of calculation to the build phase rather than at runtime. This is a standard trick in cases where the cost of calculation is significant compared to a table lookup.
You could even make it even mode efficient by using a binary search of the lookup table but that's possibly not necessary given there are only twenty elements in it.
If the number is a factorial, then its factors are 1..n for some n.
Assuming n is an integer variable, we can do the following :
int findFactNum(int test){
for(int i=1, int sum=1; sum <= test; i++){
sum *= i; //Increment factorial number
if(sum == test)
return i; //Factorial of i
}
return 0; // factorial not found
}
now pass the number 24 to this function block and it should work. This function returns the number whose factorial you just passed.
You can speed up at least half of the cases by making a simple check if the number is odd or even (use %2). No odd number (barring 1) can be the factorial of any other number
#include<stdio.h>
main()
{
float i,a;
scanf("%f",&a);
for(i=2;a>1;i++)
a/=i;
if(a==1)
printf("it is a factorial");
else
printf("not a factorial");
}
You can create an array which contains factorial list:
like in the code below I created an array containing factorials up to 20.
now you just have to input the number and check whether it is there in the array or not..
#include <stdio.h>
int main()
{
int b[19];
int i, j = 0;
int k, l;
/*writing factorials*/
for (i = 0; i <= 19; i++) {
k = i + 1;
b[i] = factorial(k);
}
printf("enter a number\n");
scanf("%d", &l);
for (j = 0; j <= 19; j++) {
if (l == b[j]) {
printf("given number is a factorial of %d\n", j + 1);
}
if (j == 19 && l != b[j]) {
printf("given number is not a factorial number\n");
}
}
}
int factorial(int a)
{
int i;
int facto = 1;
for (i = 1; i <= a; i++) {
facto = facto * i;
}
return facto;
}
public long generateFactorial(int num){
if(num==0 || num==1){
return 1;
} else{
return num*generateFactorial(num-1);
}
}
public int getOriginalNum(long num){
List<Integer> factors=new LinkedList<>(); //This is list of all factors of num
List<Integer> factors2=new LinkedList<>(); //List of all Factorial factors for eg: (1,2,3,4,5) for 120 (=5!)
int origin=1; //number representing the root of Factorial value ( for eg origin=5 if num=120)
for(int i=1;i<=num;i++){
if(num%i==0){
factors.add(i); //it will add all factors of num including 1 and num
}
}
/*
* amoong "factors" we need to find "Factorial factors for eg: (1,2,3,4,5) for 120"
* for that create new list factors2
* */
for (int i=1;i<factors.size();i++) {
if((factors.get(i))-(factors.get(i-1))==1){
/*
* 120 = 5! =5*4*3*2*1*1 (1!=1 and 0!=1 ..hence 2 times 1)
* 720 = 6! =6*5*4*3*2*1*1
* 5040 = 7! = 7*6*5*4*3*2*1*1
* 3628800 = 10! =10*9*8*7*6*5*4*3*2*1*1
* ... and so on
*
* in all cases any 2 succeding factors inf list having diff=1
* for eg: for 5 : (5-4=1)(4-3=1)(3-2=1)(2-1=1)(1-0=1) Hence difference=1 in each case
* */
factors2.add(i); //in such case add factors from 1st list " factors " to " factors2"
} else break;
//else if(this diff>1) it is not factorial number hence break
//Now last element in the list is largest num and ROOT of Factorial
}
for(Integer integer:factors2){
System.out.print(" "+integer);
}
System.out.println();
if(generateFactorial(factors2.get(factors2.size()-1))==num){ //last element is at "factors2.size()-1"
origin=factors2.get(factors2.size()-1);
}
return origin;
/*
* Above logic works only for 5! but not other numbers ??
* */
}

Find a random number length 1 to 10, using numbers 0 to 9 without repeats

I am trying to find a random number that has 1 to max digits (max < 10).
srand((int) time(NULL));
answer = ((rand() % max) + 1);
BUT:
0,...9 is only allowed to be used once.
I have found that waiting for the rand() to create such a number by chance takes too long, so I am assuming there must be a way to create a running total where each time a digit is added a comparison is made.
If you are looking for an integer with n digits drawn from 0 to 9 with no repeats (your question is hard to interpret), then the following will suffice.
The idea is to put all the digits from 0 to 9 in a hat and then draw them out one by one. Append each to the random integer value you're building.
The hat is an array initially set 0 to 9.
To draw a number when the hat has k elements in it, compute a random index j in the range [0..k-1] and get that element from the array. Then copy the last (k-1 th) element down to position j, which "erases" it. The remaining unpicked digits are now in [0..k-2], and you can repeat this process until done.
Appending a digit d to an integer value is the same as saying
val = 10 * val + d
Putting these ideas together, you have the following. Note this allows 0 in the first position, so the result may actually have one less than n digits when printed with no leading zeros.
unsigned random_unrepeated_digits(int n) {
int i, digits[] = { 0,1,2,3,4,5,6,7,8,9 };
unsigned val = 0;
for (i = 0; i < n; i++) {
int k = 10 - i, j = rand() % k;
val = 10 * val + digits[j];
digits[j] = digits[k - 1];
}
return val;
}
You can generate the each digit one by one. First, get a random integer from 0 to 9. For instance, if you get 5, then remove it from the array of all digits:
0 1 2 3 4 6 7 8 9
Next get a random integer from 0 to 8, if you get 8 this time, then the second digit is 9. Remove it and get the next digit repeatedly.
If you need to get 8 digits for instance, In the end you have only 4 digits left, for instance:
3 4 6 9
Then get a random integer from 0 to 3. If for instance, you get 0, then the last digit is 3 and the rest is discarded.
You can shuffle the digits {0, 1, 2, ..., 9}, being careful not to put 0 first, then construct the number from the appropriate number of initial digits. By doing this, while constructing the result as you go, and stopping shuffling once you've fixed the first ndig digits, you end up with code like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long long rand_digits(int ndig) {
int digits[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
long long res = 0;
for (int i = 0; i < ndig; i++) {
int r = i + rand() % (10 - i - (i == 0));
res = res * 10 + digits[r];
digits[r] = digits[i];
}
return res;
}
int main(int argc, char *argv[]) {
srand((unsigned)time(0));
for (int i = 0; i < 10; i++) {
printf("%-2d: %lld\n", i + 1, rand_digits(i + 1));
}
return 0;
}
You can use array of 10 digits, shuffle them each time and get the N first digits. Pseudo code:
void shuffle(char[] a) {
for(int i=0; i< 10; i++) {
pos = rand() % 10;
swap(a[i], a[pos]);
}
}
int main() {
char arr[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
# it prints endlessly random numbers of random length
while (1) {
shuffle(arr);
int N = rand() % 10 + 1; # how many digits to generate
for (int i=0; i<N; i++) {
printf(arr[i]);
}
}
printf("\n");
}
The possible issue in this way is when '0' comes the first digit, turning the number to gets less number than it is required. But you can add avoiding '0' at first position by fixing 'shuffle'(e.g, check if the first is '0' then generate random pos=rand()%9+1 and then swap(a[0], a[pos]) or getting numbers if you need it.
You could set up a function:
char * randstr(int len)
{
srand(0); //seed the generator
char * str = malloc(len); //allocate exactly len bytes
int i, x; //define some loop variables
char used = 0; //used is to check if the number has already been taken
char num; //a temp value
for (i = 0; i < len; i++)
{ //this loop runs through each character in the string
used = 1;
while (used) //basically, if we already used it, find another
{
used = 0;
num = rand() % 10 + 48; //48 = '8' //returns 0-9
for (x = 0; x < i; x++)
{ //this loop checks to see if its already been used
if (str[x] == num) used = 1;
}
}
}
return str;
}
This will return a char array, but not a null terminated one, though all of the numbers will be in ASCII form. For a null terminated string, simply modify it like so:
char * randstr(int len)
{
srand(0);
char * str = malloc(len + 1);
int i, x;
char used = 0;
char num;
for (i = 0; i < len; i++)
{
used = 1;
while (used)
{
used = 0;
num = rand() % 10 + 48; //48 = '8'
for (x = 0; x < i; x++)
{
if (str[x] == num) used = 1;
}
}
}
str[len - 1] = 0;
return str;
}
Hope this helps.
EDIT:
The way the function works, is it returns a string of size len, using only digits 1-9, with no repeats.
calling randstr(5) could return something like
12345
93751
73485
...
Do note, if there are no more numbers to use, the function will just sit there looping.
Comments are in the first function
Getting a random number of digits would be actually pretty simple. We just want a random number between 1 and 10. Done by
rand() % 10 + 1;
//so lets assign that to an int and call our function
int num = rand() % 10 + 1;
char * str = randstr(num); //assume this is the null terminated one
printf("The number was %s\n", str);

Resources