Incorrect coding with respect to logic written - c

The program needs to execute until 'q' is pressed. But the below code what I wrote it is only executing whichever case is first and then stops executing further cases. Ex: case 1.if my input is p, q, then only p case is executed, not the q.
case 2.if my input is g, q, then only g case is executed, not the q.
int main()
{
int i,n,cnt;
char value[10]={0,0,0,0,0,0,0,0,0,0};
int index; float values,Max;
int *val;
bool quit=false;
float num[10]={1.500, 2.200, 7.300, 9.200, 7.400, 7.500, -8.000, 1.500, 12.000, 0.000};
for(i=0;i<20;i++)
{
scanf("%c",&value[i]);
if(value[i]=='r')
{
scanf("%d", &index);
scanf(", %3f",&values);
}
if((value[i] =='p')|(value[i] =='q')|(value[i] =='r')|(value[i] =='g')|(value[i] =='s'))
{
cnt++;
}
}
for(i=0;i<cnt;i++)
{
while(!quit)
{
switch(value[i])
{
//printf("Command (p/g/r/s/q):");
case 'p':
{
printf("Command (p/g/r/s/q):");
printValues(&num,10);
return;
}
case 'g':
{
printf("Command (p/g/r/s/q):");
Max= largestElement(&num,10);
printf("Max=%0.3f",Max);
return;
}
case 'r':
{
printf("Command (p/g/r/s/q):");
replaceElement(&num,index,values);
printValues(&num,10);
return;
}
case 's':
{
printf("Command (p/g/r/s/q):");
sortOnValue(&num,10);
printValues(&num,10);
return;
}
case'q':
{
printf("Command (p/g/r/s/q):");
quit= true;
break;
}
default:
{
printf("help");
return;
}
}
}
}
return 0;
}

Within most of your case blocks you probably want break rather than return to exit the switch. At the moment you are returning frommain() and consequently exiting the program. break transfers control to the end of the switch and your program can then continue.
The case 'q' block would then have a return to exit the program.

Few problems here.
for(i=0;i<20;i++) you are accessing out of bound so your loop should be
for(i=0;i<10;i++).
You need to add ' ' in the format string to consume new line character (\n).
`scanf(" %c",&value[i]);`
You are using | operator instead of || hence your if should be.
if((value[i] =='p')||(value[i] =='q')||(value[i] =='r')||(value[i] =='g')||(value[i] =='s'))
{
cnt++;
}
You are using return instead of break in your switch case.
change this
case 'p':
{
printf("Command (p/g/r/s/q):");
printValues(&num,10);
return;
}
to
case 'p':
{
printf("Command (p/g/r/s/q):");
printValues(&num,10);
break;
}
Your while(!quit) inside the for loop is not useful and will lead to infinate loop when used break statement inside switch case. Hence remove the while(!quit) and change your for loop as below.
for(i=0;i<cnt&&!quit;i++)
side note:: It is high time for you
learn-how-to-debug-small-programs

Related

Why is my switch case not working for multiplication or addition [duplicate]

