Hey guys im trying to write a small program where the user has to put in a number between 1-9, anything else is an error, but I'm having trouble validating the input because if you put 12 it only reads the 1 and it goes in the loop. It has to be done using getchar() this is what have so far:
printf(%s,"please enter a number between 1 - 9);
int c;
c = getchar();
while(c != '\n') {
int count = 1;
count ++;
if ((c >= '0' && c <= '9') || count > 1) {
printf(%s, "Congrats!);
}
else
{
print(%s, "ERROR);
}
}
I'm also having problems validating the char into an int after it goes in. If i put in 5 i get 53.
Try changing count > 1 to count == 1, and initialize it to 0 rather than 1. That way you can keep count of the number of digits you have. Also, note that because you initialize count to 1 and then immediately increment it, count > 1 will always evaluate to true, so if you gave it any char it will always say it's correct.
getchar() will return the next character typed. If you want more than the first character you will need a call getchar() again within the while loop.
//Somewhere to store the result
//initialized with an invalid result value
int digitchar = 0;
//Get the first char
int c = getchar();
while (c != '\n')
{
//Check if we already have a digit
//and that the new char is a digit
if (digitchar == 0 && c >= '1' && c <= '9')
{
digitchar = c;
}
//Get the next char
c = getchar();
}
//Check if we have stored a result
if (digitchar != 0)
{
//Success
}
Note this doesn't handle if a non-digit or newline character is entered. You would need to handle that as an error as well as if more than one digit is entered.
This is not working with 12 because getchar() takes one character per time.The following example is one way to solve it.
printf("please enter a number between 1 - 9");
int c[10], count=1;
//Declare an array because user may insert a bigger number
char number;
//This loop allow the user to enter an input
for(i=0;i<10;i++){
number = getchar();
if (number != ' '){
c[i] = atoi(number);
sum = sum + c[i];
}
else if(number == ' '){
//Terminate the loop when user stop typing
break;
}
else if( sum > 9 || sum < 0){
//Start loop again until user enter valid input
printf("You entered a number out of field try again\n");
continue;
}
}
while(c != '\n') {
count ++;
if ((c >= '0' && c <= '9') || count > 1) {
printf("%d Congrats!",c);
}
else
{
printf(" %d ERROR", c);
}
}
Remember that getchar() returns the ascii value of the char, thus when you pass the value to the function you must subtract char '0' to pass the actual decimal value into the function.
Another point is that you must clear the input buffer. If your user enters wrong input, you have to make sure that there is nothing left on the input buffer before you try to read input again.
Hope this helps.
int main(void) {
int input = 0; // 0 is the sentinel value to close program
printf("\n%s\n", "Enter value between 1-9 .\nEnter [0] to finish.");
do {
input = getchar();
if (((input>= '1') && (input <= '9') || input == '0') && getchar() == '\n') {
if ((input >= '1') && (input <= '9')) {
callYourOwnFuntionAndPassValue(input - '0');
printf("\n%s\n", "Enter value between 1-9 .\nEnter [0] to finish.");
}
}
else {
while (getchar() != '\n') {} // clear input buffer
printf("\n%s\n", "Please enter a valid number");
}
} while (input != END_PROGRAM);
return NO_ERROR; // NO_ERROR = 0
}
Related
Brand new C coder here. In my first C course in school. I have experience in java but this course is all in C. I have homework to create a program that reads the contents of a file and counts the number of upper and lower case letters, vowels, consonants and digits. The program is not supposed to have any arguments, but will take a .txt file from the command line via redirection. My question is, how do I correct my current code to read from stdin each character of the file, whether it be a letter or a number? I'm really struggling with how read the contents of the file from stdin, read each character and then decide which category it belongs in. Any help would be appreciated. Thanks.
I'll be running the program like this...
$ program < testFile.txt
Where testFile.txt will contain the following text:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
int upper = 0; // Number of upper case letters
int lower = 0; // Number of lower case letters
int vowel = 0; // Number of vowels
int consonant = 0; // Number of constants
int digits = 0; // Number of digits
int total = 0; // Total number of characters in file
int i =0;
char value[100];
fgets(value, 100, stdin);
while(value[i] != '\0');
{
if (value[i] >= 'A' && value[i] <= 'Z')
{
upper++;
if (value[i] == 'A' || value[i] == 'E' || value[i] == 'I' || value[i] == 'O' || value[i] == 'U' || value[i] == 'Y')
{
vowel++;
}
else {
consonant++;
}
}
else if (value[i] >= 'a' && value[i] <= 'z')
{
lower++;
if (value[i] == 'a' || value[i] == 'e' || value[i] == 'i' || value[i] == 'o' || value[i] == 'u' || value[i] == 'y')
{
vowel++;
}
else {
consonant++;
}
}
else if (value[i] >= '0' && value[i] <= '9')
{
digits++;
}
total++;
i++;
}
printf("upper-case: %d", upper);
printf("\nlower-case: %d", lower);
printf("\nvowels: %d", vowel);
printf("\nconsonants: %d", consonant);
printf("\ndigits: %d", digits);
printf("\ntotal: %d", total);
printf("\n");
return 0;
I expect output to show how many upper case letters, lower case letters etc.
But once I run $ program < testFile.txt, it just sits there, no output to command line or anything.
Remove the semicolon after the while statement. :-)
while(value[i] != '\0');
This is your most obvious problem, it basically means:
while value[i] != '\0':
do nothing
end while
In other words, if it enters the loop, it will never exit it, because nothing changes that would affect the condition under which the loop continues.
There are other problems as well such as the fact that you will only process the first line rather than the whole file. The whole idea of using fgets and processing a line is unnecessary when you can just start with the following filter skeleton:
int ch;
while ((ch = getchar()) != EOF) {
/* process ch */
}
This will process an entire file character by character until all characters are done (or until an error occurs) so you can just tailor the body loop to do what you need - you've basically done that bit in your code with the loop over the line characters.
I would suggest not using the following code (since this is classwork) but you can also make better use of flow control constructs and library functions (from ctype.h and string.h), something like:
while ((ch = getchar()) != EOF) {
// Lib functions to detect upper/lower-case letters.
if (isupper(ch)) {
++upper;
} else if (islower(ch))
++lower;
}
// And to detect letter/digit type.
if (strchr("aeiouAEIOU", ch) != NULL) {
++vowel;
} else if (isalpha(ch)) {
++consonant;
} else if (isdigit(ch)) {
++digits;
}
++total;
}
This is particularly important since there's no actual guarantee that non-digit characters will be consecutive.
My assignment is to write the last name of a doctor with only small letters and end it with a dot ('.') that the user will print with the output. The expended assignment is to build a system for medical appointments:
#include<stdio.h>
#include<stdlib.h>
int main(){
fflush(stdin);
int count = 0, flag = 0;
char Nameplate; //last name of the doctor
printf("Please enter the last name of your doctor(please type with only small letters):\n");
Nameplate = getchar();
do{
Nameplate = getchar();
} while (Nameplate >= 'a' && Nameplate <= 'z' && Nameplate == '.');
if (!(Nameplate >= 'a' && Nameplate <= 'z' && Nameplate == '.')){
flag = 1;
}
else if (Nameplate == '\n'){
flag = 0;
count++;
}
if (flag == 1){
printf("Invalid input,");
fflush(stdin);
main();
}
else if (flag == 0){
printf("\n Your appointment has been successfully canceled.\n\n");
}
return 0;
}
Now, this code is not working. It is working if I do not use the dot, but when I enter the dot, the problems start.
Try
while ((Nameplate >= 'a' && Nameplate <= 'z') || (Nameplate == '.'))
instead of
while (Nameplate >= 'a' && Nameplate <= 'z' && Nameplate == '.')
Even with a change in the test for lower case letters and period, you still have a potential problem because the user might have a period in the name, but still not have a period at the end.
This code checks for lower case letters only, excluding the last character, and then tests that the last character is a period.
Also there is some control on name length.
int main()
{
int flag, n;
char *Nameplate = malloc(22); //last name of the doctor
fflush(stdin);
while(1) {
printf("Please enter the last name of your doctor(please type with only small letters):\n");
printf("End name with a period/full stop\n");
fgets(Nameplate, 20, stdin);
/* test for all valid lower case letters */
flag = 0;
for(n = 0; n < strlen(Nameplate) - 2; n++) {
if (!('a' <= Nameplate[n] && Nameplate[n] <= 'z')) {
/* not a lower case character */
flag = 1;
break;
}
}
/* now test for terminating period */
if(Nameplate[strlen(Nameplate) - 2] != '.') {
/* no period at end of name */
flag = 2;
}
/* handle errors or accept */
if(flag == 1) {
printf("small letters only\n");
} else if (flag == 2) {
printf("remember to end with a period/full stop\n");
} else {
/* name was all lower case with terminating period so exit input */
break;
}
}
printf("\n Your appointment with %s has been successfully canceled.\n\n", Nameplate);
free(Nameplate);
return 0;
}
If I understand you want to enter a doctor's name to set an appointment, only handle lower-case characters, and if the last character is a '.' cancel the appointment, you can rearrange your logic slightly and accomplish that goal while still preserving middle-initial punctuation.
Additionally, any time you are taking input, provide a prompt for your user so they are not sitting there looking at a blinking cursor wondering if the program hung.
When handling upper/lower-case conversion, there is no reason to force the user to enter in only one or the other. You can simply check/convert whatever input they provide in a transparent fashion. The ctype.h header file holds the tolower and toupper character conversions, or you can simply understand that the 6th-bit in 7-bit ASCII is the case-bit and toggle it as needed to accomplish the case-conversion.
This is just one example, there are many ways to put the pieces together:
#include <stdio.h>
#define MAXC 64
int main (void) {
int c = 0, cnx = 0, i = 0;
char name[MAXC] = "";
printf ("\n enter doctor's name (end with '.' to cancel): ");
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF)
if (('a' <= c && c <= 'z') || c == '.' || c == ' ')
name[i++] = c; /* add to name */
else if ('A' <= c && c <= 'Z') /* if upper-case */
name[i++] = c ^ (1u << 5); /* convert to lower */
if (i && name[i-1] == '.') { /* last is '.' */
cnx = 1; /* set cancel flag */
name[--i] = 0; /* overwrite last '.' */
}
else
name[i] = 0; /* nul-terminate name */
if (cnx) /* appointment canceled */
printf ("\n Your appointment with doctor '%s' has been canceled.\n\n",
name);
else /* new appointment */
printf ("\n You have a new appointment with doctor '%s'.\n\n", name);
return 0;
}
Use/Output
$ ./bin/appointment
enter doctor's name (end with '.' to cancel): John J. Marks
You have a new appointment with doctor 'john j. marks'.
$ ./bin/appointment
enter doctor's name (end with '.' to cancel): John J. Marks.
Your appointment with doctor 'john j. marks' has been canceled.
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;
}
}
}
For example :I want to terminate inputting without using (ctrl+d or pressing any character) as doing this cause the program to execute and the second scanf() does not work.I am not allowed to input number of elements in the array.
for(i=0;a[i]<10000;i++)
{
if(scanf("%d",&a[i])==1)
count++;
}
for(j=0;a[j]<10000;j++)
{
if(scanf("%d",&b[j])==1)
count1++;
}
You can do something like that:
for(i=0;a[i]<10000;i++)
{
// chack that input correct
if((scanf("%d",&a[i])==1)
{
count++;
}
else // if input is incorrect
{
// read first letter
int c = getchar();
if( c == 'q' )
{
break; // stop the loop
}
// clean the input buffer
while( getchar() != '\n' );
}
}
and when you want to stop entering just enter letter q instead of number
If you want to come out of first loop when scanf() reads a character, then you may consider reading integers using getchar(). You may add an extra condition to that function in the link to mark a flag when some particular character is entered.
For example if you want to end the loop when input is X, you can use something like this
int get_num()
{
int num = 0;
char c = getchar_unlocked();
while(!((c>='0' && c<='9') || c == 'X'))
c = getchar_unlocked();
if(c == 'X')
return 10001;
while(c>='0' && c<='9')
{
num = (num<<3) + (num<<1) + c -'0';
c = getchar_unlocked();
}
return num;
}
//------------//
for(i=0;;i++)
{
temp = get_num();
if(temp < 10000)
count++;
else
break;
}
for(j=0;;j++)
{
temp = get_num();
if(temp < 10000)
count1++;
else
break;
}
I am doing a lab for an intro programming class
I have to make sure that an integer is entered. I thought this would do it but when I put in a letter it repeats in an endless loop.
I found this solution in another post
int num;
char term;
if (scanf("%d%c", &num, &term) != 2 || term != '\n')
printf("failure\n");
else
printf("valid integer followed by enter key\n");
But im not sure what I did wrong. Why is it not working in my code?
#include <stdio.h>
int main(void)
{
int oneVar;
char term;
double numOne;
double numTwo;
double sum;
double dif;
double quo;
double mult;
int checker = 1;
do
{
printf("Please choose one of the following:\n""1) Add\n""2) Subtract\n""3) Divide\n""4) Multiply\n""5) Quit\n");
if (scanf("%d%c" , &oneVar ,&term) != 2 || term != '\n')
{
printf ("This is not valid input\n\n");
checker = 1;
}
else if (oneVar == 5)
{
printf("Thank you. Goodbye.\n");
checker = 0;
}
else if (oneVar != 1 && oneVar !=2 && oneVar != 3 && oneVar != 4)
{
printf("This is not a valid input\n\n");
checker = 1;
}
else
{
printf("Please enter the first number:\n");
if (scanf("%lf%c" , &numOne ,&term) != 2 || term != '\n')
{
printf ("This is not valid input\n\n");
checker = 1;
}
printf("Please enter the second number:\n");
if (scanf("%lf%c" , &numTwo ,&term) != 2 || term != '\n')
{
printf ("This is not valid input\n\n");
checker = 1;
}
else if (oneVar == 1)
{
sum = numOne + numTwo;
printf("The sum is: %.2lf\n" ,sum);
checker = 0;
}
else if (oneVar == 2)
{
dif = numOne - numTwo;
printf("The difference is: %.2lf\n" ,dif);
checker = 0;
}
else if (oneVar == 3)
{
quo = numOne / numTwo;
printf("The quotient is: %.2lf\n" ,quo);
checker = 0;
}
else if (oneVar == 4)
{
mult = numOne * numTwo;
printf("The product is: %.2lf\n" ,mult);
checker = 0;
}
else if (oneVar == 5)
{
printf("Thank you. Goodbye.\n");
checker = 0;
}
}
} while (checker == 1);
return(0);
}
My prof posted this Im not sure how it helps but I thought it might help someone
To make sure that a user-input number is an integer you can use the notion of casting. Casting is a way to tell C to treat a variable as if it were a variable of a different type.
so, if I have something like this:
double myDouble;
myDouble = 5.43;
printf ("%d", (int) myDouble);
It will tell C to print myDouble, but to treat it like an integer. Only the 5 will be printed and you won't get any type mismatch errors. You can use casting to check to see if an input number is an integer by comparing the input to the (int) cast of the number. Something like this should work:
if(inputNum == (int) inputNum)
You'll still get 1.0 and 2.0 passing as valid numbers, but that is ok for now.
Why complicate things?
char x = 0;
scanf("%c", &x);
if (x >= 0x41 && x <= 0x7A)
printf("you entered a letter");
In ASCII table, letters have values between 0x41 ("A") and 0x7A ("z").
So, you just need to check the ASCII value of the input. :)
Using the %c to "consume" the end of line is not a good solution. If the user enters say:
123 abc<newline>
num will be 123, but term will be the space character. If you enter a letter rather than a number, the scan will stop without consuming any of the characters, the next input call will return due to the already buffered line, and may still consume nothing. Your program loops continuously because every input statement is failing to consume the newline and returns immediately. The standard input functions wait for a complete line before returning, if the line is not read completely, input functions do not need to wait.
There are a number of solutions, many of which such as the one you used are flawed, the method below, forces the input buffer to be flushed up to and including the newline.
int check = scanf( "%d", &num ) ;
while( getchar() != '\n' )
{
// do nothing
}
if( check != 2 )
printf("failure\n");
else
printf("valid integer followed by enter key\n");
If you use the %c format specifier at the end of the input, then a slightly different flush is necessary since the character input may be a newline:
int check = scanf( "%c", &ch ) ;
while( ch != '\n' && getchar() != '\n' )
{
// do nothing
}