Converting "for" loop to "while" loop - c

I´m currently working on my semester work and this is a piece of my code. As you can see there is a for loop with some if statements where I am working with a structure. I was thinking of converting this for loop onto a while loop but I´m not quite sure how. Maybe someone may give me a hint?
for(X = 1; X <= 100; X++)
{
if(structure[X].number == -1)
{
structure[X].number = number;
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
if(structure[X].number == number)
{
if(structure[X].first_info == -1)
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
}

Converting the for loop to a while loop is easy, but the for loop is a much safer construct as it groups the initialization, test and increment of the index variable in one clear place.
Incidentally, your code is misindented, and the nested if statements may be inconsistent:
if(structure[X].number == number)
{
if(structure[X].first_info == -1)
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
When properly reformated, it becomes:
if (structure[X].number == number) {
if (structure[X].first_info == -1)
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
Is this what you intended? Be more careful with indentation, it helps avoid silly mistakes.
Here is the converted code, but be aware that contrary to a for statement, a continue statement would by-pass the X++ update expression. Also worth noting is the surprising use of a 1 based index value for X. Index values are 0 based in C and array size can be checked with a < comparison instead of <=.
X = 1;
while (X <= 100) {
if (structure[X].number == -1) {
structure[X].number = number;
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
if (structure[X].number == number) {
if (structure[X].first_info == -1)
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
X++;
}
If structure has 100 elements, the code must be changed to:
X = 0;
while (X < 100) {
if (structure[X].number == -1) {
structure[X].number = number;
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
if (structure[X].number == number) {
if (structure[X].first_info == -1)
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
X++;
}

All basic loops have three components:
an initializer (an initial value assigned to a variable)
a condition (the value we are checking for to stay in the loop)
a modifier (something that modifies our variable)
With a for loop you notice all three of those here:
for(X = 1; X <= 100; X++)
The first component in the parentheses is an initializer (X=1), the next component is the condition (X <= 100), and the last component is the modifier (X++).
We can use the exact same components with a while loop. We just place them differently:
int x = 1; //our intializer
while (x <= 100){ //our condition
if(structure[X].number == -1)
{
structure[X].number = number;
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
if(structure[X].number == number)
{
if(structure[X].first_info == -1){
structure[X].first_info = position;
}
structure[X].second_info = position;
break;
}
x++; //our modifier
}
With that said, arrays in C always start at index 0. I kept your code the same as you had it, but generally whether you are using a for loop or while loop you will want to change your initializer and condition as follows:
your initializer should likely be x = 0 (not x = 1)
your condition should likely be either x < 100 or x <= 99 (not x <= 100)
This is because an array of 100 items will have indexes 0 to 99.
Two more points:
When counting through an indexed array like this the code is usually easier to read as a for loop rather than a while loop. Is there a reason that you were wanting to use a while loop instead?
Based on your indentation it was unclear what should be included in the last if clause. I have added braces to your last if clause to make it easier to read, but maybe other lines should have been included in the braces as well?

You can do this to convert to while loop. But I would suggest to search and understand the loop structures yourself.
X=0; /* for arrays indexing always starts at 0 */
while(X<100)
{
if(structure[X].number == -1)
{
structure[X].number = number;
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
if(structure[X].number == number)
{
if(structure[X].first_info == -1) /* adding braces */
{
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
}
X++;
}

The for loop construct groups the index variable initialization, loop conditional, and index increment steps of the loop into one statement. So in order to convert a for loop into a while loop, you just need to unwrap this grouping into effectively three separate statements. In general, you can transform any for loop into a while loop using the following algorithm. Take a for loop like so:
for(A;B;C) { /* where A,B,C are valid C statements (e.g., X=0), not variables */
/* operational code */
}
To the following while loop using the same statements within the A, B, C placeholders:
A;
while(B) {
/* operational code */
C;
}
With this algorithm, you should be able to convert any for loop into a equivalent while loop.

I think this one is pretty simple. Maybe I misunderstood your situation, if then forgive me :)
My approach is like this:
var X = 1;
while (X<=100)
{
if(structure[X].number == -1)
{
structure[X].number = number;
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
if(structure[X].number == number)
{
if(structure[X].first_info == -1)
structure[X].first_info = position;
structure[X].second_info = position;
break;
}
X++;
}

Existing code can be converted into while as below
int x =1;
while(x!=100)
{
//Your code here
x++;
}

Related

Error C2360 Initialization of "arr2" is skipped by "case" tag

I am new to programming.
This is a C language program.
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdbool.h>
#define ture 1
#define false 0
void add(int m, int* arr,int n)
{
if (n == 32) return;
arr[n] += m;
if ( arr[n] > 1)
{
arr[n] = 0;
add(m, arr, ++n);
}
return;
}
int main(void)
{
int T,n,r,m,i,j,k;
bool check = ture;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &r);
switch (r)
{
case 10:
printf("%d", n);
break;
case 2:
int arr2[32] = { 0 };
if (n > 0)
{
for (i = 0; i < 32 ; i++)
{
arr2[i] = n % 2;
n = n / 2;
}
for (j = 31; j >= 0; j--)
{
if (arr2[j] == 0 && check == ture) continue;
else
{
check = false;
printf("%d", arr2[j]);
}
}
}
else if (n == 0)printf("%d", 0);
else if (n < 0)
{
n = -n;
for (i = 0; i < 32; i++)
{
arr2[i] = n % 2;
n = n / 2;
}
for (k = 0; k < 32; k++)
{
arr2[k] = !arr2[k];
}
add(1, arr2, 0);
for (j = 31; j >= 0; j--)
{
if (arr2[j] == 0 && check == ture) continue;
else
{
check = false;
printf("%d", arr2[j]);
}
}
break;
}
case 8:
int arr8[11] = { 0 };
if (n > 0)
{
for (i = 0; i < 11; i++)
{
arr8[i] = n % 8;
n = n / 8;
}
for (j = 10; j >= 0; j--)
{
if (arr8[j] == 0 && check == ture) continue;
else
{
check = false;
printf("%d", arr8[j]);
}
}
}
}
}
return 0;
}
When I run the program in VS2022.There is a bug.
Error C2360 Initialization of "arr2" is skipped by "case" tag Project5 C:\code\C\C_Single\Project5\Project5\test.cpp 74
I don't understand why this is happening.
In my opinion,when I select the contents of case8, I don't need the contents of case2, certainly,including the declaration of arr2.But obviously the compiler doesn't think that way.
So I turn to google for help.
However,google tells me something like this.
Your search - Error C2360 Initialization of "arr2" is skipped by "case" tag - did not match any documents.
Suggestions:
Make sure that all words are spelled correctly.
Try different keywords.
Try more general keywords.
Try fewer keywords.
So I want to get help in stackoverflow.Can anyone help me?
This is one reason that goto statements are frowned upon in modern code.
A case label is not much more that a regular label, and the switch will do something like:
if(value==2) goto label2;
if(value==3) goto label3;
etc.
But when you declare an array like:
int arr[10];
or actually any variable that goes on the stack, the compiler needs to increase the stack pointer to make space for that. in this case:
sp += 10 * sizeof(int)
(Of course this depends on your system/compiler etc)
So what happens if you put this piece of code, in between to (case) labels...
label2:
//int arr[10];
sp += 10*sizeof(int);
label3:
...
// end of scope for arr
sp -= 10*sizeof(int);
// or not?
Yeah it happens only half the time. So now you end up at the end of you switch statement, and your compiler doesn't know weather to decrease the stack pointer or not.
The compiler warns you that the initialization of the array arr2 can be skipped if the control will be passed to the label case 8:. In this case the array will have indeterminate values.
To avoid the compiler message just enclose statements after labels in braces creating a compound statement like for example
case 2:
{
int arr2[32] = { 0 };
//...
}
You have several problems here, within your switch(). (I'm just going to focus on that.)
Firstly, declaring variables within case clauses is problematic: providing them with initialisers, even more so. If you enclose the entire case clause within curly braces, that's a lot better. You also constrain the scope of your case-dependent variables to within that specific case.
Secondly, you have a significant logic error in your switch() statement. Your case 2: clause only hits a break in the n < 0 instance: in all others, it will fall through to case 8:. This is very clearly incorrect.
Thirdly, your case 8: clause has no break statement. As it's the last in the switch(), that's benign - you'll "fall out the bottom", but it's bad practice.
Finally, there is no default: clause. In just about every situation you use a switch() you want to catch the default: case, as it's either going to need a default handling, or it indicates an error condition.
In summary: brace your case clause code, so you can do as you with with, and scope, the variables you declare, and be rigorous about break and default: use. You'll thank me in the future!

Cycle through an array in either direction based on a bool

I'm looking for a method of looping through some array in either direction based on some passed bool value, with the same functionality as:
void Transfer(bool *_payload, int _size, bool _isLSB)
{
if (_isLSB)
{
for (int i = _size - 1; i >= 0; i--)
{
digitalWrite(dataPin, _payload[i]);
}
}
else
{
for (int i = 0; i < _size; i++)
{
digitalWrite(dataPin, _payload[i]);
}
}
}
or
void Transfer(bool *_payload, int _size, bool _isLSB)
{
int _index = 0;
if (_isLSB) _index = _size - 1;
for (;;)
{
printf("%d",_payload[_index]);
if (_isLSB) _index--;
else _index++;
if (_isLSB && _index < 0) break;
if (!_isLSB && _index >= _size) break;
}
}
Other than creating a method that reverses the array, is there a nice simplification of this?
You can define the starting and ending point and the increment conditionally:
void Transfer(bool *_payload, int _size, bool _isLSB)
{
int increment = _isLSB ? -1 : 1;
int i = _isLSB ? _size : -1; // one before the area to scan
int end = _isLSB ? -1 : _size; // one past the area
while ((i += increment) != end) // incr/decr before testing
{
digitalWrite(dataPin, _payload[i]);
}
}
We do not know in advance which way the index will be changing (incrementing or decrementing), so we can't use less-than or greater-than in the loop condition. And after processing the last item the index will be modified once more, hence the stopping point is one past the area being processed.
Similarly we need the starting point one position before the scanned area, so that after incrementing (or decrementing) the index we process the valid, first item.
You can calculate the direction and the start/end position for the for loop depending on _isLSB
void Transfer(bool* _payload, int _size, bool _isLSB) {
int dir;
int start;
int end;
if(_isLSB) {
dir = -1;
start = _size-1;
end = -1;
}else {
dir = 1;
start = 0;
end = _size;
}
for(int i = start; i != end; i+=dir) {
digitalWrite(dataPin, _payload[i]);
}
}
What you could do for example, since in C true and false are expanded to integer values in reality, is to use said integer value for calculations.
In the following example I will extract the main problem from your question which is: Looping over a size in a direction depending on a boolean value
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
int main()
{
int size = 5;
bool condition = false;
// Option #1
printf("Option #1\n");
for (int i = (size - 1) * condition; (i >= 0 && condition) || (i < size && !condition); i += 1 * pow(-1, condition))
{
printf("%d", i);
}
// Option #2
printf("\nOption #2\n");
int i = (size - 1) * condition;
for (;;)
{
printf("%d", i);
i += 1 * pow(-1, condition);
if ((i < 0 && condition) || (i >= size && !condition))
break;
}
return 0;
}
With the main function giving the following output for condition = true
Option #1
01234
Option #2
01234
And the following output for condition = false
Option #1
43210
Option #2
43210

Longest substring of correct parenthesis

I'm running into a bit of a problem. I have to compute the longest substring of correctly closed parenthesis and so far I've managed to do this:
while (work_stack.size != 0){
//I have a working stack in which I have stored the elements
//which in my case are brackets and while I have elements
//i pop the first element and see if it's a left or right
a1 = pop(&work_stack.data);
work_stack.size--;
if ('{' == ((Pair*)a1->info)->type ||
'(' == ((Pair*)a1->info)->type ||
'[' == ((Pair*)a1->info)->type) {
//if it's a left bracket, then I add it to the left stack
//which i'm going to use to compare with the right sided
//brackets i will encounter.
stanga++; //i'm incrementing the no of left brackets
if(ok == 0) //if there wasn't a match, then length is set to 0
length = 0;
if (ok == 1 && stanga > 1)
//if there was a match but then two brackets of left side
//are encountered, then length = 0
/*
Now I figured that here I am wrong. Given the input:
[][()()])())[][)]
The right value should be 8, but my code encounters
two left values and sets the length to 0. I need to
find a way to determine if the substring is worth keeping
*/
length = 0;
push(&left.data, a1);
left.size++;
}
if ('}' == ((Pair*)a1->info)->type ||
')' == ((Pair*)a1->info)->type ||
']' == ((Pair*)a1->info)->type){
//if it's a right bracket and there are elements in the left
//then i pop the first element fro the left stack and compare
//it to my current bracket
if(left.size != 0){
stanga = 0;
a2 = pop(&left.data);
left.size--;
//opposing is a function that returns 1 if
//i encounter something like ( ) or [ ] or { }
//if the brackets are opposed, i increment the length
if (oposing(((Pair*)a2->info)->type, ((Pair*)a1->info)->type) == 1){
length += 2;
ok = 1;
}
//otherwise, it seems that I have run into a stopping
//point, so I'm emptying the left stack because those
//paranthesis are not of use anymore and I'm saving
//the maximum length acquired by now
if (oposing(((Pair*)a2->info)->type, ((Pair*)a1->info)->type) == 0){
ok = 0;
while(left.size > 0){
a2 = pop(&left.data);
left.size--;
}
if(length > max){
max = length;
length = 0;
}
}
//if i haven't encountered a stopping point, i just
//compare the length to my max and save it if it's bigger
if (length > max)
max = length;
}
//this line says that if the size of the left stack is 0 and
//i have encountered a right bracket, then I can't form a
//correct substring, so the length is 0
else length = 0;
}
}
To note that: ((Pair*)a1->info)->type is my character.
Thank you!
Later Edit:
- I'm adding the structures for stack and Pair
typedef struct{
int id;
char type;
}Pair;
typedef struct cel{
void *info;
struct cel *urm;
}Celula, *TLista, **ALista;
typedef struct{
TLista data;
int size;
}stack;
My stack has the data type as a linked list but that shouldn't matter that much as the operations are correct (push and pop).
Edit: Added some new improvements to the code, as well as a new expalanation in comments as to what I'm doing. I identified the bug but I'm failing to find a solution for it.
This problem can be solved using stack. Here is my C++ implementation, hope you will feel no difficulty to understand the syntax and translate it into C.
int longestValidParentheses(string s) {
stack <int> Stack;
int maxLen = 0;
int lastPos = -1;
for(int i = 0; i < s.length(); ++i) {
if(s[i] == '(') {
Stack.push(i);
}
else {
if(Stack.empty()) {
lastPos = i;
}
else {
Stack.pop();
if(Stack.empty()) {
maxLen = max(maxLen, i - lastPos);
} else {
maxLen = max(maxLen, i - Stack.top());
}
}
}
}
return maxLen;
}
Sorry for the code rather than explanation as I am outside right now. I will put clarification if you need explanation on any part. For now, you can check with some input and pen-and-paper.

Better alternatives for switch statements

I know that this has been already discussed, and there are multiple answers to it. See Performance of array of functions over if and switch statements for instance, however I would like to get some other ideas.
I've got a function with a large switch statement. This is 26 case and each with a "left" or "right" option. This function returns a pointer based on two given parameters (plane and direction):
double* getPointer(int plane, int direction) {
switch (plane)
{
case 0:
if (direction == 0)
return p_YZ_L; // Left
else if (dir == 1)
return p_YZ_R; //Right
else {
return 0;
}
break;
...
case 25:
...
}
}
with
planes -> [0-25]
direction -> [0,1]
I have been thinking on an array of functions, but this could also be tedious and I am not sure if it is the best option. Also it is not clear to me how to do it properly. Any ideas?
You can create a lookup table like this:
double *pointers[26][2] = {
{ p_YZ_L, p_YZ_R },
...
};
Then your function becomes much simpler:
double* getPointer(int plane, int direction) {
if ((plane >= 0) && (plane < 26) && (direction >= 0) && (direction < 2)) {
return pointers[plane][direction];
} else {
return NULL;
}
}
If you are just tired of typing, yu can use the preprocessor, e.g.:
#define PLZ(dir) if(!dir)return(p_YZ_L);else if(dir==1)return(p_YZ_R);else return 0;
Not quite sure, but maybe you want this:
struct
{
double dir[2];
} directions[26] =
{
{ p_YZ_L, p_YZ_R},
{ ..., ... }, // 25 pairs of options here
...
};
double* getPointer(int plane, int direction) {
return &directions[plane].dir[direction];
}
More tests need to be added to be sure that plane and direction are within required bounds.
You can use while with an iterator as follows:
double* getPointer(int plane, int direction){
int i=0;
while (i<26){
if (plane == i){
if (direction == 0)
return p_YZ_L; //Left
else if(dir==1)
return p_YZ_R; //Right
else
return 0;
}
i++;
}
}
It is not optimized but it is less code with respect to your version.

Simplify/Neatify this two-way loop?

I've got my wires crossed somewhere (or I had not enough sleep). I need a two-way loop, and my current code is just plain ugly.
Problem: I am running along a linear datastructre using an index. I have an starting index, lets say 120. I want to run alternating into both directions.
Example:
120,121,119,122,118,123,117,...
I have a stopping criterion which needs to be met for each direction separately. If it is met for one direction, I only want to run into the other direction, if both are met I need to exit the loop. In addition I need to stop if the next index is invalid (end of data structure, say smaller than 0 or bigger than 200).
Example: Stopping execution at 116 backwards and 130 forward:
120,121,119,122,118,123,117,124,116,(break),125,126,127,128,129,130.
Running into one direction first, then the other one is unfortunately not an option.
My current code is plain ugly. It is a lot of lines without containing any "productive" code. Only iteration logic:
int start_idx = 120;
int forward_idx = start_idx;
int backward_idx = start_idx;
bool next_step_forward = true; //should next step be forward or backward?
int cur_idx;
while(backward_idx >= 0 || forward_idx >= 0)
{
if(next_step_forward //if we should step forward
&& forward_idx >= 0) //and we still can step forward
{
cur_idx = ++forward_idx;
if(forward_idx >= 200) //200 is fictive "max index"
{
next_step_forward = false;
forward_idx = -1; //end of data reached, no more stepping forward
continue;
}
if(backward_idx >= 0)
{
next_step_forward = false;
}
}
else if(!next_step_forward
&& backward_idx >= 0)
{
cur_idx = --backward_idx;
if(backward_idx < 0) //beginning of data reached, no more stepping backward
{
next_step_forward = true;
continue;
}
if(forward_idx >= 0)
{
next_step_forward = true;
}
}
else
{
next_step_forward = !next_step_forward; //ever hit?, just security case
continue;
}
//loop body
//do something with cur_idx here
if(stoppingCriterionMet())
{
if(cur_idx > start_idx)
{ //this was a forward step, stop forward stepping
forward_idx = -1;
}
else
{ //this was backward step, stop backward stepping
backward_idx = -1;
}
}
}
Am I missing anything? Any hints appreciated. Thanks.
Edit 1: There are lots of very nice answers, which put "do something with cur_idx" into a separate function. While this is a perfect idea for the way my question was asked, I prefer putting the iterating code somewhere else and leave the productive code there. I have a long algorithm and want to split it up after it is finished to minimize rearangement work.
How about this?
void do_loop(SomeType *arr, int start, int low, int high, int arr_max)
{
int downwardIndex, upwardIndex;
downwardIndex = upwardIndex = start;
while (downwardIndex > 0 && upwardIndex < arr_max) {
if (downwardIndex < low && upwardIndex > high) {
break;
}
if (downwardIndex > low) {
processElement(arr[downwardIndex]);
downwardIndex--;
}
if (upwardIndex < high) {
processElement(arr[upwardIndex]);
upwardIndex++;
}
}
}
It so happened that I coded almost this problem today. And I used a C# iterator function to do it. But I think you want a more generic solution.
If you use a language where you can build your own iterators (C++,Java,C#), it's easy. You just make a custom iterator that initially spits out numbers starting from the center. Then you give the iterator an extra function to tell it to stop running in the current direction.
If you're doing something like this in C (it looks C to me), you can mimic this with a struct containing the iterator state, and functions that you call to step it forward or stop it.
First pass at hacking this (assuming C - adaptations needed for other languages, but the concepts are basically language neutral):
void pass1(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
while (lo_x >= lo_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
}
while (hi_x <= hi_limit)
{
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
}
It is not clear what should happen if the starting position matches the stop criterion. Should the search stop altogether, or should it continue upwards, or downwards, or both ways. I chose 'stop altogether', but a case could be made for any of the options listed. In the case of 'both', you would not even bother to run the stop criterion check.
I also chose to do the lower before the upper direction; it is clearly trivially reversed. The order of the final two loops doesn't matter because if both directions terminate in the same iteration, neither trailing loop is executed; if only one direction is terminated, the corresponding loop won't execute at all - only the other will.
Since there is still repeated code in there:
void pass2(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process_lo(&lo_x, lo_limit);
Process_hi(&hi_x, hi_limit);
}
while (lo_x >= lo_limit)
Process_lo(&lo_x, lo_limit);
while (hi_x <= hi_limit)
Process_hi(&hi_x, hi_limit);
}
void Process_lo(int *lo_x, int lo_limit)
{
Process(*lo_x);
if (StopCriterion(*lo_x))
*lo_x = lo_limit - 1;
else
*lo_x--;
}
void Process_hi(int *hi_x, int hi_limit)
{
Process(*hi_x);
if (StopCriterion(*hi_x))
*hi_x = hi_limit + 1;
else
*hi_x++;
}
Visibility controls (static functions) etc left out as details of the implementation language.
This is how I'd approach it in C#:
const int UPPER_BOUND = 200;
const int LOWER_BOUND = 0;
const int START = 120;
bool foundlower = false, foundupper = false;
int upper, lower;
upper = lower = START;
while (!foundlower || !foundupper) {
if (!foundlower) {
if (--lower <= LOWER_BOUND) foundlower = true;
if (stoppingCriterionMet(lower)) foundlower = true;
}
if (!foundupper) {
if (++upper >= UPPER_BOUND) foundupper = true;
if (stoppingCriterionMet(upper)) foundupper = true;
}
}

Resources