Unspecified return from a function - c

I've been teaching myself C through various sources. One of exercises I've found is this past year's cs50 problem sets (found here under the heading Bad Credit). Essentially, I've solved the problem but realized that I am performing the same step twice and perhaps could wrap that step inside of a function to be reused.
My problem is that I'm not sure how to define a return to an as yet unspecified array. Or, for that matter, if this is a good idea. I think that reusing the code would be a good thing if I could make it work, but I can't figure out how to do so.
The problem, as shown in the code below is taking a long number, separating each individual digit, and performing a bit of math to do a checksum. This is returned to step1 in the code below. The do/while loop is doing the heavy lifting here, and what I would like to do is to do the same with elements in step1 and return those into step2 or any other variable for that matter.
long long num = 378282246310005;
int step1[10];
int step2[10];
do {
int i = 0;
step1[i] = num % 10; // this returns to one array
num /= 10;
i++;
} while (num != 0);
I realize this isn't that big a deal for this problem. I just decided that it would be good to know how to do it, if possible.

I'll take you through the steps. Here's your code:
do {
int i = 0;
step1[i] = num % 10;
num /= 10;
i++;
} while (num != 0);
First, an error. The i variable should be initialized and declared outside the loop, otherwise i == 0 every single time you go through the loop.
int i = 0;
do {
step1[i] = num % 10;
num /= 10;
i++;
} while (num != 0);
This should be recognizable as the expanded version of a for loop, so:
for (int i = 0; num != 0; i++, num /= 10)
step1[i] = num % 10;
// note: different for case num == 0
Then, if you want to turn it into a function,
void get_digits(int digits[], long long num) {
for (int i = 0; num != 0; i++, num /= 10)
digits[i] = num % 10;
}
A long story short, when you pass an array to a function in C, the array doesn't get copied so you can change the array inside the function and see those changes outside the function. (Long version: when arrays are function parameters they decay into pointers.)
Final note: you will need 19 elements in the array, not 10. So:
long long num = 378282246310005;
int step1[19];
get_digits(step1, num);

You can pass the array by reference, like so:
//Number to checksum is num
//Array to store checksum is arr
//Maximal length of arr is n
void checksum(long long num, int arr[], int n){
int i = 0;
do {
arr[i] = num % 10; // this returns to one array
num /= 10;
i++;
if(i==n) return; //break before we overflow array
} while (num != 0);
}
Note that your code is potentially unsafe because you may end up writing to a part of the array beyond the memory you've allocated for it. That is, you define int step1[10] but may end up writing to step[11].
Also, you stuck your int i=0 inside of the loop. I assumed you wanted it outside.

Related

How often is a number divisible without a rest?

I am currently trying to write a method which checks how often a number is divisible by 5 with a rest of 0 (e.g. 25 is two times; 125 is three times).
I thought my code is correct but it always states that it is possible one more time than it actually is (e.g. 25 is three times; wrong).
My approach is the following:
int main()
{
div_t o;
int inp = 25, i = 0;
while(o.rem == 0){
o = div(inp, 5);
inp = o.quot;
i++
}
return 0;
}
I debugged the code already and figured that the issue is that it steps once more into the loop even though the rest is bigger 0. Why is that? I can't really wrap my head around it.
First: 25/5 = 5; Rest = 0;
Second: 5/5 = 1; Rest = 1; - Shouldn't it stop here?
Third: 1/5 = 0; Rest = 1;
Ah... got it. The point where the remainder is 0 is reached when the division is done with the number which results in a rest bigger zero which is after i got increased.
What is the cleanest approach to fix that? i -= 1 seems kinda like a workaround and I wanted to avoid using an if to break
You're using div() to do the division, which I had to look up to verify that it's part of the standard. I think it's kind of rarely used, and more suited for cases where you really care about performance. This doesn't seem like such a case, and so I think it's a bit obscure.
Anyhow, here's how I would expect it to look, without div():
#include <stdio.h>
unsigned int count_factors(unsigned int n, unsigned int factor)
{
unsigned int count = 0;
for(; n >= factor; ++count)
{
const int remainder = n % factor;
if(remainder != 0)
break;
n /= factor;
}
return count;
}
int main(void) {
printf("%u\n", count_factors(17, 5));
printf("%u\n", count_factors(25, 5));
printf("%u\n", count_factors(125, 5));
return 0;
}
This prints:
0
2
3
Change the while loop condition in :
while(o.rem == 0 && inp >= 5)
In this way your division will stop after that you are inspecting the number 5.
A suggestion: use a const variable to wrap the 5 ;)
As far as I understand you want to know whether the input is an integer power of 5 (or in general whether v == N^x) and if it is, you want to calculate and return the power (aka x). Otherwise return 0. This is more or less a logN function except that it requires integer results.
I would go for code like this:
#include <stdio.h>
unsigned int logN_special(unsigned int v, unsigned int n)
{
unsigned int r = 0;
if (n == 0) return 0; // Illegal
if (n == 1) return 0; // Illegal
if (v < n) return 0; // Will always give zero
if (n*(v/n) != v) return 0; // Make sure that v = n^x
// Find the x
while(v != 1)
{
v /= n;
++r;
}
return r;
}

