Change(?) user input character into another character c language - c

Writing a program for school to cause a user inputted character to identify a gas cylinder. Here is what i have written so far, but all inputs display ammonia.
#include <stdio.h>
int main()
{
char n;
printf("Please enter the first letter of color of gas cylinder\n");
scanf("%c", &n);
if(n = 'o' ){
printf("Ammonia\n");
}
else if(n = 'b'){
printf("Carbon Monoxide\n");
}
else if(n = 'y'){
printf("Hydrogen\n");
}
else if(n = 'g'){
printf("Oxygen\n");
}
else{
printf("Contents Unknown\n");
}
return 0;
}

You want to use ==—the equality operator—inside your if statements.
= is the assignment operator—it will set n to be 'o', so your first if statement always returns true ('o' is non-zero).

Related

Input Validation in C When Calculating Grades

I have a problem that needs to calculate the grade needed on a final exam in order to get the letter grade that they desire. I have the code correct for the calculations but I need to account for all invalid user input. I have accounted for negative grades and letter grades that don't exist but I can't figure out how to make sure the percentages they are inputting don't contain letters or other characters. For example if I ask for their current grade in the class they cannot input something like 95.6asi!. This is the code I have right now but there are many errors.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void calcGradeNeededOnFinal() {
double percentWanted = 0.0;
double currentGrade, finalWeight;
char gradeWanted;
printf("Enter the grade you want in the class: ");
scanf("%c", &gradeWanted);
if (gradeWanted == 'A' || gradeWanted == 'a'){
percentWanted = 90.0;
}
else if (gradeWanted == 'B' || gradeWanted == 'b'){
percentWanted = 80.0;
}
else if (gradeWanted == 'C' || gradeWanted == 'c'){
percentWanted = 70.0;
}
else if (gradeWanted == 'D' || gradeWanted == 'd'){
percentWanted = 60.0;
}
else if (gradeWanted == 'F' || gradeWanted == 'f'){
percentWanted = 0.0;
}
else {
printf("Unknown Grade Received: %c. Ending Program.\n", gradeWanted);
exit(0);
}
printf("Enter your current percent in the class: ");
scanf("%lf", &currentGrade);
if(currentGrade < 0) {
printf("The number you last entered should have been positive. Ending program.\n");
exit(0);
}
char gradeString = (char)currentGrade;
for(int i=0; i < strlen(gradeString); ++i) {
if(!(isdigit(gradeString[i])) && (strcmp(gradeString[i], '.') != 0))) {
printf("Invalid formatting. Ending program.\n");
exit(0);
}
}
printf("Enter the weight of the final: ");
scanf("%lf", &finalWeight);
if(finalWeight < 0) {
printf("The number you last entered should have been positive. Ending program.\n");
exit(0);
}
char weightString = (char)finalWeight;
for(int i=0; i < strlen(weightString); ++i) {
if(!(isdigit(weightString[i])) && (strcmp(weightString[i], '.') != 0))) {
printf("Invalid formatting. Ending program.\n");
exit(0);
}
}
// this calculates the grade need on the final test to get the desired grade of the user
double gradeNeededOnFinal = (percentWanted - (currentGrade * (1.0 - finalWeight/100.0))) / (finalWeight/100.0);
printf("You need to get at least %.2lf%% on the final to get a %c in the class.\n", gradeNeededOnFinal, gradeWanted);
}
int main() {
calcGradeNeededOnFinal();
return 0;
}
For example if I ask for their current grade in the class they cannot input something like 95.6asi!.
You have declared grade as char so there is no possibility that it can store 95.6asi!
char gradeWanted;
What you need is : isalpha or isupper and islower function(s) from ctype.h
isalpha() checks for an alphabetic character; in the standard "C" locale, it is equivalent to (isupper(c) || islower(c)). In some locales, there may be additional characters for which isalpha() is true-letters which are neither upper case nor lower case.
Just check if your gradeWanted is an alphabet or not.
Using
if (isalpha( gradeWanted ))
or
if (isupper( gradeWanted ) || islower( gradeWanted ))
is enough.
All ctype functions takes an int and returns an int, you can declare char gradeWanted; as int gradeWanted;
you could read the characters entered and, using the ascii encoding, check (perhaps with a switch) which character is inserted and manage it.
This way you have full control of the entries.
you can get char to ascii conversion with:
int a_as_int = (int)'a';

