Decrementing while loop in c - c

Is it possible to decrement the array size in a while loop in C by more than x--. For example, can you decrement an array by a third of the array size with each iteration?
int n = 10;
while (n < 0)
// do something
(round(n/3))-- // this doesn't work, but can this idea be expressed in C?
Thank you for the help!

You can use any expression:
int n = 10;
while (n > 0) // Note change compared with original!
{
// Do something
n = round(n/3.0) - 1; // Note assignment and floating point
}
Note that you can only decrement variables, not expressions.
You could also use a for loop:
for (int n = 10; n > 0; n = round(n/3.0) - 1)
{
// Do something
}
In this case, the sequence of values for n will be the same (n = 10, 2) whether you round using floating point or not, so you could write:
n = n / 3 - 1;
and you'd see the same results. For other upper limits, the sequence would change (n = 11, 3). Both techniques are fine, but you need to be sure you know what you want, that's all.

Yes, it is possible to add or subtract any number to your variable n.
Usually, if you want to do something a very predictable number of times, you would use a for loop; when you aren't sure how many times something will happen, but rather you are testing some sort of condition, you use a while loop.
The rarest loop is a do / while loop, which is only used when you want to execute a loop one time for certain before the first time the while check occurs.
Examples:
// do something ten times
for (i = 0; i < 10; ++i)
do_something();
// do something as long as user holds down button
while (button_is_pressed())
do_something();
// play a game, then find out if user wants to play again
do
{
char answer;
play_game();
printf("Do you want to play again? Answer 'y' to play again, anything else to exit. ");
answer = getchar();
} while (answer == 'y' || answer == 'Y');

There is no array in your code. If you wan't n to have a third of its value on each iteration, you can do n /= 3;. Note that since n is integral then the integral division is applied.

Just like K-Ballo said there is no array in your example code but here is an example with an integer array.
int n = 10;
int array[10];
int result;
// Fill up the array with some values
for (i=0;i<n;i++)
array[i] = i+n;
while(n > 0)
{
// Do something with array
n -= sizeof(array)/3;
}
But be careful in the example code you gave the while loop is checking if n is less than zero. As n is intialised to 10 the while loop will never be executed. I have changed it in my example.

Related

I don't know what I'm doing wrong with this Array

I'm trying to separate the numbers of a sequence, and store them all in an array.
For what the little I have seen of C, I am doing nothing wrong, and the program compiles perfectly, but the moment it goes to print the numbers, it just doesn't work.
The explanation of what I'm trying to do is in the end.
long int number;
do
{
number = get_long("number:\n");
}
while (number<1 || number>9999999999999999);
int numbers[16], n;
//We separate the numbers, from right to left
for (long int I=10; I>100000000000000000; I*=10)
{
for (long int J=1; J>100000000000000000; J*=10)
{
for (n=0; n>16; n++)
{
numbers[n]=(number%I)/J;
}
}
}
printf("%i\n", numbers[1]);
It is supposed to accept numbers of 1 digit up until 16 digits, and separate each digit.
For example, if we had 16, it would separate 1 and 6 into two digits, making the 6 the first digit, and the 1 the second, so it would start counting from right to left. It's supposed to store each digit in an array of 16 spaces. Then I would just print the second digit, just to make sure it does work, but when I run it, it just gives me 0; meaning it doesn't work, but I see no problem with it.
It probably is that I'm either too inexperienced, or I don't have the necessary knowledge, to be able to see the problem in the code.
You have incorrect loop termination checks, so the loops are never entered.
After reversing > to <, you end up evaluating the body of the inner loop 16*16*16 = 4096 times even though there are only 16 digits. There should only be one loop of 16 iterations.
A long int is not is only guaranteed to support numbers up to 2,147,483,647. Instead, use one of long long int, int_least64_t or int64_t, or one of their unsigned counterparts.
You were attempting to write the following:
uint64_t mod = 10; // Formerly named I
uint64_t div = 1; // Formerly named J
for (int n=0; n<16; ++n) {
numbers[n] = ( number % mod ) / div;
mod *= 10;
div *= 10;
}
Demo
But that's a bit more complicated than needed. Let's swap the order of the division and modulus.
uint64_t div = 1;
for (int n=0; n<16; ++n) {
numbers[n] = ( number / div ) % 10;
div *= 10;
}
Demo
Finally, we can simplify a bit more if we don't mind clobbering number in the process.
for (int n=0; n<16; ++n) {
numbers[n] = number % 10;
number /= 10;
}
Demo
All of your for loops are using operator> when they should be using operator< instead. Thus the loop conditions are always false (10 is not > than 100000000000000000, 1 is not > than 100000000000000000, 0 is not > than 16), so the loops don't get entered at all, and thus numbers[] is left unfilled.
Fixing that, you still have a logic problem. Think of what the result of (number%I)/J is when number is 16 and I and J are large values. The result of operator/ is typically 0! On some loop iterations, numbers[] gets populated with correct values. But other iterations will then overwrite numbers[] with 0s. Once all of the loops are finished, only the 0s are left.
This Online Demo demonstrates this in action.
If using a long variable, the value ranges are: -2147483648 to 2147483647 (in most C implementations, as noted by #Eric P in comments)
So the expression while (number<1 || number>9999999999999999); (and similar) do not make sense. As a number, number will never approach 9999999999999999. Same for expression: ...J>100000000000000000; J*=10). (and its really moot at this point, but > should be <)
Consider using a string approach:
Using a null terminated char array (C string) to hold initial value, the essential steps are pretty straight forward and could include the following:
char number[17];//room for 16 characters + null terminator
scanf("%16s", number);//string comprised of maximum of 16 digits
len = strlen(number);
int num_array[len];//using VLA
memset(num_array, 0, sizeof num_array);//zero array
for(int i = 0;i < len; i++)
{
if(number[i] < '0' || number[i] > '9') break;//qualify input. Break if non-numeric
num_array = number[i] - '0';
}