Function that returns the sum of the number of dividers without remainder of a number, C

I could easily print what I wanted in a loop, but I'm new to functions and I need to save or return the sum of the dividers that have no remainder to a number which is an input of the user.
Example:
Input - 6
Output - 1+2+3=6
How I started:
int NumberOfDividers(int number)
{
int i,num, count = 0;
num = number;
for ( i = 0; i < num; i++)
{
if ((num % i) == 0) //so now I know i is one of the dividers i want to save.
}
}
So if i is one of the dividers I want, how can I save it into a variable? Or an array?
To return the sum of the proper divisors, do:
int sum_of_proper_divisors (int number)
{
int sum = 0;
int i;
for (i = 1; i < number; i++)
{
if ((number % i) == 0)
sum += i;
}
return sum;
}
You just need to use the return keyword to return the value.
You can do this way...
//other headers as you need
#include<string.h>//this header is for memset
int dividers[1000];//global array
int currPos;//global variable
int NumberOfDividers(int number)
{
int i,num, count = 0;
num = number;
for ( i = 1; i < num; i++)//you should start counting from 1 otherwise you will get floating point exception
{
if ((num % i) == 0)
{
dividers[currPos]=i;//putting the dividers in the array
currPos++;//updating the pivot where the next dividers will stay
}
}
return 0;
}
int main()
{
memset(dividers,0,sizeof(dividers));//initializing the array
currPos=0;//initializing the variable to point at the start of the array
NumberOfDividers(6);
int i;
int sum=0;
for(i=0;i<currPos;i++)
{
printf("%d",dividers[i]);
sum+=dividers[i];
if(i!=currPos-1)
{
printf("+");
}
}
printf("=%d\n",sum);
return 0;
}
As this task looked fun to do, did not want to take away the coding experience. Instead laid out a sample algorithm that should code in C fairly directly.
Pseudo-code
int *NumberOfDividers(int number)
find isqrt(number) --> sqrt_number
sqrt_number*2 + 2 --> max_array_count
allocate int[] with max_array_count elements
validate allocation
starting at divisor = 1, in a loop ...
quotient = number/divisor
remainder = number%divisor
if (remainder == 0)
add divisor to list
if (divisor != quotient) add quotient to list
if (divisor >= quotient) quit loop
divisor++
append 0 to list to indicate the end
shrink array to needed size if desired
validate shrink result
return array pointer.
Notice the loop does at most sqrt(number) iterations, so a reasonable upper bound of the needed array size can be calculated before using any divisors.
Also see How many positive integers are factors of a given number? for more advanced ideas.
You can see an another way to do this. This will work very fast for a vast amount of data. Here is my way and you can follow this to find this in a fastest way to find the sum of factors of a number. Here is my code:
int number_of_divisor(int n)
{
int sum_of_factors=0;
sum_of_factors+=1;//as 1 is factor of all num
//sum_of_factors+=n;//n will always a factor of n
for(int i = 2; i * i <= n; ++i)
{
if(n % i == 0)
{
sum_of_factors+=i;
if(i * i != n)
sum_of_factors+=(n/i);
}
}
return sum_of_factors;
}
if your input is long then change all int by long.
Thank you.

Trying to turn the factorial part into another function