Scanning character caused problem in devC

So my code does the following:
Ask what's the option
If option is 1: Scan some numbers
If option is 2: Print those numbers
After each option, ask if user wanted to continue choosing (Y/N)
This is my main code
while(yesnocheck==1)
{
printf("What's your option?: ");
scanf("%d",&b);
switch(b){
case 1:
printf("How many numbers?: ");
scanf(" %d",&n);
a=(struct sv*)malloc(n*sizeof(struct sv));
for(int i=0;i<n;i++)
scanf("%d",&((a+i)->num));
break;
case 2:
for(int i=0;i<n;i++)
printf("%d\n",(a+i)->num);
break;
}
yesnocheck==yesnochecker();
}
And this is the yesnochecker function:
int yesnochecker()
{
char yesorno;
printf("Do you want to continue? (Y/N)");
while(scanf("%s",&yesorno))
{
if(yesorno=='Y')
return 1;
if(yesorno='N')
return 0;
printf("*Wrong input. Please reenter (Y/N): ");
}
}
So on dev C++, my code won't run correctly. After it's done option 1, when I enter "Y" then choose option 2, case 2 will display some weird numbers. However it works well on online C compilers.
And then, when I change the char yesorno in yesnochecker() function to char yesorno[2] and treat it as a string, the code does work.
Can someone shed some light?
It is a bad idea to read a char c with scanf("%s", &c);. "%s" requires a buffer to store a string. The only string which fits into a char is an empty string (consisting only of a terminator '\0' – not very useful). Every string with 1 character requires 2 chars of storage – 1 for the character, 1 for the terminator ('\0'). Providing a char for storage is Undefined Behavior.
So, the first hint was to use the proper formatter instead – "%c".
This is better as it removes the Undefined Behavior. However, it doesn't solve another problem as the following sample shows:
#include <stdio.h>
int cont()
{
char c; do {
printf("Continue (y/n): ");
scanf("%c", &c);
printf("Input %c\n", c);
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n):
Input '
'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
WTH?
The scanf("%c") consumes one character from input. The other character (inserted for the ENTER key) stays in input buffer until next call of any input function.
Too bad, without ENTER it is hard to confirm input on console.
A possible solution is to read characters until the ENTER key is received (or input fails for any reasons). (And, btw., getc() or fgetc() can be used as well to read a single character.):
#include <stdio.h>
int cont()
{
int c;
do {
int d;
printf("Continue (y/n): ");
if ((c = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
printf("Input '%c'\n", c);
for (d = c; d != '\n';) {
if ((d = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
}
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n): Hello↵
Input 'H'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
Please, note, that I changed the type for the read character to int. This is because getc()/fgetc() return an int which is capable to store any of the 256 possible char values as well as -1 which is returned in case of failing.
However, it isn't any problem to compare an int with a character constant (e.g. 'y'). In C, the type of character constants is just int (SO: Type of character constant).

How do you print different things depending the user input?

First, I apologize if the question doesn't make sense as my English isn't that good...
My question is, how do we print out different things depending on the user input?
What I'm trying to do is: when user inputs integer, the program prints out the inputted number. When the user inputs something that's not integer (like symbols and characters), the program prints out "not integer".
my current idea (pseudo-code) is as follows:
`int main(){
int value;
printf("Enter numbers");
scanf("%d", &value);
if(value is integer){
printf("%d", value);
} else {
printf("not integer");
}
return 0;
}`
what gets me is the scanf; by using %d, I'm assuming that the user will input an integer values, but the user can input values that are not integers so I can't make a comparison using the if statement if( value is integer). How can I make a comparison that will determine whether the inputted value is integer or not?
I don't know if this is a good thing or not.
You can use ASCII to check if the input type is an integer or not
(between 48 - 57 in ASCII)
it will be like this
char value;
int flag = 0; //to check true or false (0 means false, and 1 means true)
printf("Enter numbers");
scanf("%c", &value);
for(int i = 48; i <= 57; i++){
if(value == i){
flag = 1;
break;
}
}
if(flag == 1){
printf("%c", value);
} else {
printf("not integer");
}
How do you print different things depending the user input?
Step 1: Read the line of user input
char buf[100];
if (fget(buf, sizeof buf, stdin)) {
// something was entered
Step 2: test the string
char *end;
long value = strtol(buf, *end);
// If the end is the same as the beginning, no conversion occurred.
if (end == buf) {
puts("not integer");
}
printf("%ld\n", value);
}
}
Additional code could look for input that occurred after the integer. Also code could test for a large number that overflowed the long range.
The code is as follows. It caters for different situations like inputting negative numbers and decimal numbers:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char input[20];
int wrongFlag = 0;
scanf("%s", input);
if (input[0] == '0' && strlen(input) > 1) {
wrongFlag = 1;
//for number starts with 0, and string length>1 eg: 010
}
for (int i = 0; i < strlen(input); i++) {
if (i == 0 && (input[i] == '-' && strlen(input) > 2 && input[i + 1] == '0')) {
//check first round only: negative number with length >2 and starts with 0 eg: -010.
wrongFlag = 1;
continue;
}
if (i != 0 && !isdigit(input[i])) {
//check following rounds, check if it is not digit
wrongFlag = 1;
break;
}
}
if (wrongFlag) {
printf("Not integer");
}
else {
printf("integer");
}
return 0;
}
Try this it works for me.
#include<stdio.h>
#include<string.h>
int main()
{
int i;
char value[50];
int len;
printf("Enter maximum 50 digits\n");
/* enter the values you wanted*/
printf("Enter the value: ");
gets(value);
len = strlen(value);
/*it will iterate upto the end of the user input*/
for(i=0;i<len;i++)
{
if(48<value[i] && value[i]<=57)
{
if(i==(len-1))
printf("It's an integer");
}
else{
printf(" Not an integer");
break;
}
}
return 0;
}

unintended loop (C)

I keep getting a duplicate loop when running a Rock Paper Scissors program in C:
#include <stdio.h>
#include <stdlib.h>
int getUserInput(userInput);
int getComputerInput(cpuInput);
int pickWinner(int player, int cpu);
int main()
{
int playerWins = 0;
int compWins = 0;
int ties = 0;
int userInput;
int cpuInput;
int userChoice =1;
int compChoice;
int decision;
while (userChoice != 4)
{
compChoice = getComputerInput();
userChoice = getUserInput(userInput);
printf("computer chose %d\n", compChoice); //for debugging
printf("you chose %d \n", userChoice);//for debugging
decision = pickWinner(userChoice, compChoice);
if (decision == 1)
{
playerWins++;
}
else if (decision == 2)
{
compWins++;
}
else if (decision == 3)
{
ties++;
}
}
printf("Final score is: \nPLAYER: %d \nCOMPUTER: %d \n", playerWins, compWins);
}
//generates a random number for computer, 1=rock 2= paper 3=scissors
int getComputerInput (int cpuInput)
{
srand(time(NULL));
int r = rand() %3 +1;
return r;
}
//prompts user for character input, then converts input into a number to return back to main
int getUserInput(userInput)
{
char playerPick ;
printf("Please choose R, P, or S. (Q for quit)\n");
playerPick = getchar();
switch(playerPick)
{
case 'R' | 'r':
printf("Player chose R. \n");
return 1;
break;
case 'p':
case 'P':
printf("Player chose P. \n");
return 2;
break;
case 's':
case 'S':
printf("Player chose S. \n");
return 3;
break;
case 'q':
case 'Q':
printf("player quit");
return 4;
break;
default:
printf("Invalid choice, choose again \n");
break;
}
}
//method for determining winner
int pickWinner(int player, int cpu)
{
if (player ==1 && cpu ==1)
{
printf("tie\n\n");
return 3;
}
else if (player==1 && cpu ==2)
{
printf("you lose, paper beats rock\n\n");
return 2;
}
else if (player ==1 && cpu ==3)
{
printf("you win, rock beats scissors\n\n");
return 1;
}
else if (player ==2 && cpu ==1)
{
printf("you win, paper beats rock\n\n");
return 1;
}
else if (player ==2 && cpu ==2)
{
printf("tie\n\n");
return 3;
}
else if (player ==2 && cpu ==3)
{
printf("you lose, scissors beats paper\n\n");
return 2;
}
else if (player ==3 && cpu ==1)
{
printf("you lose, rock beats scissors\n\n");
return 2;
}
else if (player ==3 && cpu ==2)
{
printf("you win, scissors beat paper\n\n");
return 1;
}
else if (player ==3 && cpu ==3)
{
printf("tie\n\n");
return 3;
}
}
Output:
it seems to be passing a zero back to the getUserInput method and I cant figure out why.
any hints in the right direction would be VASTLY appreciated.
apologies if this post is not formatted correctly.
thanks in advance
When you enter input, you end the input by pressing the Enter key. That key is actually placed into the input queue as a newline.
So when you read the first character, you will get the character entered (for example 'r'). However, the next character in the input queue is the newline, and that will be what the second call to getchar will give you.
There are ways to skip that. The simplest is simply doing an extra getchar call to discard the next character. However, if that's not the newline (for example if the user entered more than one letter as input) then that will not work.
Another possible solution is to use fgets to read a whole line, and the just get the first character from that line. The problem is if you don't provide a big enough buffer to store the line, you will have the same problem as before.
The only safe solution is to read the input from the user as a character. Then in a loop read until you get the newline character. The characters you read in the loop is simply discarded.
Perhaps something like this function:
void skip_past_newline(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF)
{
// Do nothing
}
}
Then just call it after you read the user input:
playerPick = getchar();
skip_past_newline();
Please do note a couple of things with the skip_past_newline function as presented above:
The variable that receives the result of getchar is an int variable. This is actually important.
I not only check for the newline in the loop, I also check for EOF. This indicates the used pressed the end-of-file key-combination (Ctrl-Z in the Windows console window) and that you should exit your program. This check is why you need to make the variable an int.
AFAICS, there are at least two problems with getUserInput()
When the user inputs an invalid choice, getUserInput returns without a value, because there is no loop around the code to ask again. I am pretty sure, the compiler warns about this.
To input a value, the user must enter a character and a newline. This is the character read the second time, which produces the output "invalid choice". To prevent this, you must skip the whitespace before reading the next input char.

C Program Looping Incorrectly

I'm just a beginner and I'm trying to use whatever I know to make a simple program that:
Asks the user to input the letter 'S' or 's'. The program loops if 's' is not input. If the user does input 's', the program then
Asks the user to input a number, 1 or 2. The program loops if the incorrect number is input.
The problem I'm having is that after 's' is successfully input and the user is asked to enter a number, if an incorrect number is input (not 1 or 2) the program asks the user to input a letter again from the beginning which is incorrect. The program loops from the very beginning and doesn't work anymore. Can anyone help me fix this please?
#include <stdio.h>
#include <ctype.h>
int function(int num);
int main()
{
char input,ch,temp,c[64],exit;
int i,invalid,num,index,flag,day;
invalid = 0;
num = 0;
size_t length = 0;
index = 0;
flag = 0;
do
{
puts("Enter the letter S to start the program:");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
{
if(isalpha(input)==0)
{
printf("Invalid input. Please input something.\n");
continue;
}
if(input == 'S' || input == 's')
{
printf("\nProgram start.");
while( sscanf(c, "%d", &num) != 1)
{
length = 0;
flag = 0;
num = 0;
printf("\nEnter 1 for Module A. Enter 2 for Module B. Enter here: ");
fgets(c, 63, stdin);
length = strlen(c);
for(index = 0; index < length; ++index)
{
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
}
if( flag)
{
printf("\nInvalid character\n");
continue;
}
if( sscanf(c, "%d", &num) != 1)
{
printf("\nNo input detected.");
continue;
}
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
}
}
else
{
printf("\nInvalid input.");
continue;
}
}
}
while(1);
}
Make the scanf into like this.
scanf(" %c",&input);
Then While getting the input from the user using fgets It will place the new line character into that buffer. So this will lead to fails this condition.
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
So make the this condition into like this.
length=strlen(c)-1;// to skip the new line character
Or else to like this.
length=strlen(c);
if ( c[length] == '\n' )
c[length]='\0';
Output After placing this,
Enter the letter S to start the program:
S
Program start.
Enter 1 for Module A. Enter 2 for Module B. Enter here: 1
Module A Selected.
Make this in you code.
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
else if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
else
{
printf("\nInvalid option\n");
c[0]='\0'; // It is for satisfy the second while loop condition.
continue;
}
Note that the loop:
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
is limited to the one line by the semicolon at the end. The following code is not the body of the loop, despite indentation trying to pretend that it is.
Also note that getchar() returns an int, not a char; you cannot reliably assign the result to a char and then test it for EOF. Depending on the platform, you will either never detect EOF at all or you will misdetect EOF when some other character (often ÿ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS) is typed. You must use int ch;.
Here. I fixed the problem using the following code. This way the code does the following:
Scans letters 'S' or 's'. Keeps looping if these are not entered.
Scans either number 1 or 2. Keeps looping until either number is entered and then exits.
The program does not loop from the very beginning (by outputting "Enter 'S' to start program), if any number other than 1 or 2 in entered in part 2 of the program. This was the problem originally.
The following is the correct code:
#include <stdio.h>
#include <ctype.h>
int function();
char input,temp,c[64],ch,exit;
int i,invalid,num,index,flag,start;
start = 0;
invalid = 0;
num = 0;
size_t length = 0;
index = 0;
flag = 0;
int main()
{
do
{
puts("Enter the letter S to start the program: ");
scanf("%c", &input);
while( input!='\n' && (ch=getchar())!='\n' && ch!= EOF);
{
if(isalpha(input)==0)
{
printf("Invalid input. Please input something.\n");
continue;
}
if(input == 'S' || input == 's')
{
printf("\nProgram start.");
start = 1;
if(start == 1)
{
function();
return(0);
}
}
else
{
printf("\nInvalid input.");
continue;
}
}
}
while(1);
}
int function()
{
while( sscanf(c, "%d", &num) != 1)
{
length = 0;
flag = 0;
num = 0;
printf("\nEnter 1 for Module A. Enter 2 for Module B. Enter here: ");
fgets(c, 63, stdin);
length = strlen(c);
length --;
for(index = 0; index < length; ++index)
{
if(c[index] < '0' || c[index] > '9')
{
flag = 1;
break;
}
}
if( flag)
{
printf("\nInvalid character\n");
continue;
}
if( sscanf(c, "%d", &num) != 1)
{
printf("\nNo input detected.");
continue;
}
if(num == 1)
{
printf("\nModule A Selected.\n");
return(0);
}
else if(num == 2)
{
printf("\nModule B Selected.\n");
return(0);
}
else
{
printf("\nInvalid option\n");
c[0]='\0'; // It is for satisfy the second while loop condition.
continue;
}
}
}

Resources