Whats happening in this for loop - c

whats happening in the first statement of the for loop? I can not seem to wrap my head around why 1 == 2 would be acceptable because its a comparison and not a value assignment.
char ch = 120;
unsigned char x = 1;
unsigned int y = 1;
for(1 == 2; ch > 0; ch++) {
printf("%d\n", ch);
x <<= 1;
y *= 2;
}

It is just a useless statement that the compiler will optimize away. The first statement in the for does not need to be an assignment, it is just build to be succinct/readable way to loop over a set of values. You can expand the for loop into a while and it may make it clearer:
1 == 2; // does nothing, likely emits compiler warning.
while( ch > 0 )
{
printf("%d\n", ch);
x <<= 1;
y *= 2
ch++;
}
If you want to use a for loop for the post iteration expression but have already initialized your variables, you can use the null statement as the first expression:
for( ; ch > 0; ch++ ){ /* ... */ }

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!

converting binary to multiple characters

I basically posted this question yesterday, but I'm running into a different type of error. So I'm trying to create a program where the user enters a 12-bit binary hamming code sequence like "100010010001" and it should print out its corresponding ASCII character, which in this case is 'A'.
The problem is it seems to work for single characters like 'A' but if I type the binary sequence 100010010001010110010010010010000011 which represents 'ABC' it prints out random characters unrelated to what should be printed out. I don't understand what's causing this problem?
char charToBin(char usersInput[]) {
char j = 0 ;
for (int i = 0; i <= 12 ; i++) {
if((i == 0) || (i == 1) || (i == 3) || (i == 7)){
continue ;
} ;
usersInput[j] = usersInput[i] ;
j++ ;
} ;
char c = strtol(usersInput, (char **)NULL, 2);
return c;
}
You should try my answer to that question of your yesterday. That solution will work and the first method should be really fast if you trying to break up the array into steps because it is a small array.
Nonetheless, for this code, the main problem that you have with your code is that you are trying to remove 4 indexes from a char array of 12 indexes without doing anything to tell strtol() that. So in your code, you only have to tell strtol() to stop at index 8 by injecting char '\0' at position 8 or the array which would be the 9th char. Also, since you are going to skip index 0 and 1, there is no point starting from index 0 and evaluating whether if it is index 0 or 1. You can start at index 2. Besides that, "i" should be less than 12 in your loop. That is because the last index of a 12 indexes array would be 11, and not 12. Also, j does not need to be a char. That should be an int.
char charToBin(char usersInput[]) {
int j = 0 ;
for (int i = 2; i < 12 ; i++) {
if( (i == 3) || (i == 7) ){
continue ;
} ;
usersInput[j] = usersInput[i] ;
j++ ;
} ;
usersInput[8] = '\0';
char c = strtol(usersInput, (char **)NULL, 2);
return c;
}
You must provide more info about your program like fully functional main(), example input and outputs, how to call the functions and etc.
But before that i think Same code like this may works for you.
p = len of usersInput / 12
char * charToBin(char usersInput[], int p) {
char j = 0 ;
char *c;
for(int n=0;n<p;n++){
for (int i = 0; i <= 12 ; i++) {
if((i == 0) || (i == 1) || (i == 3) || (i == 7)){
continue ;
} ;
usersInput[j+n] = usersInput[i+n] ;
j++ ;
} ;
c[n] = strtol(usersInput, (char **)NULL, 2);
}
return c;
}
Your for() loop should only iterate for 12 times,hence the condition should be i<12 and create a local character array as I did(to_Char[]) of length 9(8+1 for Null at end) and read appropriate bits into it from usersInput[], usersInput[] shouldn't be provided as input to strtol() as its of 32bits in length but our characters are just 8bits in length.
char charToBin(char usersInput[]) {
char j = 0;
char to_Char[9];
for (int i = 0; i < 12; i++) {
if ((i == 0) || (i == 1) || (i == 3) || (i == 7)) {
continue;
};
to_Char[j] = usersInput[i];
j++;
};
to_Char[j] = '\0';
char c = strtol(to_Char, (char**)NULL, 2);
return c;
}

Nested for loop isn't iterating