Okay so I'm writing a code for something and I've encountered a problem whilst testing switch function. It does all the cases incrementing from one's selection (my explanation). Could someone help me explain why is this so?
#include <stdio.h>
#include <stdlib.h>
#include "ratedzfunctions.h"
int main()
{
int selection, loop=1;
FILE* fajl;
//Opening the participants file
fajl=fopen("participants.txt","r+");
if (fajl==NULL)
{
printf("The file cannot be opened.\n");
}
//MENU
do
{
printf("\nMENU: \n------------\n1. RATEDZ\n\n2. STATISTICS\n\n3. EXIT\n\n==>");
scanf("%d", &selection);
switch (selection)
{
case 1:
ratedz(fajl);
case 2:
stats(fajl);
case 3:
loop=0;
}
}
while (loop==1);
fclose(fajl);
return 0;
}
//THIS IS FROM RATEDZFUNCTIONS.H
void ratedz(FILE *fajl)
{
printf("\nTEST RATEDZ");
}
void stats(FILE *fajl)
{
//Printing all participants
char *buffer=(char*) malloc(50);
while(fscanf(fajl,"%s %s %s", buffer)!=EOF)
{
printf("\n%s %s %s", buffer);
}
free(buffer);
}
You forgot to add a break; statement after each case.
case 2:
stats(fajl);
break; /* <---- */
You should put a break; after each case.
The switch/case rule is easy, after a mached case, all following cases will be executed until a break; or end of switch:
switch (selection)
{
case 1:
...
break;
case 2:
...
break;
case 3:
...
break; // Last break is not necessary
// but it's good practice to put it.
}
There are good situations which removing break; is reasonable:
switch(letter)
{
case 'i':
case 'a':
case 'o':
case 'u':
case 'e':
printf ("Vowel!");
break;
default :
printf ("Consonant!");
break;
}
If you do not add a break at the end of each case it will just fall through to the next case:
switch (selection)
{
case 1:
ratedz(fajl);
break ;
case 2:
stats(fajl);
break ;
/* ... */
}
A case in a switch statement is treated like a label (see C.11 § 6.8.1). . There is actually no requirement to have any cases at all (See C.11 § 6.8.4).
switch (0) { /* do nothing */ }
The above code will compile just fine.
Since a case is like a label, there are no implicit semantics attached to it that would cause it to automatically jump outside the switch. Just as break is used to leave a loop block early, break is also used to leave a switch block early.
Syntax for switch staement in C
switch(expression)
{
case (constant-expression) : staements
....
case (constant-expression) : staements
default : statements
}
To work with a particular case your last statement in that group of statement must be break.
Without the break statement , when the last statement in the case has been executed, control "falls through" to the first statement in the following case; the case label (const-expression) for the next case is ignored. Without break (or some jump statement), control will flow from one case into the next.
Some corrections,
#include <stdio.h>
#include <stdlib.h>
#include "ratedzfunctions.h"
int main()
{
int selection, loop=1;
FILE* fajl;
//Opening the participants file
fajl=fopen("participants.txt","r+");
if (fajl==NULL)
{
printf("The file cannot be opened.\n");
exit(1); //handle error when file cannot be opened...
}
//MENU
do
{
printf("\nMENU: \n------------\n1. RATEDZ\n\n2. STATISTICS\n\n3. EXIT\n\n==>");
scanf("%d", &selection);
switch (selection)
{
case 1:
ratedz(fajl);
break;
case 2:
stats(fajl);
break;
case 3:
loop=0;
break;
default:
break;
}
}
while (loop==1)
{
//do stuff here
}
fclose(fajl);
return 0;
}

kbhit and multiple calls on function

While making a asteroid shooter, I came around using _kbhit() and kbhit(). I'm no expert, but here is the problem I think I'm having:
int run = 1;
int main() {
while(run){
if(GetUserInput() == 2)
printf("W");
if(GetUserInput() == 1)
printf("S");
Sleep(50);
}
}
int GetUserInput(){
if(kbhit()){
char c = _getch();
if(c == 's')
return 2;
if(c == 'w')
return 1;
}
else
return 0;*
}
So, what I think is happening, it does the first check on GetUserInput(), and because of the nature of getch(), the keyboard is read from the buffer and discarded? Anyways, I store the value in c and should return appropriately. But it only does the first check. Is it because there is no more input on the buffer after the first check (in the main() function)?
Your problem is that you're trying to read once for every key you're interested in with this code:
if(GetUserInput() == 2)
printf("W");
if(GetUserInput() == 1)
printf("S");
For example, I press 'S', you read the key, check if the return value is 2 and it is not. Then you try to read another key, but I haven't pressed one, so the second check for 'S' also fails.
To fix this you need to perform all of your tests on the value you get from GetUserInput().
int val = GetUserInput();
if(val == 2)
printf("W");
else if(val == 1)
printf("S");
You don't need to use else if, but once you've found a match it makes no sense to keep checking if all of your checks are mutually exclusive. You might consider using a switch statement and an enum instead of hardcoded magic values, or even return the key value directly if one is pressed and a sentinel value like 0 that won't match any of the keys you're interested in.
Here is a complete example that works for me:
#include <conio.h>
#include <stdio.h>
int GetUserInput()
{
if (_kbhit())
{
char c = _getch();
switch (c)
{
case 's':
case 'S':
return 2;
case 'w':
case 'W':
return 1;
case 'x':
case 'X':
return -1;
}
}
return 0;
}
int main()
{
for (;;)
{
int c = GetUserInput();
switch (c)
{
case 1:
printf("W");
break;
case 2:
printf("S");
break;
case -1:
return 0;
}
}
return 0;
}

Reading file line by line - why I get the first line only?