I have to begin my thanking you guys for the help. I am trying to turn the factorial part of the code into another function and was wondering if I needed to add everything within the
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
int indx;
int arrayIndx;
int accumulator;
int fact;
int individualDigit[50];
int length;
for(indx = 99999; indx > 0; indx--)
{
num = indx;
for (length = 0; num > 0; length++)
{
individualDigit[length] = num % 10;
num /= 10;
}
accumulator = 0;
for (arrayIndx = 0; arrayIndx < length; arrayIndx++)
{
fact = 1;
while(individualDigit[arrayIndx] > 0)
{
fact*= individualDigit[arrayIndx];
individualDigit[arrayIndx]--;
}
accumulator += fact;
}
if(accumulator == indx)
{
printf("%d ", accumulator);
}
}
return 0;
}
You program is badly designed. It is not indented, you are using variable names index, indx and idex which is confusing for the reader and would lead to nightmares for long term maintenance. Also the factorial computation would deserve to be in a function for better modularity.
But apart from that, your program does what you ask, correctly computes factorials and adds them in the accumulator variable. The only problem is that you never print that accumulator except for the last 2 cases (2 and 1) where n = n!.
Simply replace :
if (accumulator == indx)
{
printf("\n%d\n", indx);
}
with
printf("\n%d\n", accumulator);
and you will see your results.
If you want to store the sum of factorials in an array, you just have to declare int sumOfFact[26] = {0}; just before int individualDigit[50]; to define the array and initialize sumOfFact[0] to 1, and then add sumOfFact[indx] = accumulator; just before printing the accumulator.
To put the factorial part in a function, it is quite simple. First declare it above your main:
int ffact(int n);
the define it anywhere in your code (eventually in another compilation unit - a .c file - if you want)
inf ffact(int n) {
fact = 1;
while (n > 1) {
fact *= n--;
/* if (fact < 0) { fprintf(stderr, "Overflow in ffact(%d)\n", n); return 0; } */
}
return fact
}
I commented out the test for overflow, because I assume you use at least 32 bits int and fact(9) will not overflow (but fact(13) would ...)
The loop computing the sum of factorials becomes:
accumulator = 0;
for (arrayIndx = 0; arrayIndx < length; arrayIndx++)
{
accumulator += ffact(individualDigit[arrayIndx]);
}
printf("\n%d\n", accumulator);
Advantages for that modularity: it is simpler to separately test the code for ffact. So when things go wrong, you have not to crawl among one simple piece of code of more than 40 lines (not counting the absent but necessaries comments). And the code no longers clutters the individualDigit array.

Segmentation Fault 11 with recursive function in C

I keep receiving a Segmentation Fault 11 for the following code. I believe it has something to do with recursion but I'm not entirely sure how. The method should take in an array, skip the odd values, and keep repeating until it has an array with only value left and returns that value.
Thanks!
#include <stdio.h>
int callTable(int table[], int size)
{
int i = 0;
int j = 0;
int cHeight = size / 2;
int cTable[cHeight];
while (i < size)
{
if (table[i] % 2 == 0)
{
cTable[j] = table[i];
j++;
}
i++;
}
if (size > 1)
return callTable(cTable, cHeight);
else
return cTable[0];
}
int main()
{
int tPass[100];
int i, answer;
for (i = 0; i < 100; i++)
tPass[i] = i + 1;
answer = callTable(tPass, sizeof(tPass) / sizeof(tPass[0]));
printf("%d\n", answer);
}
Do you want to skip the odd values or the odd indexes? You are currently skipping the odd values, so after you call callTable once, there are only even values left. Then, on the second call, you try to use an array of half the size to store the even values (which are all of them), so you try to store the entire array on another with half the size.
If you intended to skip the odd indexes, then change this line:
if (table[i]%2==0)
for this one:
if (i%2==0)
That runs fine and returns 1 (which is the number with index 0).

C programming - A array and a random number combined question?