I'm trying a K and R exercise. The program is to compare two strings. If the first string has any characters that are also in string 2 then it will be deleted in string1.
The goal of my compare function below is to compare every array element in the first string with every array element in the second string. If we've got a match then we "raise a red flag" (acting as a boolean value) and we DON'T add it to the new array that will contain the edited string1. However it seems to be ignoring the second for loop. It only passes through on the k = 0 iteration for every i iteration. My other issue is that based on the output (provided beneath node) it seems that s1[i] is being assigned to s2[k]. I'm guessing this takes place in the if statement but how would that be possible? Any help anyone could provide would be very appreciated.
I used the GNU GCC compiler if it makes a difference.
#include <stdio.h>
int getLength(char s[]);
char compare(char s1[], char s2[],int s1Length, int s2Length);
int main()
{
char stringOne[] = {'a','b','c','d','e'};
char stringTwo[] = {'P','f','g','c','t','y','u','o','z'};
int lengthOne;
int lengthTwo;
lengthOne = getLength(stringOne);
char theResultingString[lengthOne];
lengthTwo = getLength(stringTwo);
compare(stringOne, stringTwo, lengthOne, lengthTwo);
return 0;
} //end of main.
int getLength(char s[]) //getLength gives us the length of each and every string
{
int i=0;
for(i = 0; s[i]!='\0'; i++) {
} //end for loop
return i;
} //end of getLength
char compare(char s1[], char s2[],int s1Length, int s2Length)
{
int redFlagRaised = 0; //This will be used as a boolean indicator if we have a matching element
char toBeReturned[s1Length];
int i;
int k;
for(i = 0; i<s1Length; i++) {
printf("i is now %d\n",i);
for(k = 0; k<s2Length; k++) {
printf("k is now %d\n",k);
if(s1[i] = s2[k]) { //If at any point the s1 char being examined equals any of s2 chars then
printf("s1[i] is %c\n",s1[i]);
printf("s2[i] is %c\n",s2[i]);
redFlagRaised = 1; //we raise the red flag!
} //end first inner if statement
if((k=(s2Length-1))&&(redFlagRaised = 0)) { //if we reach the end and we DON'T have a red flag then
toBeReturned[i] = s1[i];
printf("toBeReturned[0] is %c\n",toBeReturned[0]);
} //end second inner if statement
} //end inner for loop
redFlagRaised = 0; //We lower the flag again for the next inner for loop iteration
} //end outer for loop
printf("The result is %c", toBeReturned[0]);
return toBeReturned[0];
} //end of compare
Output:
i is now 0
k is now 0
s1[i] is P
s2[i] is P
i is now 1
k is now 0
s1[i] is P
s2[i] is f
i is now 2
k is now 0
s1[i] is P
s2[i] is g
i is now 3
k is now 0
s1[i] is P
s2[i] is c
i is now 4
k is now 0
s1[i] is P
s2[i] is t
i is now 5
k is now 0
s1[i] is P
s2[i] is y
The result is �
Process returned 0 (0x0) execution time : 0.005 s
Press ENTER to continue.
char stringOne[] = {'a','b','c','d','e'};
char stringTwo[] = {'P','f','g','c','t','y','u','o','z'};
These are not strings. You need to terminate them using null character.
Try this -
char stringOne[] = {'a','b','c','d','e','\0'};
char stringTwo[] = {'P','f','g','c','t','y','u','o','z','\0'};
Also in this condition-
if(s1[i] = s2[k])
use == instead of =(this is assignment operator).So condition should be written as -
if(s1[i]==s2[k])
Similarly in this condition (as mentioned by Weather Vane Sir in comment)if((k=(s2Length-1))&&(redFlagRaised = 0)) use ==
if((k==(s2Length-1))&&(redFlagRaised == 0))
In compare function in IF condition you are assigning the value to K like bleow
if((k=(s2Length-1))&&(redFlagRaised = 0)){ //if we reach the end and we DON'T have a red flag then
toBeReturned[i] = s1[i];
printf("toBeReturned[0] is %c\n",toBeReturned[0]);
}
But it's needs to be like this
if((k==(s2Length-1))&&(redFlagRaised == 0)){ //if we reach the end and we DON'T have a red flag then
toBeReturned[i] = s1[i];
printf("toBeReturned[0] is %c\n",toBeReturned[0]);
}
You have to use Compare operator (==) not assignment operator(=)
In below code
char stringOne[] = {'a','b','c','d','e'};
char stringTwo[] = {'P','f','g','c','t','y','u','o','z'};
These are not strings. You need to terminate them using null character. Try this -
char stringOne[] = {'a','b','c','d','e','\0'};
char stringTwo[] = {'P','f','g','c','t','y','u','o','z','\0'};
Below also use this == operator instead of = operator
if(s1[i] = s2[k])

