What is wrong with my loop? I've tried everything - c

I'm doing a final project right now and I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
int main(void){
int day;
int year;
int month;
int daynum=0;
int days=365;
printf("\nPlease input what year you would like to meet\n");
scanf("%d",&year);
printf("\nPlease input what month you would like to meet\n");
scanf("%d",&month);
printf("\nPlease input what day you would like to meet\n");
scanf("%d",&day);
//Later in the code i have the following loop
int k=month;
do {
k--;
switch (k) {
case 0:
case 2:
case 4:
case 6:
case 7:
case 9:
case 11:
daynum=daynum+31;
printf("\nadded 31");
break;
case 1:
if (days==365) {
daynum=daynum+28;
}
else if (days==366) {
daynum=daynum+29;
}
printf("\nadded 28/29");
break;
case 3:
case 5:
case 8:
case 10:
daynum=daynum+30;
printf("\nadded 30");
break;
default:
printf("\nsomething went wrong");
}
}while(k>=0);
return 0;
}
I've tried essentially the same thing with a while and for loop but every time the only thing that shows up in the console is something went wrong. I even tried checking the value of k before the loop and it says it is equal to month. I've also tried setting k equal to a number and it works just fine with that, but i need it to equal month. I really have no idea whats wrong and any help would be appreciated.

The problem is that you're decrementing k at the beginning of the loop body, but checking it at the end of the loop. So on the last iteration you'll decrement it to -1, print the error message, and then stop the loop.
Change the condition to while(k > 0).