this is the part of my code I'm having trouble with. I can't understand why its doing it wrong. I have an array where it stores numbers 0 - 25 which are cases. The numbers are to be randomized and overwritten into the array. Only condition is is that no number can be doulbes, there can only be one of that number. I'm not asking you to do my code but do hint me or point me in the write directions. I am trying to learn :)
The problem lies within the second do loop. I can get the numbers to be randomized, but I get doubles. I have created a loop to check and fix this, but it's not working. The code does run, and doubles do still happen and I can't see why. It looks correct to me. Please look, thank you (:
This is what I have done originally (at the very end is where I am at now):
int check_double = 0;
int i = 0;
int counter = 0;
int array_adder = 0;
int random_number = 0;
int cases[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
};
float money[] = {
0.01,1,5,10,25,50,75,100,200,300,400,500,750,1000,5000,10000,25000,50000,750000,100000,200000,300000,400000,500000,750000,1000000
};
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
cases[counter]= rand() % 26;
counter += 1;
printf("%d\n", cases[counter]);
}
while (counter <= 25);
//make sure there are no doubles in the array, just 0 - 25 and not a single number repeated twice
do
{
check_double = 0;
for (i = 0; i < counter; i++)
{
if (cases[counter] == cases[i])
{
cases[counter] = rand()% 26;
check_double == 1;
}
}
}
while (check_double != 0);
Currently, what I had achived after that was combing both loops and check for doubles as the array goes. This is what I made, it still has doubles and im not sure why, I only posted the cose with both loops combined:
do
{
cases[counter]= rand() % 26;
if (cases[counter]>=1);
for(i=0;i<=counter;i++)
if (cases[counter]==cases[i])
{
cases[counter]=rand()% 26;
}
printf("%d\n",cases[counter]);
counter+=1;
}
Robsta, you could try the following piece of code, I have run this in Dev-C++, any changes that you require can be made from your side. But, I assure you that this code generates what you intend.
int check_double = 0;
int i = 0;
int counter = 0;
int cases[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
};
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
cases[counter]= rand() % 26;
for(i=0;i<counter;i++)
if (cases[counter]==cases[i]){
while (cases[counter]==cases[i])
{
cases[counter]=rand()% 26;
}
i=0;
}
printf("%d\t%d\n",counter,cases[counter]);
counter+=1;
}while (counter <= 25);
If you have any clarifications required, I would love to discuss with you.
-Sandip
You're only ever writing over the last value in the array:
for(i=0;i<counter;i++)
if (cases[counter]==cases[i])
You need to loop through as you are, then have an inner loop, where you compare all the other entries to the current one.
Even easier would be to do the loop where you set each random number, so when you set cases[3] for example, loop from 0 to 2 and check to see if your new value for 3 clashes, if so, wash - rinse - repeat!
You have this line of code:
check_double==1;
That doesn't change check_double because it's ==, not =. == compares; it doesn't assign. Change that line to this:
check_double=1;
A helpful compiler (clang in this example) will give you a warning about this:
test.c:5:14: warning: expression result unused [-Wunused-value]
check_double==1;
~~~~~~~~~~~~^ ~
You can't check for duplicates with a single loop. You need to at least compare every possible pair of elements to be able to see if there's a duplicate. I'm guessing you forgot to loop over counter somewhere inside the second do...while?
Note that your method is not guaranteed to terminate. (Very, very likely but not certain.) Why don't you simply shuffle the cases array? Shuffling is simple but tricky; see Fisher-Yates (or Knuth) Shuffle for a simple algorithm.
If you are asking how to randomly sequence the number 1-25 then you could do something like this. This is a very brute-force way of generating the sequence, but it does work and might give you a starting point for something more optimized.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <conio.h>
const int LastNumber = 25;
bool HasEmpty(int available[LastNumber][2])
{
bool result = false;
for(int i = 0; i < LastNumber; i++)
{
if (available[i][1] == 0)
{
result = true;
break;
}
}
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int available[LastNumber][2];
int newSequence[LastNumber];
srand((unsigned int)time(NULL));
for(int i = 0; i < LastNumber; i++)
{
available[i][0]=i;
available[i][1]=0;
}
int usedIndex = 0;
while (HasEmpty(available))
{
int temp = rand() % (LastNumber + 1);
if (available[temp][1] == 0)
{
newSequence[usedIndex++] = available[temp][0];
available[temp][1] = 1;
}
}
for(int i = 0; i < LastNumber; i++)
{
printf("%d\n",newSequence[i]);
}
getch();
return 0;
}

Resources