Finding the most frequent character in a file in C

I'm writing a function that finds the most common alphabetic character in a file. The function should ignore all characters other than alphabetic.
At the moment I have the following:
int most_common(const char *filename)
{
char frequency[26];
int ch = 0;
FILE *fileHandle;
if((fileHandle = fopen(filename, "r")) == NULL){
return -1;
}
for (ch = 0; ch < 26; ch++)
frequency[ch] = 0;
while(1){
ch = fgetc(fileHandle);
if (ch == EOF) break;
if ('a' <= ch && ch <= 'z')
frequency[ch - 'a']++;
else if ('A' <= ch && ch <= 'Z')
frequency[ch - 'A']++;
}
int max = 0;
for (int i = 1; i < 26; ++i)
if (frequency[i] > frequency[max])
max = i;
return max;
}
Now the function returns how many times the most frequent letter occurred, not the character itself. I'm a bit lost, as I'm not sure if that's the way this function should look like at all. Does it make sense and how possibly can I fix the problem?
I would really appreciate your help.
The variable frequency is indexed by the character code. So frequency[0] is 5, if there have been 5 'a's.
In your code you are assigning the count to max, not the character code, so you're returning the count not the actual character.
You need to store both the maximum frequency count and the character code that it referred to.
I would fix this with:
int maxCount = 0;
int maxChar = 0;
// i = A to Z
for (int i = 0; i <= 26; ++i)
{
// if freq of this char is greater than the previous max freq
if (frequency[i] > maxCount)
{
// store the value of the max freq
maxCount = frequency[i];
// store the char that had the max freq
maxChar = i;
}
}
// character codes are zero-based alphabet.
// Add ASCII value of 'A' to turn back into a char code.
return maxChar + 'A';
Note that I changed int i = 1 to int i = 0. Starting at 1 would mean starting at B, which is a subtle bug you might not notice. Also, the loop should terminate at <= 26, otherwise you'd miss out Z too.
Note the braces. Your braces style (no braces for single-statement blocks) comes very highly un-recommended.
Also, i++ is more common than ++i in cases like this. In this context it will make no difference, so would advise i++.

Varying arguments for if () statement

I have a problem as stated below:
i have an array(say) a[]={10,24,56,33,22,11,21}
i have something like this
for(i=0;i<100;i++){
if(a[i]==10)
// do something
}
next when i=1
if(a[i]==10 && a[i+1]==24)
so on so at each iteration the arguments / conditions within if should be varying
now this will be a very big sequence i cant explicitly write
if(a[i]==10 && a[i+1]==24 && a[i+2]==56 ...... a[i+100]=2322)
how can i achieve this varying conditions?
You have to have a cumulative "boolean" variable that checks a[i] at the i-th iteration and update that variable:
int a[] = {...}; /* array with some values to verify */
int v[] = {...}; /* these are the actual desired values in a[] */
/* the verifying loop */
int i;
int cond = 1;
for (i = 0; i < 100; i++)
{
cond = cond && (a[i] == v[i]);
if (cond)
{
/* do something */
}
}
I think that you should introduce a boolean value.
bool valid = true;
for(i=0;i<100;i++){
if(a[i]==10 && valid)
// do something
else
{
valid = false;
break;
}
}
For every iteration, you need to change the value to which you are comparing a[i]
Have a loop within a loop:
for (i = 0; i != 100; ++i)
{
int condition = 1;
for (j = 0; i + j != 100 && condition; ++j)
{
condition = condition && (a[i + j] == /* your number */ );
}
if (condition) { /* ... */ }
}
In this case, you can use function pointers or blocks.
You can find a good example here here
Seeing your examples, I think that the variations you are talking about is only in the length of array 'a' whose presence you want to check in some array x. If indeed it is so, memcmp can be of use to you.
Let me modify your example a bit to clarify what I am saying.
int a[7]={10,24,56,33,22,11,21} is the required values you want to check in some array 'x', with different lengths of 'a' each time, with 'x' declared as
int x[1000];
In that case, you could use memcmp as follow :-
for ( len = 1 ; len <= 7 ; ++len )
{ for ( i = 0 ; i <= 1000-len ; ++i )
{ if ( ! memcmp( a, x+i, len * sizeof(int) ) )
{ // do something
}
}
}

Resources