Well, I believe you now know the error as #Barmar wrote.
Anyway I add:
always, I mean always, check for the return of scanf(): there is no point in letting the program go if some of the values are not read. scanf() always returns the number of specifiers read, that things that starts with a single %. In your case it will be 1, 0 or -1.
about this
do {
k--;
switch (k) {
you can always switch(--k) with the same effect.
you could state the purpose of the code and provide at least one test value. If you are trying to get the number of days up to and including the user supplied one, you could have made it clear. I was just guessing.
note that Excel or Google sheets can operate on dates so it is a good free reliable check point.
a small change on the default label, like
printf("\n==> daynum is %d, k is %d and something went wrong\n", daynum, k);
would have print
==> daynum is 365, k is -1 and something went wrong
and it would be very helpful. Far better than just write something went wrong. make your program work for you.
you do not need a switch to compute always the same values. Use a table. And as the only change in days is in February just add the extra day there as we always do...
char days_in_month[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
days_in_month[1] += ( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0; // 1 or 0
use the command line for the arguments. It is a bit boring enter the program name and then 3 parameters in 3 lines just to see a resulting number.

Honestly have no idea what was the issue with my code, but i moved this section of code further up and its working as intended now. Somewhere months was getting reset to 0 before the loop despite this being the first time i referenced it besides in printf statements. thank you to #dbush who helped me find out the issue.

Related

Alternative function to (switch without break)

#include <stdio.h>
void main(void)
{
int price;
scanf("%d", &price);
switch (price)
{
case 1000: // what i want - case pay >= 1000
// code (no break - intentional)
case 500: // ....... - case pay >= 500
// code
default:
break;
}
}
I'm new to this. Is there any alternative to switch without break and also able to use comparisons, not constant, in a switch?
Just series of if statements then :
if (price >= 1000) {
// do something
}
if (price >= 500) {
// do some more stuff
}
You may also want to use #define for those magic numbers (1000, 500 ...). Or Enumerate them using enum.
Although switch() looks like a function, it's a statement block.
As others have said, this problem is better suited to consecutive if blocks than to a switch statement (where the use of deliberate fall-through is frowned-upon by many in the C programming world).
However, if you want to divide a number into ranges of fixed-size blocks (in your case, that size is 500), then you can divide your number by that block-size and use the result as the switch variable. Also, note that the default case doesn't have to be the final case – it can be anywhere, even first.
In the below example, because of the fall-through (i.e. no break; statements in any of the case blocks), the case 0: code will be run for any input; for inputs less than 500 (i.e. the integer division will result in 0), only that case will execute. For numbers in the range 500 thru 999 (division will give 1), the case 1 and case 0 code will run; and, for numbers >= 1000, the default case will run, followed by the other two blocks. (This code requires a positive value for price!)
#include <stdio.h>
int main(void)
{
int price = 0;
printf("Price: ");
int s = scanf("%d", &price);
if (s != 1 || price < 0) {
printf("Invalid price!\n");
}
else {
switch (price / 500) {
default:
printf("Price is >= 1000!\n");
case 1:
printf("Price is >= 500\n");
case 0:
printf("Price is anything\n");
}
}
return 0;
}
As I have said, I would generally not recommend using a switch in cases (poor pun) like this; but, that advice notwithstanding, it is then actually quite easy to add extra blocks/conditions, such as code for prices in the 1000 - 1499 range, where you could just insert a case 2: block to the code. Furthermore, when the number of 'ranges' becomes sufficiently large (say, more than 3), then it does arguably become clearer to use such a switch, rather than a chain of if statements/blocks.
Note: For added clarity – if your compiler supports it (clang and gcc do but I'm not aware of an equivalent for MSVC) – then you can add __attribute__((fallthrough)); statements wherever you are relying on any (implied) fall-though from one case block to the next. In the code shown above, such statements would be added immediately before the case 1: and case 0: labels.
Use chained if … else statements:
if (1000 <= price)
{
// Things for price 1000 or more.
}
else if (500 <= price)
{
// Things for price 500 or more.
}
else
{
// Things for other cases.
}

Exercise in C with if and switch statements: Write code to convert 2 digit numbers into words

There's this exercise I'm trying to figure out. The assignment asks to convert a two-digit number in words, the output should be something like this :
Enter a two-digit number:45
You entered the number forty-five.
I'm still a total beginner to programming. I'm at this chapter in this C programming book, in the exercise section about the switch and if statements. The exercise suggests to use two switch statements, One for the tens and the other one for units, but numbers within 11 and 19 require special treatment.
The problem is that I'm trying to figure out what should I do for numbers between 11 and 19, I was thinking to use the if statement but then the second switch function would include in the output and it would turn into something like You've entered the number eleven one.
This is the program I've been writing so far (incomplete):
int digits;
printf("Enter a two-digit number:");
scanf("%d", &digits);
printf("You entered the number ");
switch (digits / 10) {
case 20:
printf("twenty-");break;
case 30:
printf("thirty-");break;
case 40:
printf("forty-");break;
case 50:
printf("fifty-");break;
case 60:
printf("sixty-");break;
case 70:
printf("seventy-");break;
case 80:
printf("eighty-");break;
case 90:
printf("ninety-");break;
}
switch (digits % 10) {
case 1:
printf("one.");break;
case 2:
printf("two.");break;
case 3:
printf("three.");break;
case 4:
printf("four.");break;
case 5:
printf("five."); break;
case 6:
printf("six.");break;
case 7:
printf("seven.");break;
case 8:
printf("eight.");break;
case 9:
printf("nine.");break;
}
return 0;
Before the switch use these if then else statements.
if (digits == 11) {
printf("eleven");
}
else if (digits == 12) {
printf("twelve");
}
else if (... ) {// similar statements for 13 14 15 16 17 18 19
}
// now figure out where do the switch statements have to be inserted
else {
// here?
}
// or here?
The above solution assumes you haven't learnt arrays yet. If you have learnt or know to use arrays - there are ways to improve this code.
This is such a good problem for a learner, do not want to give much away
// Pseudo code
int print_two_digits(int tens, int ones) {
if (tens 2 or more)
print tens_place(tens) // use `tens` to index an array of strings.
if (ones == 0) return;
print -
else
ones += tens*10;
print ones_text(ones) // ones is 0-19 at this point. Index an string array with `ones`
}
How to index a string array and print?
// index: valid for 0,1,2
void print rgb(int index) {
const char *primary[] = { "red", "green", "blue" };
puts(primary[index]);
}
Trivia: English numbers in text 10-99 are mostly big-endian, most significant first as in "forty-two", except for [11-19] which has the smaller digit first as in "fourteen".
I would suggest you write a function with 3 switches instead of 2:
a first switch to handle special cases such as 0 and the numbers from 10 to 19 and return directly.
a second switch to handle tens from 20 and print the word without a trailing dash,
an if statement where you test if you need a dash,
a third switch where you handle units.

"Big Pig" dice game code goes in infinite loop :C

Hello I'm new to c and i'm currently learning with my university curriculum so i need to abide by these rules: We can't use arrays or global variables.
So i've been trying to make a dice game named "big pig". I'm right now creating the function the computer is going to use to play the game called "play_computer()". There is also a function called "computer_strategy_decider()".Computer_strategy_decider() is supposed to pick from yes or no. I just made a rand function that calls either 1 or 2 to make that work. Play_computer() let's you pick two dices and from there it needs to calculate the score. If you pick only one one, then your score doesn't increase and your game is terminated. If you et two ones you get 25 added. If you get any other double value for example a , is added such as (a+a)*2 or 4*a. And lastly if you get two random numbers the computer gets to decide if it wants to continue. That's where the computer_strategy_decider() comes in..
The problem comes with the play_computer() function. Everything seems to be working well when the computer rolls two different values and doesn't continue. It terminates ok. But if it wants to continue it goes in an infinite loop. The infinite loop also has the same dice values.
The same loop happens when doubles are rolled. Something in my code doesn't loop properly. I don't know whether it is something to do with rand() or not. I don't think it's rand() since i use rand() on computer_strategy_decider(). My theory is it's hopefully something small i have missed.
My code was working an hour ago before i added some changes so that's why im frustrated haha.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
int computer_strategy_decider(){
int deci;
srand(time(NULL));
deci=1+ (int) rand() % 2;
return deci;}
int play_computer(round_number,strategy){
int roll_1,roll_2,cntrl_var=0,score_comp=0;
char answ;
printf("\nRound %d-- My Turn:",round_number);printf("\n---------------------------------");
while(cntrl_var==0){
srand(time(NULL));
roll_1 = 1 + (int) rand() % 6;
roll_2 = 1 + (int) rand() % 6;
printf("\nI got --> [Dice 1]: %d [Dice 2]: %d",roll_1,roll_2);
if(roll_1==roll_2 && roll_1!=1){
score_comp=score_comp+roll_1*4;
printf("\nScore: %d",score_comp);printf("\nDoubles! Roll again!");}
else if(roll_1==1 && roll_2==1){
score_comp=score_comp+25;
printf("\nScore: %d",score_comp);printf("\nDoubles! Roll again!");}
else if(roll_1==1 || roll_2==1){
cntrl_var=1;
printf("\nYou got a single one! End of your turn!");}
else{
score_comp=score_comp+roll_1+roll_2;
printf("\nScore: %d",score_comp);
while(cntrl_var==0){
printf("\nDo you want to continue (Y/N)?");
if (strategy==1){
printf("Y");
break;}
else if (strategy==2){
printf("N");
break;}}
if (strategy==1)
cntrl_var=0;
else if (strategy==2)
cntrl_var=1;
else
cntrl_var=0;}}
printf("\nMy Score: %d",score_comp);
return score_comp;}
int main(){
int round_no=1,deci;
deci=computer_strategy_decider();
play_computer(round_no,deci);
}
I put the srand in the while loop and that caused the srand to be called multiple times. So i put the srand above the loop. That fixed it!

Check only last 3 digits of sensor output

I have a library from WiringPi for DHT11 sensor and I need to modify condition which checks if the value read from sensor is good.
Sometimes the library reads bad values which are 255.255,255.255 or 55,255.255 etc.
sample output
There is the condition in the library:
if(counter==255)
break;
But it doesn't work if the value is e.g. 55,255.255
How can I modify this condition the check last 3 digits of output?
If the output is wrong, there are always "255" at the end of value.
I tried to add conditions like
if(counter==255)
break;
else if(counter==255.255)
break;
But it doesn't solve all possible situations and I realy don't know anything about C/C++
Here is the whole library:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5
int dht11_val[5]={0,0,0,0,0};
int dht11_read_val()
{
uint8_t lststate=HIGH;
uint8_t counter=0;
uint8_t j=0,i;
for(i=0;i<5;i++)
dht11_val[i]=0;
pinMode(DHT11PIN,OUTPUT);
digitalWrite(DHT11PIN,LOW);
delay(18);
digitalWrite(DHT11PIN,HIGH);
delayMicroseconds(40);
pinMode(DHT11PIN,INPUT);
for(i=0;i<MAX_TIME;i++)
{
counter=0;
while(digitalRead(DHT11PIN)==lststate){
counter++;
delayMicroseconds(1);
if(counter==255)
break;
}
lststate=digitalRead(DHT11PIN);
if(counter==255)
break;
// top 3 transistions are ignored
if((i>=4)&&(i%2==0)){
dht11_val[j/8]<<=1;
if(counter>16)
dht11_val[j/8]|=1;
j++;
}
}
// verify checksum and print the verified data
if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))
{
printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);
return 1;
}
else
return 0;
}
int main(void)
{
int attempts=ATTEMPTS;
if(wiringPiSetup()==-1)
exit(1);
while(attempts)
{
int success = dht11_read_val();
if (success) {
break;
}
attempts--;
delay(500);
}
return 0;
}
No single variable in your code can hold "255.255", that would require a string or a float. You are obviously referring to the output of
printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);.
This printf can never produce a three-value output like 55,255.255.
I assume that your output would be 55.255,255.255.
This in turn means that in case of error you will find the "last three digits" in dht11_val[3].
If my assumption is not correct please provide much more detail on the error circumstances.
On the other hand, I suspect that looking for that value is not the solution for your problem either. The function is more complicated. The value of 255 seems the result of an endless loop which is detected by breaking early at counter = 255. So I am pretty sure that checking "the last three digits" is a LESS precise check than what is already implemented.

Galton Box/Bean Machine-C

I want to code a simple bean machine program. The program will accept user input for the number of balls and the number of slots, and will calculate the path of each ball. The number of balls in each slot will be printed as a histogram as well.
I tried my best to keep the code short and sweet, yet the best I have managed is 112 lines long. When I ran my code, I received no errors. However, the output seems to have run into some sort of an infinity loop (The '#' symbol which was used to represent numbers in the histogram keeps on printing forever for some reason unknown to me).
Apparently, there is something wrong with my logic somewhere... or a silly little mistake in syntax(but it would have shown up as error, wouldn't it?)... In a nutshell, I cannot figure out exactly what is the problem. (I attempted to walk through the whole code process from start to finish, but my mind kept getting tangled up somewhere in the middle of the code, nowhere near the end of the code either).
Where exactly does my logic go wrong?(Or have I taken the wrong approach to the whole problem?) I do not wish to know the correct code, so that I am able to learn during the whole process of re-editing my code.
Any help (hopefully no model-code answers though), even as a single comment, is tremendously appreciated! :)
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <stdbool.h>
#include <time.h>
//Pls excuse my extensive use of libraries even though I don't really use them
int intchecker(float x)
{
if (floor(x)==x && ceilf(x)==x)
{
return 0;
}
else {
return 1;
}
}
int main(){
char line[] = " +----+----+----+----+----+----+----+----+----+----+---+";
char numbers[] = " 0 5 10 15 20 25 30 35 40 45 50";
float balls,slots;
int slotarry[9],tlevel,ballnum,column,lcounter=0,slotsduplicate=1,y;//tlevel-number of levels in the triangle
srand(time(NULL));
int r;
printf("==========================================================\nGalton Box Simulation Machine\n==========================================================\n");
printf("Enter the number of balls [5-100]: ");
scanf("%f",&balls);
while (balls>100 || balls<5) {
printf("\nInput is not within the range. Please try again.");
printf("\nEnter the number of balls [5-100]: ");
scanf("%f",&balls);
}
while (intchecker(balls)==1) {
printf("\nInput is not an integer. Please try again.");
printf("\nEnter the number of balls [5-100]: ");
scanf("%f",&balls);
}
printf("Enter the number of slots [2-10] : ");
scanf("%f",&slots);
while (slots>10 || slots<2) {
printf("\nInput is not within the range. Please try again.");
printf("\nEnter the number of slots [2-10] : ");
scanf("%f",&slots);
}
while (intchecker(slots)==1) {
printf("\nHow can there be a fraction of a slot? Please re-enter slot number.");
printf("\nEnter the number of slots [2-10] : ");
scanf("%f",&slots);
}
tlevel=slots-1;
for(ballnum=1,column=0;balls>0;balls--,ballnum++,column++){
if (column%5==0){
printf("\n");
}
if (ballnum<10){
printf("[0%d]",ballnum);
}
else{
printf("[%d]",ballnum);
}
for(;tlevel>0;tlevel--){
r = rand() % 2;
if (r==0){
printf("R");
}
else {
printf("L");
lcounter++;
}
}
slotarry[lcounter]++;
tlevel=slots-1;
lcounter=0;
printf(" ");
}
printf("\n\n%s",numbers);
printf("%s",line);
char line2[] = "\n +----+----+----+----+----+----+----+----+----+----+---+";
for(;slotsduplicate<=slots;slotsduplicate++){
if (slotsduplicate<10){
printf("0%d|",slotsduplicate);
}
else{
printf("%d|",slotsduplicate);
}
y=slotarry[slotsduplicate];
if (y==0){
printf(" 0");
}
else{
for (;y>0;y--){
printf("#");
}
printf(" %d",slotarry[slotsduplicate]);
}
printf("%s",line2);
}
return 0;
}
Note:This is not completely error-free. This is just my first draft. I just wish to find out why there is an infinite loop.
Here's how I found the problem. First of all, I think it is a bit of a code smell to have a for loop without anything in the initial assignment section. Couple that with the fact that it seems to print # forever, and it looks like y has a garbage value at the beginning of the loop to print the #s.
So I ran your code in the debugger and paused it when it started printing loads of hashes. I checked the value of y and sure enough it was some unfeasibly high number.
Then I checked where y comes from and found you get it from slotarray. I printed it in the debugger and found that all the values in it were unfeasibly high or massively negative numbers. Obviously, slotarray wasn't being initialised correctly, so I looked for where it was initialised and bingo!
Stack variables (of which slotarray is one) must be explicitly initialised in C. I fixed your code with a call to memset.
The whole debugging process I have just outlined took something less than a minute.
ETA As #EOF points out, there is another bug in that slotarray is defined to contain nine slots (indexed 0 - 8) but you allow people to enter 10 slots. This is a buffer overflow bug.

Resources