I have a task in university to write a C program which reads a file and counts the number of single and multi comments. The problem I have is that the second while() only reads the first line and so the returned comments are 0.
Previously I read the file character by character, but that's not the task requirement. Why does this program read only the first line and not the others?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp;
int c, i = 0;
char path[256], ch, line[80];
unsigned int multi = 0;
unsigned int single = 0;
enum states {
PLAIN_TEXT,
SLASH,
STAR,
SINGLE_COMMENT,
MULTI_COMMENT,
QUOTES
} state = PLAIN_TEXT;
printf("Write file's name\n");
gets(path)
fp = fopen(path, "r");
if (!fp) {
// give an error message
} else {
while (fgets(line, sizeof(line), fp) != NULL) {
while (i < sizeof(line)) {
printf("%d.%c", i, line[i]);
switch (state) {
case PLAIN_TEXT:
switch (line[i]) {
case '/': i++;
state = SLASH;
break; // found a slash. In the next loop the switch argument will be SLASH
case '"': i++;
state = QUOTES;
break; // found a quote. Quoted text (there might be a '//' inside)
default: i++;
break; // found an ordinary character
}
break;
case QUOTES:
switch (line[i]) {
case '"': i++;
state = PLAIN_TEXT;
break; // Gets out the string;
case ' ':i++;
state = PLAIN_TEXT;
break;
default: i++;
state = QUOTES;
break; // Still a quoted text;
}
break;
case SLASH:
switch (line[i]) {
case '/': i++;
state = SINGLE_COMMENT;
break; // found a slash => a possible single comment found
case '*': i++;
state = MULTI_COMMENT;
break; // found a star => a possible multi comment found
default: i++;
state = PLAIN_TEXT;
break; // found an ordinary character
}
break;
case STAR:
switch (line[i]) {
case '/': i++;
state = PLAIN_TEXT;
multi++;
break; // Increments the multi comment and the next characher will be treated as a plain_taxt
default: i++;
state = MULTI_COMMENT;
break; // Still multi comment
}
break;
case SINGLE_COMMENT:
switch (line[i]) {
case '\n':i++;
state = PLAIN_TEXT;
single++;
break; // End of the single comment line. Increment the counter and the next character will be treated as a plain_text
default: i++;
break;
}
break;
case MULTI_COMMENT:
switch (line[i]) {
case '*': i++;
state = STAR;
break; // Found a multi comment. The next state will be star.
default: i++;
break;
}
break;
default: i++;
break;
}
}
}
fclose(fp);
printf("Single-comment : %8u\n", single);
printf("Multi-comment : %8u\n", multi);
}
return 0;
}
To enumerate the characters on the line, you must reinitialize i to 0 for each line and stop at the null terminator or at the newline character

Working with .txt in VS2008 in C

I wrote some program which overwrites some text in .txt file and put the overwritten one in another output.txt... But it's constantly saying that the file can't be opened. What should I do?
#include <stdio.h>
#include <ctype.h>
int main()
{
FILE *ul=fopen("hexbr.txt","r"),*iz=fopen("bitovi.txt","w");
int i;
char ch;
if ((!ul)||(!iz)) { printf("Neuspesno otvaranje datoteke!");return 0; }
while((ch=fgetc(ul))!=EOF)
{
if ((isdigit(ch)) || (c>='A' && c<='F'))
{
if (isalpha(ch))
switch(ch)
{
case 'A': { fputc('1',iz);fputc('0',iz);fputc('1',iz);fputc('0',iz);continue; }
case 'B': { fputc('1',iz);fputc('0',iz);fputc('1',iz);fputc('1',iz);continue; }
case 'C': { fputc('1',iz);fputc('1',iz);fputc('0',iz);fputc('0',iz);continue; }
case 'D': { fputc('1',iz);fputc('1',iz);fputc('0',iz);fputc('1',iz);continue; }
case 'E': { fputc('1',iz);fputc('1',iz);fputc('1',iz);fputc('0',iz);continue; }
case 'F': { fputc('1',iz);fputc('1',iz);fputc('1',iz);fputc('1',iz);continue; }
}
for(i=0;i<4;i++)
{
fputc((ch & 0X8)?'1':'0',iz);
ch<<=1;
}
}
else fputc(ch,iz);
if (ch=='\n') { ch=fgetc(ul);fputc(ch,iz); }
}
fclose(ul);
fclose(iz);
return 0;
}
The program did not compile without error, there is a pair of typos here, c should be ch:
... (c>='A' && c<='F') ...
Apart from that the program almost works, and the output file (created in the same folder as the executable) is readable.
There is a mistake in trying to handle newline chars, which mistakenly causes the next (printing) char to be passed through and not converted to binary. I left newline and return to be passed through like other non-hex chars.
Other than that, the handling of A..F is clumsy. I suggest trapping them like this:
while((ch=fgetc(ul))!=EOF)
{
if ((isdigit(ch)) || (ch>='A' && ch<='F'))
{
if (isalpha(ch))
ch -= 7;
for(i=0;i<4;i++)
{
fputc((ch & 0X8)?'1':'0',iz);
ch<<=1;
}
}
else fputc(ch,iz);
}
And you might want to check and convert the lower case a..f too.

