This program displays certain messages when some of the elements are 'y' or if all of the elements are 'n'.
My question is about this line: someElements |= array[i] == 'y'.
I understand that it can be written in this way: someElements = someElements | array[i] == 'y'.
I'm just asking for an explanation why does it work?
#include <stdio.h>
int main()
{
char array[3] = { 0 };
int i;
for (i = 0; i < 3; i++) {
do {
printf("\nElement No.%d [y/n]: ", i + 1);
scanf(" %c", &array[i]);
if (array[i] != 'y' && array[i] != 'n') {
printf("Must be a lowercase 'y' or 'n'\n");
}
} while (array[i] != 'y' && array[i] != 'n');
}
int someElements = 0;
for (i = 0; i < 3; i++) {
someElements |= array[i] == 'y';
}
if (someElements) {
printf("\nSOME of the elements = y.\n");
}
else{
printf("\nNONE of the elements = y.\n");
}
return 0;
}
Code link
The result of array[i] == 'y' is a boolean true or false. It can be implicitly converted to the int value 1 or 0 (respectively).
Then it's easy to create a bitwise OR table for the possible combinations of someElements | array[i] == 'y':
someElements
array[i] == 'y'
someElements | array[i] == 'y'
0
0
0
0
1
1
1
0
1
1
1
1
So if any of the values are 1 then the result will be 1.
From this follows that if any of the characters in the array is equal to 'y' then the end result of someElements after the loop will be 1. Which then can be implicitly converted back to a boolean true in the following if condition.
Bitwise OR:
Returns true if either bit is true.
Truth table:
A | B | A | B
-------------
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 1
From this, we can conclude that
someElements = someElements | array[i] == 'y;
as someElements has been initialized with 0, or false, it will remain false until array[i] = 'y' returns 1, or true.
Aside: On the last iteration, i + 1 would access out of bounds memory.
The key insight is for a given binary value x:
0 | x == x
1 | x == 1
We initialize the variable someElemenets to 0 (false) so we are in the first case. someElemenets will remain 0 till we encounter an 'y' in the array. It now becomes 1 and will remain so irregardless of the remaining input. Think of it as a one-way (light) switch.
You could just terminate the loop early instead:
someElements = 0;
for (i = 0; i < 3 && !someElements; i++) {
someElements = array[i] == 'y';
}
and it even clearer if you write it as a function:
int any_y(size_t n, const char array[n]) {
for(size_t i = 0; i < n; i++)
if(array[i] == 'y') return 1
return 0
}
which is specialization of memchr():
someElements = memchr(array, 'y', 3);
Related
I am trying to write a C program that takes a string input from a user and then looks into the input to count the frequency of all the integers in the string. So suppose if the user gives the input:
a11472o5t6
the output would be :
0 2 1 0 1 1 1 1 0 0
my approach involves comparing every character of the string to all 10 digits one by one and if any the character is equal to the digit, it would increment the isdigit number by 1.
the code I wrote for the same is as follows:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int is1 = 0; //initialise integers for checking
int is2 = 0;
int is3 = 0;
int is4 = 0;
int is5 = 0;
int is6 = 0;
int is7 = 0;
int is8 = 0;
int is9 = 0;
int is0 = 0;
int main()
{
char s[100]; //initialise array for string
scanf("%s", s); //scan string input
//now all characters of the string are stored in the array s
for (int i = 0; i < strlen(s); i++) //loop to iterate over all the elements in the array
{
if (strcmp(&s[i], "0") == 0)
{
is0 = is0 + 1;
}
if (strcmp(&s[i], "1") == 0)
{
is1 = is1 + 1;
}
if (strcmp(&s[i], "2") == 0)
{
is2 = is2 + 1;
}
if (strcmp(&s[i], "3") == 0)
{
is3 = is3 + 1;
}
if (strcmp(&s[i], "4") == 0)
{
is4 = is4 + 1;
//printf("%d", is4);
}
if (strcmp(&s[i], "5") == 0)
{
is5 = is5 + 1;
}
if (strcmp(&s[i], "6") == 0)
{
is6 = is6 + 1;
}
if (strcmp(&s[i], "7") == 0)
{
is7 = is7 + 1;
}
if (strcmp(&s[i], "8") == 0)
{
is8 = is8 + 1;
}
if (strcmp(&s[i], "9") == 0)
{
is9 = is9 + 1;
}
}
printf("%d ", is0);
printf("%d ", is1);
printf("%d ", is2);
printf("%d ", is3);
printf("%d ", is4);
printf("%d ", is5);
printf("%d ", is6);
printf("%d ", is7);
printf("%d ", is8);
printf("%d ", is9);
}
I expected the code to iterate over and over for the entire length of the string and and update values of the isdigit series every time a number was successfully found. However whenever I run the code only the last digit seems to find its place in the output .
for example if I type 54 as an input the expected output is
0 0 0 0 1 1 0 0 0 0
however the output my code seems to be giving is
0 0 0 0 1 0 0 0 0 0
likewise the number 45 also has the same expected output
0 0 0 0 1 1 0 0 0 0
but the output I am receiving is
0 0 0 0 0 1 0 0 0 0
which looks like the code overwrites any operation that occurred in the previous iteration, but I can't seem to understand why and how to fix it.
On my part I checked if the characters were being called properly one by one and that all characters were being compared, where I found no problem. I also looked up other answers on stack overflow and elsewhere, but was I am a beginner and most answers were written in reference to languages that I can't understand, so I was unable to relate to the solution they were being told. the closest I got was someone who was using a single variable repetitively thus overwriting it in each iteration. however I have declared sufficient variables( one for each digit from 0-9), so that shouldn't be the problem in my code either.
while I know this question could be solved easily using arrays, I would like to know what I was doing wrong here to avoid any such mistakes in the future.
When you do if (strcmp(&s[i],"1")==0) you are comparing strings, not individual characters, which is why only the last character is counted. It's the only one matching.
Example:
If s == "a11472o5t6" and you use strcmp(&s[1], "1"), you would be comparing the string "11472o5t6" with the string "1", which clearly will not be equal.
You want if(s[i] == '1') etc. to do the comparisons of individual characters instead.
And you are correct about using arrays instead. It'd certainly be easier.
Example:
#include <ctype.h>
#include <stdio.h>
int main() {
const char *str = "a11472o5t6";
int ints[10] = {0};
for (const char *chptr = str; *chptr != '\0'; ++chptr) {
if(isdigit((unsigned char) *chptr)) ++ints[*chptr - '0'];
}
for (int i = 0; i < 10; ++i) printf("%d %d\n", i, ints[i]);
}
Output:
0 0
1 2
2 1
3 0
4 1
5 1
6 1
7 1
8 0
9 0
This is kind of strange, imo, I have a for loop that does a comparison
using the return value from a function.
for (size_t i = 0; i < func(val); i++) {
printf("Value from array modified in func = %u", values[i]);
}
The issue is the loop seems to run before the function is finished, if have a printf in the called function some output occurs before the output of the loop, expected, and some after, not expected. The function is only called in the for loop comparison so output should all happen before for loop's output. If I use a var instead such as:
size_t temp = func(val);
for (size_t i = 0; i < temp; i++) {
printf("Value from array modified in func = %u", values[i]);
}
Then everything works correctly, this is rather odd to me, I'm not using threads so this should all be synchronus right? So why would the loop not wait for func(val) to return?
Here's the original code (cutting out a bunch of comments):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdlib.h>
#define SUITS 4
#define FACES 13
#define CARDS 52
#define HAND 5
typedef struct {
unsigned int suit;
unsigned int face;
} card;
size_t checkX(card hand[HAND], unsigned int faces[HAND], unsigned int num);
int main() {
card hand[HAND] = {{1,1},{1,7},{1,1},{1,4},{1,7}};
const char *suit[SUITS] = {"Hearts", "Diamonds", "Clubs", "Spades"};
const char *face[FACES] = {"Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
unsigned int matchingFaces[HAND] = {0};
for (size_t i = 0; i < checkX(hand, matchingFaces, 2); ++i) {
printf("Pair of %s%s\n", face[matchingFaces[i]], matchingFaces[i] == 5 ? "es" : "s");
}
}
size_t checkX(card hand[HAND], unsigned int faces[HAND], unsigned int num) {
size_t facePos = 0;
for (size_t i = 0; i < HAND - 1; i++) {
size_t count = 1;
for (size_t j = i + 1; j < HAND; j++) {
printf("%u == %u && %u != %u\n", hand[i].face, hand[j].face, hand[i].face, faces[facePos]);
if (hand[i].face == hand[j].face && hand[i].face != faces[facePos]) count++;
}
faces[facePos] = hand[i].face;
if (count == num) facePos++;
}
return facePos;
}
Some of this isn't my code, I was given a basic card shuffling type of program and told to modify it to deal a hand and check for pairs/three of a kind. Like I said this does work when I set the return value of checkX as a variable and then compare i to that instead of directly, I just don't know why. I've tried disabling gcc optimization, which didn't seem to make a difference.
Output from direct func comparison:
1 == 7 && 1 != 0
1 == 1 && 1 != 0
1 == 4 && 1 != 0
1 == 7 && 1 != 0
7 == 1 && 7 != 0
7 == 4 && 7 != 0
7 == 7 && 7 != 0
1 == 4 && 1 != 0
1 == 7 && 1 != 0
4 == 7 && 4 != 1
Pair of Deuces
1 == 7 && 1 != 1
1 == 1 && 1 != 1
1 == 4 && 1 != 1
1 == 7 && 1 != 1
7 == 1 && 7 != 1
7 == 4 && 7 != 1
7 == 7 && 7 != 1
1 == 4 && 1 != 7
1 == 7 && 1 != 7
4 == 7 && 4 != 1
Output from indirect comparison of func using variable:
1 == 7 && 1 != 0
1 == 1 && 1 != 0
1 == 4 && 1 != 0
1 == 7 && 1 != 0
7 == 1 && 7 != 0
7 == 4 && 7 != 0
7 == 7 && 7 != 0
1 == 4 && 1 != 0
1 == 7 && 1 != 0
4 == 7 && 4 != 1
Pair of Deuces
Pair of Eights
I know this code isn't the nicest but I had to work with what was given and just need to make it work, so this question is just out of curiosity.
for (size_t i = 0; i < func(val); i++) {
printf("Value from array modified in func = %u", values[i]);
}
func(val) gets called multiple times here, each time a decision needs to be made whether to continue the loop or not, you can picture it as
size_t i = 0;
if (i < func(val)) {
printf(.....);
i++;
if (i < func(val)) {
printf(.....);
i++;
if (i < func(val)) {
printf(.....);
i++;
if (i < func(val)) {
printf(.....);
i++;
....and so on......
}
}
}
}
So you can see, func(val) may get called multiple times.
A rather good, but a little out of date, section of the great book "The C Programming Language", by Kernighan and Ritchie, re-state a for loop to the equivalent:
{
size_t i = 0;
while (i < func(val)){
printf("Value from array modified in func = %u", values[i]);
i++;
}
}
(The outer braces are mine and are necessary since you can now declare a variable inside the first "expression" in the for loop.)
If you write the loop this way, it's plain to see that func(val) is re-evaluated on each iteration. That is what is causing the effects you observe. (Note that not all languages do this, VBA and VB6 are two examples where the end condition of the for loop is not re-evaluated.)
Because of this, if func(val) is an expensive function and your algorithm doesn't require repeated evaluation, you might want to consider pre-computing the value in advance. Some compilers may optimise out the re-evaluation especially if you are using a standard function like strlen for example, but such an optimisation is a very tricky science.
What I want the program to do is to evaluate the 2 consecutive integers after another in a set of array, then convert these integers to a corresponding character.
For example, if I have array[10] = {4 2 3 2 5 3 5 3 6 3}, the first 2 ints 4 2 will be converted into "H", 3 2 = E, 5 3 = L and so on until it prints the word HELLO. The program should accept a list of integers.
This is what I've done so far..
#include <stdio.h>
#include <stdlib.h>
int main() {
int i=0, j=0, k=0;
int array[1000];
char space;
printf("Input integers to convert into a string: ");
do {
scanf("%d%c", &array[i], &space);
i++;
} while(space != '\n');
for(/*what should I include here?*/)
if (array[0] == 2 && array[1] == 1)
printf("A");
else if (array[0] == 2 && array[1] == 2)
printf("B");
/* and so may else ifs*/
}
Something like this should work. Instead of going through the for loop one int at a time, it would probably be best to do two at a time.
for(int i = 0; i < 1000; i += 2){
if (array[i] == 2 && array[i + 1] == 1)
printf("A");
else if (array[i] == 2 && array[i + 1] == 2)
printf("B");
/* and so may else ifs*/
}
I would create a function that converts the integers to the characters.
char int_to_char(int val)
{
if(val == 21)
return 'A';
if(val == 22)
return 'B';
if(val == 42)
return 'H';
if(val == 32)
return 'E';
if(val == 53)
return 'L';
if(val == 63)
return 'O';
// I don't see you pattern, so I don't know which value
// is which character
return '?';
}
I don't see your pattern here.
Then your loop would look like:
// i is the number of entered values
// making sure that the end condition is even
for(int j = 0; j < i&1 ? i - 1 : i; j += 2)
{
printf("%c", int_to_char(array[j] * 10 + array[j+1]));
}
This would print HELLO with the input 4 2 3 2 5 3 5 3 6 3.
Suppose there is an array with 0, 1 and 5 in it. 5 can be replaced by either 0 or 1. How to find the length of longest continuing character?
Suppose array is 051. In this case we can replace 5 by 0 or 1. So it will become 001 or 011. In both the cases the length of longest continuing character is 2.
Suppose if array is 0511 now 5 has to be replaced with 1 to get longest continuing character in 0111. If 5 is replace by 0 we get 0011 and longest continuing character becomes 2, this is less than 3. Therefore length of longest continuing character is 3.
3. This has to be done in one iteration of array
Some Examples:
INPUT: 15015001. OUTPUT: 3
Explanation: 15015001 -> 11010001 -> we have 3 zeros together so length of longest continuing character is 3.
Please let me know if you need more details.
Check each character:
If it's a 0, increment my zero-counter and set my one-counter to 0
If it's a 1, increment my one-counter and set my zero-counter to 0
If it's a 5, increment both my zero-counter and my one-counter
Check the value of both counters. If either of them is greater than the current value of my longest-set , then update my longest-set to that value.
int getLongestContinousCharLength(int[] array) {
int count0 = 0;
int count1 = 0;
int maxCount1 = 0;
int maxCount0 = 0;
int i = 0;
while (i < array.length) {
if (array[i] == 0) {
count0++;
count1 = 0;
if (count0 > maxCount0)
maxCount0 = count0;
} else if (array[i] == 1) {
count1++;
count0 = 0;
if (count1 > maxCount1)
maxCount1 = count1;
} else {
count0++;
if (count0 > maxCount0)
maxCount0 = count0;
count1++;
if (count1 > maxCount1)
maxCount1 = count1;
}
i++;
}
return maxCount0 > maxCount1 ? maxCount0 : maxCount1;
}
I am supposed to make a dice game that plays multiple times. I am not really looking for the answer, kind of looking to see what I am doing wrong. I would expect the for loop to assign the int i a value of 0, then run the dice rolls, then add one to i, until i is > 50. Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
main(){
int rollDie1, rollDie2, keyValue = 0, win = 0, lose = 0, reroll = 0, i;
srand(time(NULL)); // call this only once – seed the random generator
for (i = 0 ; i < 50 ; i++);
{
rollDie1 = rand() % 6 + 1; // in the range of 1 - 6
rollDie2 = rand() % 6 + 1; // in the range of 1 - 6
keyValue = rollDie1 + rollDie2;
if ( keyValue == 7 || keyValue == 11 )
{
printf ("Player wins on the first roll \n");
}
if ( keyValue == 2 || keyValue == 3 || keyValue == 12 )
{
printf("Sorry, you lost on the first roll \n");
}
if ( keyValue == 4 || keyValue == 5 || keyValue == 6 || keyValue == 8 || keyValue == 9 || keyValue == 10 )
{
printf("Reroll! \n");
}
}
system("pause");
}
There's a ; at the end of the for loop that shouldn't be there.
for (i = 0 ; i < 50 ; i++);
should be
for (i = 0 ; i < 50 ; i++)
otherwise there is nothing in the for-loop and what's in the {} will only be executed once, as that's a separate statement.
You have a semicolon at the end of the loop:
for (i = 0 ; i < 50 ; i++);
So it does nothing 50 times. You simply need to remove the semicolon so that your brackets {} will actually encapsulate the lines of your code that are supposed to be in the for loop. If you don't have an open bracket { immediately following a for loop, the first complete statement following the for loop will be executed at each iteration. The semicolon is a complete statement that does nothing.
Actually it will run as long as i<50 which is from 0 to 49