Using arrays to compare char - c

I'm coding this pattern game, but I am having difficulties in storing the previous input of the users "uno" and "dos" to a array so it can be compared, if same it will ask for another input which has not been picked. Example of This
Round 1:
Player 1 Inputs : -> A
Player 2 Inputs : -> B
Valid
Round 2:
Player 1 Inputs : -> L
Player 2 Inputs : -> V
Valid
Round 3:
Player 1 Inputs : -> A (Invalid Already been used)
enter char again
That above is an example i am trying to achieve. I will post the code below. I would appreciate the help very much.
#include <stdio.h>
#include <string.h>
#define SWITCH(_g0,_g1) \
(_g0 << 8) | (_g1 << 0)
#define CASE(_g0,_g1) \
case SWITCH(_g0,_g1)
intgetval(const char *prompt)
{
char *cp;
char buf[100];
int val;
while (1) {
printf("%s: ",prompt);
fflush(stdout);
cp = fgets(buf,sizeof(buf),stdin);
// handle end of file
if (cp == NULL) {
val = -1;
break;
// get the first char on the line
val = buf[0];
if (val != '\n')
break;
}
return val;
}
int main ()
{
int i = 0;
int roundCount = 1;
int pos = 0;
int over = 0;
int f = 1;
char G[9];
char uno,dos;
printf("Game Start!\n");
do {
printf("Round %d!\n", roundCount++);
printf("Input selection upon prompt.\n");
printf("Player 1: ");
scanf(" %c", &uno );
printf("Player 2: ");
scanf(" %c", &dos);
if()
//printf("DEBUG: %2.2X %2.2X\n",G[0],G[1]);
switch (SWITCH(uno,dos)) {
CASE('L','V'):
CASE('V','S'):
CASE('S','P'):
CASE('P','R'):
CASE('R','L'):
CASE('R','S'):
CASE('P','V'):
CASE('S','L'):
CASE('V','R'):
CASE('L','P'):
f++;
pos--;
printf("Uno Wins! Pos[%d]\n\n", pos);
break;
CASE('R','P'):
CASE('L','R'):
CASE('R','V'):
CASE('P','S'):
CASE('P','L'):
CASE('S','R'):
CASE('S','V'):
CASE('L','S'):
CASE('V','P'):
CASE('V','L'):
f++;
pos++;
printf("Dos Wins Pos[%d]!\n\n", pos);
break;
CASE('R','R'):
CASE('P','P'):
CASE('S','S'):
CASE('L','L'):
CASE('V','V'):
f++;
pos = pos;
break;
}
if (pos == -3 || pos == 3) {
printf("Game over\n");
break;
}
if (f == 5 && pos != -3 && pos != 3) {
switch (SWITCH(uno,dos)) {
CASE('L','V'):
CASE('V','S'):
CASE('S','P'):
CASE('P','R'):
CASE('R','L'):
CASE('R','S'):
CASE('P','V'):
CASE('S','L'):
CASE('V','R'):
CASE('L','P'):
printf("Uno:Wins!\n");
break;
CASE('R','P'):
CASE('L','R'):
CASE('R','V'):
CASE('P','S'):
CASE('P','L'):
CASE('S','R'):
CASE('S','V'):
CASE('L','S'):
CASE('V','P'):
CASE('V','L'):
printf("Dos Win!\n");
break;
}
}
} while (f < 5);
return 0;
}
im trying to implement a for loop for this but it wouldn't work , i am not getting the result that i want, adding this code. I would appreciate it if you would rewrite the code with this loop or if there is any other way please tell me how.
for ( i = 0; i < sizeof(useduno); i++)
{
if (uno == useduno[i]) // where useduno is the array, where uno is to be stored, so it cannot be used again
{
printf("You already used the letter. Use another letter: ");
scanf(" %c", &uno);
}
}

Related

How to separate a string by spaces and save the separated words regardless?

I have a program that separates words by spaces. I need to count which words in the text contain 4 different vowels. It didn't seem complicated, until I realized that I know how to save the divided words of the function (strtok) that returns the separated words, and of course, I can't count a single word because the function only prints. I don't know how to save the word individually to calculate how many vowels it contains and continue with the other words, one by one.
#include <stdio.h>
#include <string.h>
#define MAX 100
int main() {
char phase[MAX];
char temp [50];
char delim[] = " ";
printf("Ingrese un texto corto: ");
gets(phase); //Short text with spaces
printf("\n");
for (i = 0; x < phase[x] != '\0'; ++x) {
if (phase[x] == ' ' || phase[x] == '\t' || phase[x] == '\v') {
//Detect space.
}
}
char *ptr = strtok(phase, delim);
while (ptr != NULL) {
printf("%s\n", ptr); //I need to keep all the words separate.
ptr = strtok(NULL, delim);
}
return 0;
}
Result:
Ingrese un texto corto: Ana come en el refrigerador.
Ana
come
en
el
refrigerador.
I believe this code will solve the task. It's tempting to use strtok() again to search for vowels, but that would erase any information about word bounds from strtok's internal memory. So, instead, use strpbrk() (docs and more docs)
#include <stdio.h>
#include <string.h>
#define MAX 100
int main() {
char text[MAX];
// all isspace() characters for "C" locale
char delimiters[] = " \t\n\v\f\r";
char vowels[] = "aeiou";
printf("Input a string of text: ");
// replaced unsafe gets() with more safe fgets()
fgets(text, sizeof(text), stdin);
char* word = strtok(text, delimiters);
while (word != NULL) {
// strpbrk() does roughly the same thing as strtok(), but it doesn't
// modify a string nor does it remember anything on future calls
char* ptr_to_vowel = word;
int count = 0;
while (NULL != (ptr_to_vowel = strpbrk(ptr_to_vowel, vowels))) {
count++;
// otherwise we'd stay on the same vowel
ptr_to_vowel++;
}
printf("found %d vowels in %s\n", count, word);
word = strtok(NULL, delimiters);
}
return 0;
}
A few issues:
The for loop for counting spaces is incorrect.
We should have a separate function to count vowels.
Never use gets (use fgets instead).
The code did not preserve the original buffer as the code comments suggested.
I need to count which words in the text contain 4 different vowels.
So, we can only count unique vowels in a word (e.g.):
fleece has only 1 unique vowel and not 3.
great has 2 vowels
greet has 1 vowel
incombustible has 4 [unique] vowels and not 5.
It's not totally clear, but I interpret this to mean that a candidate word has at least 4 unique vowels (i.e. it could have 5)
I had to refactor quite a bit of the code. It is annotated:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <ctype.h>
#define MAX 100
// vcount -- count _unique_ vowels
// RETURNS: number of _unique_ vowels
int
vcount(const char *str)
{
const char *vowels = "aeiou";
int vfreq[5] = { 0 };
int vsum = 0;
// loop through all chars in string
for (int chr = *str++; chr != 0; chr = *str++) {
// get lower case
chr = tolower((unsigned char) chr);
// is it a vowel?
const char *vptr = strchr(vowels,chr);
if (vptr == NULL)
continue;
// get index into frequency table
ptrdiff_t vidx = vptr - vowels;
// have we seen it before?
if (vfreq[vidx])
continue;
// mark as already seen
vfreq[vidx] = 1;
// count new unique vowel
++vsum;
}
return vsum;
}
int
main(void)
{
char phrase[MAX];
char temp[MAX];
const char *delim = " \t\v";
printf("Ingrese un texto corto: ");
// Short text with spaces
// NOTE/BUG: _never_ use gets
#if 0
gets(phrase);
#else
fgets(phrase,sizeof(phrase),stdin);
#endif
printf("\n");
// NOTE/BUG: loop condition is incorrect
#if 0
for (i = 0; x < phrase[x] != '\0'; ++x) {
if (phrase[x] == ' ' || phrase[x] == '\t' || phrase[x] == '\v') {
// Detect space.
}
}
#else
int space_count = 0;
for (int i = 0; phrase[i] != '\0'; ++i) {
switch (phrase[i]) {
case ' ':
case '\t':
case '\v':
++space_count;
break;
}
}
printf("Spaces: %d\n",space_count);
#endif
// I need to keep all the words separate.
#if 0
char *ptr = strtok(phrase, delim);
#else
strcpy(temp,phrase);
char *ptr = strtok(temp, delim);
#endif
while (ptr != NULL) {
#if 0
printf("%s\n", ptr);
#else
printf("%s -- has enough vowels: %s\n",
ptr,(vcount(ptr) >= 4) ? "Yes" : "No");
#endif
ptr = strtok(NULL, delim);
}
return 0;
}
In the above code, I used cpp conditionals to denote old vs new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
For the input:
Ana come en el refrigerador.
Here is the program output:
Ingrese un texto corto:
Spaces: 4
Ana -- has enough vowels: No
come -- has enough vowels: No
en -- has enough vowels: No
el -- has enough vowels: No
refrigerador. -- has enough vowels: Yes
Instead of splitting words and then count vowels inside them, you can count vowels and upon a delimiter, check the vowel count and reset the count. This way, you do not need to modify the string. You actually do not even need an array to store the string: you can just read one byte at a time.
Here is a modified version:
#include <stdio.h>
int main() {
int mask = 0;
int vowels = 0;
int matches = 0;
int done = 0;
printf("Ingrese un texto: ");
while (!done) {
switch (getchar()) {
case EOF:
case '\n':
if (vowels >= 4)
matches++;
vowels = mask = 0;
done = 1;
break;
case ' ':
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
if (vowels >= 4)
matches++;
vowels = mask = 0;
break;
case 'a':
case 'A':
if (!(mask & 1)) {
mask |= 1;
vowels++;
}
break;
case 'e':
case 'E':
if (!(mask & 2)) {
mask |= 2;
vowels++;
}
break;
case 'i':
case 'I':
if (!(mask & 4)) {
mask |= 4;
vowels++;
}
break;
case 'o':
case 'O':
if (!(mask & 8)) {
mask |= 8;
vowels++;
}
break;
case 'u':
case 'U':
if (!(mask & 16)) {
mask |= 16;
vowels++;
}
break;
}
}
printf("%d\n", matches);
return 0;
}
Here is an alternative without a switch statement:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main() {
int mask = 0;
int vowels = 0;
int matches = 0;
const char *vowels = "aAeEiIoOuU";
printf("Ingrese un texto: ");
while (!done) {
int c = getchar();
if (c == EOF || isspace(c)) {
if (vowels >= 4)
matches++;
vowels = mask = 0;
if (c == '\n' || c == EOF)
done = 1;
} else {
char *p = memchr(vowels, c, 10);
if (p != NULL) {
int bit = 1 << ((p - vowels) / 2);
if (!(mask & bit)) {
mask |= bit;
vowels++;
}
}
}
}
printf("%d\n", matches);
return 0;
}

Re-assign value to variable if rand() repeats a number

I am making a tic tac toe game in which the user competes against the computer. Whenever the person chooses a spot between 1 and 9, the computer needs to choose one too. For this, I am using rand(). However, if the spot is already taken, I need the computer to calculate a new one. I've tried using while and do-while loops but when I apply them, cmd stops working and doesn't let me continue the game.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct symbol{
int marcado;
char simbolo;
} SPOT;
SPOT casilla1 = {0,'1'};
SPOT casilla2 = {0,'2'};
SPOT casilla3 = {0,'3'};
void table();
void User();
void AI();
int main(){
system("cls");
User();
AI();
Check();
return 0;
}
void table(){
printf("\n %c | %c | %c ",spot1.symbol,spot2.symbol,spot3.symbol);
}
this is the function in which the user chooses a spot:
void User(){
char choice;
do{
do{
board();
printf("\n\nChoose a spot: ");
fflush(stdin);
scanf("%c",&choice);
}while(choice < '1' || choice > '3');
switch(choice){
case '1': if(choice == '1'){
system("cls");
if(casilla1.marcado == 1){
printf("\noccupied\n");
}
else if(casilla1.marcado == 0){
casilla1.marcado = 1;
casilla1.simbolo = 'X';
AI();
}
}
break;
case '2': if(choice == '2'){
system("cls");
if(casilla2.marcado == 1){
printf("\noccupied\n");
}
else if(casilla2.marcado == 0){
casilla2.marcado = 1;
casilla2.simbolo = 'X';
AI();
}
}
break;
case '3': if(choice == '3'){
system("cls");
if(casilla3.marcado == 1){
printf("\noccupied");
}
else if(casilla3.marcado == 0){
casilla3.marcado = 1;
casilla3.simbolo = 'X';
AI();
}
}
break;
}while(Check() != 0 && Check() != 1);
}
and this is the function for the computer. In which I am having trouble in the 'else if' statements since I don't know what to put in them.
void AI(){
int random;
srand(time(NULL));
random = rand() % 3 + 1;
if (random == 1){
if(casilla1.marcado == 0){
casilla1.simbolo = 'O';
casilla1.marcado = 1;
}
else if(casilla1.marcado == 1){
random = rand() % 3 + 1
}
}
if (random == 2){
if(casilla2.marcado == 0){
casilla2.simbolo = 'O';
casilla2.marcado = 1;
}
else if(casilla2.marcado == 1){
random = rand() % 3 + 1;
}
}
if (random == 3){
if(casilla3.marcado == 0){
casilla3.simbolo = 'O';
casilla3.marcado = 1;
}
else if(casilla3.marcado == 1){
random = rand() % 3 + 1;
}
}
}
As I said before, I've tried putting the whole AI() inside the different types of loops, putting only rand() inside them, and so on, and still can't get it to work.
First, choose your data structures better. Instead of:
SPOT casilla1 = {0,'1'};
SPOT casilla2 = {0,'2'};
SPOT casilla3 = {0,'3'};
use
SPOT casilla[3] = { {0,'1'}, {0,'2'}, {0,'3'} };
As a consequence, the switch constructs are not needed any longer. Instead of:
if(casilla1.marcado == 0){
if(casilla2.marcado == 0){
if(casilla3.marcado == 0){
use:
if(casilla[random-1].marcado == 0){
the person chooses a spot between 1 and 9
and
random = rand() % 9 + 1;
You only have 3 casilla. Where are the other 6?
I've tried using while and do-while loops
In AI() there are no loops. Maybe you can show us a code with loops?
printf("\n\nChoose a spot: ");
fflush(stdin);
You probably wanted to fflush() stdout?

Verifying integer input in a union in C

I'm trying to verify that what a user inputs in to one section of a union is actually an integer. I have been trying to use the isdigit function (see below) but I am having no success. All I need to do is make sure the user enters ONLY numbers for the date, but I am having a lot of trouble with it.
My code:
#define STRSIZE 30
#define PROFSIZE 30
#define NBRASSI 2
#define TRUE 1
#define FALSE 0
struct assignment
{
char name[STRSIZE];
char prof[PROFSIZE];
int duedate;
float value;
};
.
.
.
struct assignment populate_structure(struct assignment assi[], int assi_nbr)
{
int count;
int date_check = FALSE;
for (count = 0; count < assi_nbr; count++)
{
flushall();
printf("Enter Assignment #%d name (max %d chars):\n", count + 1,
STRSIZE);
gets(assi[count].name);
while (date_check == FALSE)
{
printf("Enter due date for Assignment #%d (YYYYMMDD):\n",
count + 1);
scanf("%d", &assi[count].duedate);
if (isdigit(assi[count].duedate))
{
date_check = TRUE;
}
else
{
printf("Invalid");
date_check = FALSE;
}
}
printf("Enter %% of final grade for Assignment #%d:\n", count + 1);
scanf("%f", &assi[count].value);
flushall();
printf("Enter Professor's name for Assignment #%d (max %d chars):\n",
count + 1, PROFSIZE);
gets(assi[count].prof);
printf("\n\n");
}
return assi[count];
}
It gives me no errors in Visual Studio, but when I run the program I get an Abort error whenever ANY value is input for assi[].duedate
If I remove if (isdigit(assi[count].duedate)), the program runs fine (so long as they only input an integer for duedate). Any help is greatly appreciated.
As the commenters already noted: isdigit() is for single characters only. Also: the way you use scanf() already assures the result to be a number.
But you should read a string instead, it is easier to test. For example
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int c;
int position = 0;
int res;
char date[9] = {'\0'};
char input[20] = {'\0'};
puts("try if date is in the format \"YYYYMMDD\"");
res = scanf("%19s",input);
if(res != 1){
fprintf(stderr,"input was a mess, aborting\n");
goto __FAILURE;
}
c = input[position];
while(c != '\0'){
switch(position){
case 0:
if( c == '2' || c == '1' ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 1:
if( c == '9' || c == '0' ){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 2:
if( isdigit(c) ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 3:
if( isdigit(c) ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 4: // month
if( c == '0' || c == '1' ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 5: // month
if( isdigit(c) ){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 6: // day
if( c == '0' || c == '1' || c == '2' || c == '3'){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 7: // day
if( isdigit(c)){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
default:
break;
}
c = input[++position];
}
printf("Date was correct and is %s\n",date);
exit(EXIT_SUCCESS);
__FAILURE:
printf("Date was wrong at position %d with character %c or just too short/long\n",position,c);
exit(EXIT_FAILURE);
}
Fill out the rest (check if date is valid and in the correct range). You could also part the date into individual year/month/day sections instead of putting the string into another string and convert them into numbers via atoi ( you can use atoi `because you already made sure to have a valid number) or by converting manually inside the switch without extra variables and functions. Checking ranges arithmetically is simpler than comparing strings/characters.
Here is my offering - any invalid entry calls exit(1) though a better error handler would be preferred. The data is entered as a string, and then extracted and validated.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct {
int year;
int month;
int day;
} mydate_t;
int main(void){
int i;
mydate_t dat = {0};
int dayspermon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char str[12];
printf("Enter a date (YYYYMMDD): ");
fflush(stdout);
if(fgets(str, sizeof str, stdin) == NULL) {
exit(1);
}
for(i=0; i<8; i++) {
if(!isdigit(str[i])) {
exit(1); // also fails when the string is too short
}
}
// extract
for(i=0; i<4; i++) {
dat.year = dat.year * 10 + str[i] - '0';
}
for(i=4; i<6; i++) {
dat.month = dat.month * 10 + str[i] - '0';
}
for(i=6; i<8; i++) {
dat.day = dat.day * 10 + str[i] - '0';
}
// validate
if(dat.year < 2000 || dat.year > 3000) // arbitrary range
exit(1);
if(dat.year % 4 == 0 && (dat.year % 100 != 0 || dat.year % 400 == 0)) {
dayspermon[1]++; // leap year adjustment
}
if(dat.month < 1 || dat.month > 12)
exit(1);
if(dat.day < 1 || dat.day > dayspermon[dat.month - 1])
exit(1);
printf("Date: %04d %02d %02d\n", dat.year, dat.month, dat.day);
}

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;
}
}
}

Logic in detecting int in C

I would appreciate some help with this. I'm trying to create this simple program that repeatedly loops asking for the user to enter in an int. If he enters an int, it exits but if he enters something else or bigger than int (ex.4gs4r33) it will loop again asking to enter an int. This is what I have tried, and it's not working. It says it's an int even if it's not.
#include<stdio.h>
unsigned int findInt();
int main() {
printf("Please input an int.\n");
findInt();
}
unsigned int findInt() {
char input;
long num = 0;
int b = 0;
do {
scanf("%c", &input);
if (isdigit(input)){
num = num*10+input+'0';
b = 1;
}
else if (input == '\n')
b = 1;
else
b = 0;
} while(input != '\n');
if (b == 1)
printf("Great!\n");
else{
printf("Not an int \n");
findInt();
}
return 0;
}
Two possible approaches. One would be to modify your code:
b = 1; // start off with good intentions…
do {
scanf("%c", &input);
if (isdigit(input)){
num = num*10+input -'0'; // *** SUBTRACT '0', don't add it!
}
else if (input != '\n') {
b = 0;
break; // *** break when you find non-digit
}
} while (input != '\n');
Two changes: getting the math right as you compute the integer, and fixing the logic (so you break out of your loop when you find a non digit character)
Second approach:
char buf[100];
char intAsString[100];
fgets(buf, 100, stdin);
sscanf(buf, "%d", num);
sprintf(intAsString, "%d\n", num);;
if(strcmp(buf, intAsString) == 0 ) {
printf("yay - you entered an integer!\n");
}
I'm sure you can figure out how that works.
update a complete code snippet that solves the issue of "loop logic" as well: you call the findInt function once from the top level, and it keeps going until you get the int. Note - in order for this to work properly, I read the entire input at once (rather than one at a time), then pick off the characters one by one using sscanf (and updating the pointer manually). It has a number of advantages - not least of which is that you start with a fresh input every time you call findInt, instead of having the rest of the input buffer that still needs reading (and which was giving rise to "no,no,no,great!" - as you would keep reading the bad input until you got to the newline, and accept that...)
#include<stdio.h>
#include <ctype.h>
unsigned int findInt();
int main() {
findInt();
}
unsigned int findInt() {
char input;
char buf[100];
char *temp;
long num = 0;
int b = 0;
printf("please enter an int:\n");
fgets(buf, 100, stdin);
temp = buf;
do {
sscanf(temp++, "%c", &input);
if (isdigit(input)){
num = num*10+input-'0';
b = 1;
}
else if (input == '\n')
{
b = 1;
break;
}
else {
b = 0;
break;
}
} while(input != '\n');
if (b == 1)
printf("Great! %d is an integer!\n", num);
else{
printf("Not an int \n");
findInt();
}
return 0;
}
In the else branch - i.e. not a digit or a newline - you set b to 0. Now if a digit DOES follow you reset that to 1.
You'll probably want to break or somehow record the permanent failure instead of just continuing.
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
void findInt(){
int x;
bool ok;
do{
char buff[32], *endp;
long long num;
ok = true;//start true(OK)
printf("Enter a number: ");
fgets(buff, sizeof(buff), stdin);
//strtoll : C99
x=(int)(num=strtoll(buff, &endp, 0));//0: number literal of C. 10 : decimal number.
if(*endp != '\n'){
if(*endp == '\0'){
printf("Too large!\n");//buffer over
while('\n'!=getchar());
} else {
printf("Character that can't be interpreted as a number has been entered.\n");
printf("%s", buff);
printf("%*s^\n", (int)(endp - buff), "");
}
ok = false;
} else if(num > INT_MAX){
printf("Too large!\n");
ok = false;
} else if(num < INT_MIN){
printf("Too small!\n");
ok = false;
}
}while(!ok);
}
,

Resources