Switch function in C does all the cases

Okay so I'm writing a code for something and I've encountered a problem whilst testing switch function. It does all the cases incrementing from one's selection (my explanation). Could someone help me explain why is this so?
#include <stdio.h>
#include <stdlib.h>
#include "ratedzfunctions.h"
int main()
{
int selection, loop=1;
FILE* fajl;
//Opening the participants file
fajl=fopen("participants.txt","r+");
if (fajl==NULL)
{
printf("The file cannot be opened.\n");
}
//MENU
do
{
printf("\nMENU: \n------------\n1. RATEDZ\n\n2. STATISTICS\n\n3. EXIT\n\n==>");
scanf("%d", &selection);
switch (selection)
{
case 1:
ratedz(fajl);
case 2:
stats(fajl);
case 3:
loop=0;
}
}
while (loop==1);
fclose(fajl);
return 0;
}
//THIS IS FROM RATEDZFUNCTIONS.H
void ratedz(FILE *fajl)
{
printf("\nTEST RATEDZ");
}
void stats(FILE *fajl)
{
//Printing all participants
char *buffer=(char*) malloc(50);
while(fscanf(fajl,"%s %s %s", buffer)!=EOF)
{
printf("\n%s %s %s", buffer);
}
free(buffer);
}
You forgot to add a break; statement after each case.
case 2:
stats(fajl);
break; /* <---- */
You should put a break; after each case.
The switch/case rule is easy, after a mached case, all following cases will be executed until a break; or end of switch:
switch (selection)
{
case 1:
...
break;
case 2:
...
break;
case 3:
...
break; // Last break is not necessary
// but it's good practice to put it.
}
There are good situations which removing break; is reasonable:
switch(letter)
{
case 'i':
case 'a':
case 'o':
case 'u':
case 'e':
printf ("Vowel!");
break;
default :
printf ("Consonant!");
break;
}
If you do not add a break at the end of each case it will just fall through to the next case:
switch (selection)
{
case 1:
ratedz(fajl);
break ;
case 2:
stats(fajl);
break ;
/* ... */
}
A case in a switch statement is treated like a label (see C.11 § 6.8.1). . There is actually no requirement to have any cases at all (See C.11 § 6.8.4).
switch (0) { /* do nothing */ }
The above code will compile just fine.
Since a case is like a label, there are no implicit semantics attached to it that would cause it to automatically jump outside the switch. Just as break is used to leave a loop block early, break is also used to leave a switch block early.
Syntax for switch staement in C
switch(expression)
{
case (constant-expression) : staements
....
case (constant-expression) : staements
default : statements
}
To work with a particular case your last statement in that group of statement must be break.
Without the break statement , when the last statement in the case has been executed, control "falls through" to the first statement in the following case; the case label (const-expression) for the next case is ignored. Without break (or some jump statement), control will flow from one case into the next.
Some corrections,
#include <stdio.h>
#include <stdlib.h>
#include "ratedzfunctions.h"
int main()
{
int selection, loop=1;
FILE* fajl;
//Opening the participants file
fajl=fopen("participants.txt","r+");
if (fajl==NULL)
{
printf("The file cannot be opened.\n");
exit(1); //handle error when file cannot be opened...
}
//MENU
do
{
printf("\nMENU: \n------------\n1. RATEDZ\n\n2. STATISTICS\n\n3. EXIT\n\n==>");
scanf("%d", &selection);
switch (selection)
{
case 1:
ratedz(fajl);
break;
case 2:
stats(fajl);
break;
case 3:
loop=0;
break;
default:
break;
}
}
while (loop==1)
{
//do stuff here
}
fclose(fajl);
return 0;
}

Resources