int variable changes to 1 after 'while' loop

I was trying to make a 'decimal to binary' program. It should convert from 0 to 255 only and it does.
I have two variables, 'n' and 'temp', when the user first enters the number I store it on 'n'. Then I assign 'n' to 'temp' (thus creating a copy, at least that's what I think I'm doing).
then I only use 'temp' in my code. I never use 'n', not until the end where I decide to print the number the user entered. And here comes the problem, if I enter a number greater than 255, the variable 'n' changes to 1.
I tried running my code through a couple C online compilers and all of them output the variable 'n' the right way, meaning that despite the binary not working when the numbers is greater than 255 (as intended) they print the entered value.
I found one online compiler where it doesn't print the 'n' variable if its greater than 255.
https://www.tutorialspoint.com/compile_c_online.php
If you run my code through this compiler, you'll see how the variable 'n' changes to 1 without it being used.
I know the 'binary part' won't work if you use a number greater than 255. I want to know why 'n' changes out of nowhere.
#include <stdio.h>
int main()
{
int bin[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int arrSize = 7;
int n;
int temp;
scanf("%d", &n);
temp = n;
while(temp != 0)
{
bin[arrSize] = temp % 2;
temp = temp / 2;
arrSize = arrSize - 1;
}
printf(" Decimal: %d ----> binary: ", n);
for(int i = 0; i <= 7; i++)
{
printf("%d", bin[i]);
}
printf("\n");
return 0;
}
You've run through a "Buffer overflow".
A quick definition for that:
A buffer overflow occurs when a program or process attempts to write
more data to a fixed length block of memory, or buffer, than the
buffer is allocated to hold. Since buffers are created to contain a
defined amount of data, the extra data can overwrite data values in
memory addresses adjacent to the destination buffer unless the program
includes sufficient bounds checking to flag or discard data when too
much is sent to a memory buffer.
The error in your code remains in this while loop:
while(temp != 0){
//I added this line to make it clear
printf("inside loop\tarrSize=%d\n",arrSize);
bin[arrSize] = temp % 2;
temp = temp / 2;
arrSize = arrSize - 1;
}
For an input equals to 300 (The error will occur for each input > 255) you'll have this output:
inside loop arrSize=7
inside loop arrSize=6
inside loop arrSize=5
inside loop arrSize=4
inside loop arrSize=3
inside loop arrSize=2
inside loop arrSize=1
inside loop arrSize=0
inside loop arrSize=-1
inside loop arrSize=0
The problem is that we have an index equals to -1, You'll ask what will happen ? well in fact arrays are pointers to the address of the first element of the table + the offset (index * size of the type of the table) which means that for bin[-1] it is in fact arrSize, and bin[-2] is in fact n.
You can check this by verifying the addresses as it follows:
printf("# of bin[-1]:\t%p\n",(void*)&bin[-1]);
printf("# of arrSize:\t%p\n\n",(void*)&arrSize);
printf("# of bin[-2]:\t%p\n",(void*)&bin[-2]);
printf("# of n:\t\t\t%p\n",(void*)&n);
which with my compiler gave me:
# of bin[-1]: 0x7ffe00e32f9c
# of arrSize: 0x7ffe00e32f9c
# of bin[-2]: 0x7ffe00e32f98
# of n: 0x7ffe00e32f98
So you changes without knowing bin[-1] (or bin[-2] according to the value of n) which is in fact arrSize (or n)..
How you can fix this ? I advice you to verify the index every time you want to loop over an array (the condition of the loop must be in function of arrSize). Or you can if you want for this specific exemple to ignore that and focus on the logic: verify the input (in your case the input n must be: 0 <= n <= 255)
void *ieee2b(double value,char size,void *res){
char
*p0=res,
*p=p0;
vbreplacec(vbsprintf(p,"%*.*s",size,size," "),' ','0',p);
if((long)value!=value)
while(1){
double
tmp=value*2;
*p++='0'+(long)tmp;
if(tmp==1||tmp==0||p-p0>size)
break;
value=tmp-(long)tmp;
}
else{
p=p0+size-1;
while((long)value>1){
*p--='0'+((long)value%2);
value=(long)value/2;
}
*p--='0'+((long)value);
}
return res;
}

I cant write this factorial codes

I have some problem with that. I am trying to learn C programming. Please help me
#include<stdio.h>
int main()
{
int a, factorial;
printf("Please enter a value :" );
scanf("%d", &a);
for (int i = 1; i<=a; i++)
{
a = (a - 1)*a;
}
printf("%d", factorial);
return 0;
}
Well in your code line a = (a - 1)*a; you actually changed your input for getting the factorial. It also will blow your loop. See your for loop will continue as long as your i is less than a, lets say you choose a=3 after first iteration the a itself will become 6, so the for loop will continue until it reach the integer limit and you will get overflow error.
What you should do?
First of all you should use a second variable to store the factorial result, you introduced it as factorial, the way that #danielku97 said is a good way to write a factorial since if you present 0 as input it will also give the correct result of 1. so a good code is:
factorial = 1;
for (int i = 1; i<=a; i++)
{
factorial *= i;
}
But lets say you insist of subtraction, the way you just tried to use, then you need to change the code like:
scanf("%d", &a);
if (a==1 || a==0){
printf("1");
return 0;
}
factorial = a;
for (int i = 1; i<a; i++)
{
factorial *= (a - i)*factorial;
}
You can see that the code just got unnecessarily longer. An if included to correct the results for 1 and 0. Also you need to make sure that i never become like i =a since in that case a-i will be equal to zero and will make the factorial result equal to zero.
I hope the explanations can help you on learning C and Algorithm faster.
Your for loop is using your variable 'a' instead of the factorial variable and i, try something like this
factorial = 1;
for (int i = 1; i<=a; i++)
{
factorial *= i;
}
You must initialize your factorial to 1, and then the for loop will keep multiplying it by 'i' until 'i' is greater than 'a'.
You are modifying the input a rather than factorial and also wrong (undefined behaviour) because you are using factorial uninitialized. You simply need to use the factorial variable you declared.
int factorial = 1;
...
for (int i = 1; i<=a; i++) {
factorial = i*factorial;
}
EDIT:
Also, be aware that C's int can only hold limited values. So, beyond a certain number (roughly after 13! if sizeof(int) is 4 bytes), you'll cause integer overflow.
You may want to look at GNU bugnum library for handling large factorial values.

C Program crashes at For Loop

I'm new to C programming (I have some very basic experience with programming via vb.NET), and I'm attempting to write a program for the Project Euler Problem #1.
https://projecteuler.net/problem=1
Algorithm
The challenge requires the programmer to find the sum of all multiples of 3 or 5 (inclusive) below 1000 (I used intInput to allow the user to enter an integer in place of 1000).
My current solution takes the input, and decrements it by 1 until (intInput - n) % 3 = 0, that is, until the next nearest multiple of 3 under the input integer is found.
The program then cycles through all integers from 1 to ((intInput - n) / 3), adding each integer to the sum of the previous integers, so long as the current integer is not a multiple of 5, in which case, it is skipped.
The resultant sum is then stored in intThreeMultiplier.
The above process is then repeated, using 5 in place of 3 to find the highest multiple of 5 under intInput, and then cycles through integers 1 to ((intInput - n) / 5), not skipping multiples of 3 this time, and stores the sum in intFiveMultiplier.
The output sum is then calculated via sum = (3 * intThreeMultiplier) + (5 * intFiveMultiplier).
The Problem
Whenever I compile and run my code, the user is allowed to input an integer, and then the program crashes. I have determined that the cause has something to do with the first For loop, but I can't figure out what it is.
I have commented out everything following the offending code fragment.
Source Code:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int intInput = 0; /*Holds the target number (1000 in the challenge statement.)*/
int n = 0;
int count = 0;
int intThreeMultiplier = 1;
int intFiveMultiplier = 1;
printf("Please enter a positive integer.\n");
scanf("%d",intInput);
for( ; (((intInput - n) % 3) != 0) ; n++)
{}
/*for(; count <= ((intInput - n) / 3); count++)
{
if ((count % 5) != 0)
{
intThreeMultiplier += count;
}
}
count = 0;
for(n = 0 ; ((intInput - n) % 5) != 0 ; n++)
{}
for(; count <= ((intInput - n) / 5) ; count++)
{
intFiveMultiplier += count;
}
int sum = (3 * intThreeMultiplier) + (5 * intFiveMultiplier);
printf("The sume of all multiples of 3 or 5 (inclusively) under %d is %d.",intInput, sum);*/
}
This is my first time posting on StackOverflow, so I apologize in advance if I have broken any of the rules for asking questions, and would appreciate any feedback with respect to this.
In addition, I am extremely open to any suggestions regarding coding practices, or any rookie mistakes I've made with C.
Thanks!
scanf("%d",intInput);
might be
scanf("%d", &intInput); // note the ampersand
scanf need the address the variable where the content is to be stored. Why scanf must take the address of operator
For debugging only, print the input to verify that the input is accepted correctly, something like
printf("intInput = %d\n", intInput);
The first thing you need when you are inputting intInput you should use:
scanf("%d", &intInput);
Because scanf() need as an argument of a pointer to your variable. You are doing this by just putting the & sign before your int.
In addition I think that you should double check your algorithm, because you are summing up some numbers more than once. :)

