The Solution
So we need to know what an odd number is. It can be defined as a number that cannot be divided by 2 and the result being a whole number. In mathematics, we can also say the modulo division by 2 does not yield 0.
Let's print these numbers.
Naive implementation
We can just iterate between the start and the end and check if a number can be divided by two or not and print accordingly.
void printOdds(int start, int end)
{
while (start <= end)
{
if (start % 2 != 0)
printf("%d, ", start);
start++;
}
printf("\n");
}
But we can do better
We know, after we found the first off number, that the next odd number is larger by two. So instead of checking every number, all we need to do is find the smallest odd number from start, and list (without checking) every second number until we reach the end (or reach the first odd after end, which we do not process any more).
If the first number is odd, we're good. If not, the first odd is one larger than our start.
// print all the odd numbers between start and end (inclusive)
void printOdds(int start, int end)
{
if (start % 2 == 0)
start++;
for (int i = start; i <= end; i += 2)
{
if (i != start)
printf(", ");
printf("%d", i);
}
}
We can still do better
But what if someone was tricky and start is larger than end? In this case, we have to list the numbers descending. Things will get a bit tricky.
In this case, we have to increase or decrease start depending on what direction we go: ascending (+1) or descending (-1).
The direction can be determined by comparing the start and end and see which one is larger.
We also have to make sure end is the first odd we do not want to print, as i != end is the exit condition of the loop. So first we make sure end is the last odd that we want to print, then we take a step beyond this limit.
// print all the odd numbers between start and end (inclusive)
void printOdds(int start, int end)
{
int direction = start < end ? +1 : -1;
if (start % 2 == 0)
start += direction;
if (end % 2 == 0)
end -= direction;
int step = 2 * direction;
end += step;
for (int i = start; i != end; i += step)
{
if (i != start)
printf(", ");
printf("%d", i);
}
printf("\n");
}
Handle corner cases?
If we still want to work on this method, we may notice, that we may have an overflow or underflow if we pick end to be too high or too low due to t he end += step line.
We can battle this by:
- leaving the loop if we reached the end before we increment the loop variable.
- we do not enter the loop at all, if there's nothing to do (avoiding double checking the exit condition)
typedef enum { finished = 0, firstElement = 1, restOfTheElements = 2} states;
void printOdds(int start, int end)
{
// ...
int dirAfterLimitAdjust = start <= end ? +1 : -1;
if (direction != dirAfterLimitAdjust) // There were no odds between start and end
{
printf("\n"); // Indicate no output by an empty line.
return;
}
int step = 2 * direction;
states status = firstElement;
while (status)
{
if (status == firstElement)
status = restOfTheElements;
else // status == restOfTheElements
printf(", ");
printf("%d", start);
if (start == end)
status = finished;
start += step;
}
printf("\n");
}
The Final Implementation
#include <stdio.h>
typedef enum
{
finished = 0,
firstElement = 1,
restOfTheElements = 2
} states;
// print all the odd numbers between start and end (inclusive)
void printOdds(int start, int end)
{
int direction = start <= end ? +1 : -1;
if (start % 2 == 0)
start += direction;
if (end % 2 == 0)
end -= direction;
int dirAfterLimitAdjust = start <= end ? +1 : -1;
if (direction != dirAfterLimitAdjust) // There were no odds between start and end
{
printf("\n"); // Indicate no output by an empty line.
return;
}
int step = 2 * direction;
states status = firstElement;
while (status)
{
if (status == firstElement)
status = restOfTheElements;
else // status == restOfTheElements
printf(", ");
printf("%d", start);
if (start == end)
status = finished;
start += step;
}
printf("\n");
}
int main()
{
printf("[-4, 6]: "); printOdds(-4, 6); // Test ascending
printf("[6, -4]: "); printOdds(6, -4); // Test descending
printf("[6, 6]: "); printOdds(6, 6); // Test empty
printf("[5, 5]: "); printOdds(5, 5); // Test only one odd
return 0;
}
Note
Problem #2 is not described ("perform following mathematical expression", what is that? It's not put into the post), so it cannot be solved.