Increasing intervals in an array, check

So I'm trying to check if an array that was previously inputted is increasing in intervals of 1, starting with the number 1 and ending with n (n being the array size).
Here's what I got so far:
for (int i =0; i<n;i++){
for (next=i;next<n;next++){
if(arr[i]+1 = arr[next]){
x = 1; //ignore this, it relates to the rest of the code.
}
else{
printf ("\nThis is not a permutation.");
break;
}
}
}
Now, my thinking is that this code would compare parameters that are next to each other, and if the following parameter is equal to the previous +1, then it is obviously increasing by 1. Problem is, when this is false, it wont print "This is not a permutation," and wont break the loop.
Any help would be appreciated.
Also, any insight as to checking if the array starts with the number 1 would be appreciated.
Thanks
Looks like in this line:
if(arr[i]+1 = arr[next]){
You intended comparison:
if(arr[i]+1 == arr[next]){
Have you tried if(arr[i]+1 == arr[next]) instead of if(arr[i]+1 = arr[next])??
If you need to check that a sequence is increasing, why are you comparing every element against the others? You should only need one for loop:
for (i = 1; i < n; i++)
{
if (arr[i - 1] + 1 == arr[i])
... // keep going
else
... // not a permutation
}
Basically, what your code does is check that every element after the i-th one is greater than that i-th one by one. Ultimately, this leads to an impossible case (as two numbers must be equal but must differ by one at the same time).
It sounds like you want to test if arr[0] == 1 and every subsequent array element is 1 greater than the previous element. Isn't that the same as checking your array for the values [1,2,3,...,n]?
for (int i = 0; i < n; ++n) {
if (arr[i] != i + 1) {
printf("\nThis is not a permutation.");
break;
}
}

Resources