This is the code i used to generate the number:
printf("%d\n", rand()%10);
I am creating a card game HiLo. I want to know how to store the number generated from that and then make the user guess wether the next number is going to be higher or lower than the previous. After that, another number is generated and not stored just yet. I want to compare the new number with the old number too see if the user is correct (alot points) and then store the new number.
You just want to use a variable. All variables may include alphabetic characters, as well as numeric characters, however the first character must be alphabetic. The concept of creating a variable is that you are creating an area of temporary storage for the successful operation of your program. Any areas of code using a particular variable are considered to be dependent on it, and variables work in "scopes". Scopes are started using the { character and are ended using the } character. Any variables declared between these characters are usable only within those characters, and not outside of them, as they do not exist except within those characters.
I have created an example of the program I believe you are trying to write in order to demonstrate the software programming practices involved in such a task.
The example is shown below:
#include <stdio.h>
#include <string.h>
#define LENGTH_OF_BUFFER 100
int main( int argc, char **argv )
{
int prevRandomNumber = rand() % 10;
int continuePlaying = 1;
while( continuePlaying == 1 )
{
int randomNumber = rand() % 10;
int userSelection = 0;
char lineBuffer[LENGTH_OF_BUFFER];
printf( "Previous random number %d\n", prevRandomNumber );
while( userSelection == 0 )
{
printf( "higher or lower?" );
gets( lineBuffer );
if ( strcmp( "higher", lineBuffer ) == 0 )
{
userSelection = 1;
printf( "You selected higher!\n" );
}
else if ( strcmp( "lower", lineBuffer ) == 0 )
{
userSelection = -1;
printf( "You selected lower!\n" );
}
else
{
printf( "Sorry, I didn't understand you, please check your input and try again!\n" );
}
}
if ( userSelection == 1 )
{
if ( randomNumber > prevRandomNumber )
{
printf( "Correct, you really are a marvel!\n" );
}
else
{
printf( "Incorrect, I pity you!\n" );
}
}
else if ( userSelection == -1 )
{
if ( randomNumber < prevRandomNumber )
{
printf( "Correct, you really are a marvel!\n" );
}
else
{
printf( "Incorrect, I pity you!\n" );
}
}
printf( "Number was %d\n", randomNumber );
printf( "Care to play again?\n" );
gets( lineBuffer );
prevRandomNumber = randomNumber;
if ( strcmp( "yes", lineBuffer ) != 0 )
{
continuePlaying = 0;
}
}
}
I hope this helps...
int number = rand()%10;
int nextNumber;
char choice;
while(choice != 'Q' && choice != 'q')
{
printf("Current Number is : %d",number);
printf("\nYou want to guess the next number : ");
printf("\nPress L if number will be greater than current number ");
printf("\nPress S if number will be smaller than current number ");
printf("\nPress Q if you want to quit playing : ");
Printf("\n\nEnter your choice : ")
scanf("%c",&choice);
nextNumber = rand()%10;
if(choice == 'L' || choice == 'l')
{
if(nextNumber > number)
{
printf("\nYour Guess is Right...");
}
else
{
printf("\nYour Guess is wrong...");
}
}
else if(choice == 'L' || choice == 'l')
{
if(nextNumber < number)
{
printf("\nYour Guess is Right...");
}
else
{
printf("\nYour Guess is wrong...");
}
}
else
{
printf("\nYour choice is invalid. Try Again...");
}
number = nextNumber;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(){
char* bet, cmd;
long random_number, new_random_number;
while (1)
{
srand(time(NULL));
random_number = rand();
printf("%d\n", random_number);
printf("bet if the next number is bigger (+) or lower (-): ");
scanf("%s",bet);
srand(time(NULL));
new_random_number = rand();
printf("%d\n", new_random_number);
/* TODO - you might want to put that into a function some how */
if ( bet[0] == '+')
{
if ( new_random_number >= random_number ) /* user is correct */
{
printf("yeah! you are right\n");
printf("\nlet's play again!!\n");
continue;
}
else
{
printf("trololol :P That was wrong\n");
printf("\nlet's play again!!\n");
continue;
}
}
if ( bet[0] == '-')
{
if ( new_random_number < random_number ) /* user is correct */
{
printf("yeah! you are right\n");
printf("\nlet's play again!!\n");
continue;
}
else
{
printf("trololol :P That was wrong\n");
printf("\nlet's play again!!\n");
continue;
}
}
}
}
/* vim: set et sw=4 ts=4: */
Related
I am having an issue with the output of my code, which is trying to return an array backwards in c using pointers. Do you guys have any solutions to the error I am getting?
Sample input:
Please enter the array size: 3
Please enter 3 elements:
4, 5, 7
Segmentation fault (core dumped)
Code:
#include <stdio.h>
int main(void){
int size, i;
int *pointer;
int arr[size];
printf("Please enter the array size: ");
scanf("%d/n", &size);
pointer = &arr[0];
printf("Please enter %d elements: \n", size);
for(i = 0; i < size; i++){
scanf("%d", arr[i]);
pointer++;
}
pointer = &arr[size - 1];
printf("The reversed array is \n");
for(i = size; i > 0; i--){
printf("%d", arr[i]);
pointer--;
}
return 0;
}
The task is not simple for beginners like you and me.
As I have understood the user can enter any number of integers in one line and all entered integers in the line must be outputted like
You entered 2
In this case neither array nor character array nor integer array will help. And in fact you need not to define an array if you want only to output numbers stored in the input buffer.
In this case you can just use the standard function getchar. Using the function in a loop you can read all numbers placed by the user in one line in the I/O buffer.
Here is a sample program. It is a little complicated because I allow the user to enter sign symbols.
There is no check in the program whether the user entered not a digit or a sign. You can develop the program further. The program demonstrates an approach to solve the task.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
printf( "Enter a seria of integer numbers in one line: " );
int c;
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n' )
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
}
The program output might look for example like
Enter a seria of integer numbers in one line: 1 -1 +12-12+13 +14 -15
You entered 1
You entered -1
You entered 12
You entered -12
You entered 13
You entered 14
You entered -15
If you want to enter several lines of numbers and output numbers that are present in each line then the program can look the following way
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
size_t i = 0;
while (1)
{
printf( "Enter a seria of integer numbers in one line (or press just Enter to exit): " );
int c = getchar();
if (c == EOF || c == '\n') break;
ungetc( c, stdin );
printf( "Line %zu contains the following numbers:\n", i++ );
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n')
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
putchar( '\n' );
}
}
The program output might look for example like
Enter a seria of integer numbers in one line (or press just Enter to exit): 1 -2 3 +4
Line 0 contains the following numbers:
You entered 1
You entered -2
You entered 3
You entered 4
Enter a seria of integer numbers in one line (or press just Enter to exit): 11-12 13+14
Line 1 contains the following numbers:
You entered 11
You entered -12
You entered 13
You entered 14
Enter a seria of integer numbers in one line (or press just Enter to exit):
As the program just outputs entered numbers then actually there is no need to build an object of the type int like
num = Base * num + c;
You could just output adjacent digits in a line.
int array[100];
int n;
scanf("%d", &n);
for(int i=0; i<n; i++) {
scanf("%d", &array[i]);
}
for(int i=0; i<n; i++) {
printf("You entered %d \n", array[i]);
}
We use the array to get all of the values, and just print them out at the end.
In C and C++ it does not matter if the values are separated by space or a newline, so you can get every integer in a single line if separated by spaces.
output
3
1 2 3
You entered 1
You entered 2
You entered 3
C makes this very easy, but you need to leverage some library functions. At the most simple:
use fgets() and strpbrk() to obtain and verify a line of text
use strtok() and strtol() to parse and verify integer values.
What you do with those values is up to you. Following your example prompt, let’s just print them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int error( const char * message, const char * value )
{
fprintf( stderr, "%s%s\n", message, value );
return 1;
}
int main()
{
printf( "Input: " );
// Get all input on a single line
char text[1000];
fgets( text, sizeof(text), stdin );
// Verify that the entire line of input was obtained
char * nl = strpbrk( text, "\r\n" );
if (!nl) return error( "Line too long!", "" );
*nl = '\0';
puts( "Output:" );
// For each whitespace-delimited (spaces, tabs) token in the line:
for (char * token = strtok( text, " \t" ); token; token = strtok( NULL, " \t" ))
{
// Attempt to convert it to an integer
char * nok;
int n = strtol( token, &nok, 10 );
if (*nok) return error( "Invalid integer value: ", token );
// Success!
printf( "You entered %d\n", n );
}
return 0;
}
Notice also how it is OK to create a little helper function (error()). You can make helpers as complex or simple as you need. For this helper, all we need was to complain with one or two strings and return an “error happened” exit code that main() can pass right to the shell.
fgets can be used to read a line.
strtol can parse integers and report overflow and invalid input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
int parselint ( char *line, int *value, char **end) {
long int number = 0;
errno = 0;
number = strtol ( line, end, 10);
if ( *end == line) {// nothing was parsed. no digits
size_t span = strcspn ( *end, "-+0123456789"); // characters to next int
if ( ! span) {
span = 1;
}
fprintf ( stderr, "problem parsing: %.*s\n", (int)span, line);
*end += span; // advance pointer to next int
return 0;// return failure
}
if ( ( errno == ERANGE && ( number == LONG_MAX || number == LONG_MIN))
|| ( errno != 0 && number == 0)) {// parsing error from strtol
fprintf ( stderr, "problem %.*s", (int)(*end - line), line);
perror ( " ");
return 0;
}
if ( number > INT_MAX || number < INT_MIN) {
fprintf ( stderr, "problem %.*s ", (int)(*end - line), line);
fprintf ( stderr, "out of int range\n");
return 0;
}
*value = number;//assign number to pointer
return 1;//success
}
int main ( void) {
char line[4096] = "";
char *parse = line;
int number = 0;
fgets ( line, sizeof line, stdin);
line[strcspn ( line, "\r\n")] = 0; // remove newline
while ( *parse) {
if ( 1 == parselint ( parse, &number, &parse)) {
printf ( "you entered %d\n", number);
}
}
return 0;
}
So I am trying to make a tic-tac-toe game in C and I've gotten most of the code written out, no error messages, but I want to know what code to add to get the computer to play the game as well. I just don't know what else to add here to make sure the game is interact-able and not just the user typing in one letter and being done. If anyone could help, that'd be appreciated! The code is below:
#include <time.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
system("clear");
const char ROWS = 3;
const char COLS = 3;
int rows, cols, tile = 1, choice;
for (rows = 0; rows < ROWS; rows++)
{
for (cols = 0; cols < COLS; cols++)
{
printf("[%d]", tile++);
}
printf("\n");
}
printf("\nWhere would you like to put your X: ");
scanf("%d", &choice);
tile = 1;
for (rows = 0; rows < ROWS; rows++)
{
for (cols = 0; cols < COLS; cols++)
{
if (tile == 1 || tile == 2 || tile == 3 || tile == 4 || tile == 5 || tile == 6 || tile== 7 || tile == 8 || tile == 9)
{
printf("[%d]", tile++);
}
if (choice == tile)
{
tile -= tile;
printf("[X]");
choice += 1000;
}
}
printf("\n");
}
return 0;
}
Instead of worrying about implementing a computer player, I think your first step shoud be to offer support for a second human player.
First, you will need some array to represent the state of the game board. A multi-dimensional array of type char seems appropriate, in which each char can have one of three values:
'E' for empty
'X' for first player
'O' for second player
You could define the array like this:
char board[3][3];
Also, you will need an additional variable to keep track of whose turn it currently is. A variable of type bool with the name first_players_turn would probably be appropriate. When it is the first player's turn, this variable should be set to true, otherwise to false.
I also suggest that you create your own function print_board for printing the game board to the screen.
You will also need a function evaluate_game_state in order to determine the state of the game, which can be one of the following:
The game is still undecided.
The game is a draw.
Player 1 has won.
Player 2 has won.
To represent these 4 possible game states, I recommend that you use an enum, like this:
enum game_state
{
GAMESTATE_UNDECIDED,
GAMESTATE_DRAW,
GAMESTATE_WINNER_PLAYER1,
GAMESTATE_WINNER_PLAYER2
};
You can now declare the function evaluate_game_state like this:
enum game_state evaluate_game_state( char board[3][3] );
As long as the function evaluate_game_state returns GAMESTATE_UNDECIDED, you will have to prompt the user for input in a loop.
Here is my implementation of everything stated above, which I have tested a bit and seems to work, but I have not tested all corner cases. I took over the function get_int_from_user from this answer of mine from another question, and made a slight modification, so that it accepts variadic arguments, so that I can pass a string containing %d to that function and it treats it as a printf format specifier. Although your implementation of using printf and scanf would also work, that solution has the disadvantage that scanf does not perform proper input validation, so I used my function get_int_from_user instead.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
enum game_state
{
GAMESTATE_UNDECIDED,
GAMESTATE_DRAW,
GAMESTATE_WINNER_PLAYER1,
GAMESTATE_WINNER_PLAYER2
};
void init_board( char board[3][3] );
void print_board( char board[3][3] );
enum game_state evaluate_game_state( char board[3][3] );
int get_int_from_user( const char *prompt, ... );
int main( void )
{
char board[3][3];
bool first_players_turn = true;
enum game_state gs;
init_board( board );
while ( ( gs = evaluate_game_state( board ) ) == GAMESTATE_UNDECIDED )
{
//prompt user for input until input is valid
for (;;)
{
int input;
print_board( board );
input = get_int_from_user(
"It is player %d's turn.\n"
"Please select a move (1-9): ",
first_players_turn ? 1 : 2
);
if ( 1 <= input && input <= 9 )
{
int x = ( input - 1 ) % 3;
int y = ( input - 1 ) / 3;
//make sure field is empty
if ( board[y][x] != 'E' )
{
printf( "That field is already occupied!\n\n" );
continue;
}
//perform the move
board[y][x] = first_players_turn ? 'X' : 'O';
first_players_turn = !first_players_turn;
break;
}
printf( "Input must be between 1 and 9!\n\n" );
}
}
//game is over
print_board( board );
switch ( gs )
{
case GAMESTATE_DRAW:
printf( "The game is a draw.\n\n" );
break;
case GAMESTATE_WINNER_PLAYER1:
printf( "Player 1 wins!\n\n" );
break;
case GAMESTATE_WINNER_PLAYER2:
printf( "Player 2 wins!\n\n" );
break;
}
}
void init_board( char board[3][3] )
{
for ( int i = 0; i < 3; i++ )
for ( int j = 0; j < 3; j++ )
board[i][j] = 'E';
}
void print_board( char board[3][3] )
{
printf( "\n\n" );
for ( int i = 0; i < 3; i++ )
{
for ( int j = 0; j < 3; j++ )
{
//add spacing if necessary
if ( j != 0 )
printf( " " );
if ( board[i][j] == 'E' )
//replace empty field with number of field
printf( "%d", (i*3) + (j+1) );
else
printf( "%c", board[i][j] );
}
//end the line
printf( "\n" );
}
printf( "\n" );
}
enum game_state evaluate_game_state( char board[3][3] )
{
//check for horizontal wins
for ( int i = 0; i < 3; i++ )
{
char possible_winner = board[i][0];
if ( possible_winner != 'E' )
{
if ( possible_winner == board[i][1] && possible_winner == board[i][2] )
{
return possible_winner == 'X' ? GAMESTATE_WINNER_PLAYER1 : GAMESTATE_WINNER_PLAYER2;
}
}
}
//check for vertical wins
for ( int i = 0; i < 3; i++ )
{
char possible_winner = board[0][i];
if ( possible_winner != 'E' )
{
if ( possible_winner == board[1][i] && possible_winner == board[2][i] )
{
return possible_winner == 'X' ? GAMESTATE_WINNER_PLAYER1 : GAMESTATE_WINNER_PLAYER2;
}
}
}
//check for diagonal-down win
{
char possible_winner = board[0][0];
if ( possible_winner != 'E' )
{
if ( possible_winner == board[1][1] && possible_winner == board[2][2] )
{
return possible_winner == 'X' ? GAMESTATE_WINNER_PLAYER1 : GAMESTATE_WINNER_PLAYER2;
}
}
}
//check for diagonal-up win
{
char possible_winner = board[2][0];
if ( possible_winner != 'E' )
{
if ( possible_winner == board[1][1] && possible_winner == board[0][2] )
{
return possible_winner == 'X' ? GAMESTATE_WINNER_PLAYER1 : GAMESTATE_WINNER_PLAYER2;
}
}
}
//check if board is full
for ( int i = 0; i < 3; i++ )
for ( int j = 0; j < 3; j++ )
if ( board[i][j] == 'E' )
return GAMESTATE_UNDECIDED;
return GAMESTATE_DRAW;
}
int get_int_from_user( const char *prompt, ... )
{
for (;;) //loop forever until user enters a valid number
{
va_list args;
char buffer[1024], *p;
long l;
//prompt user for input
va_start( args, prompt );
vprintf( prompt, args );
va_end( args );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
l = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "error converting string to number\n" );
continue;
}
//make sure that number is representable as an "int"
if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
{
printf( "number out of range error\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfh4q" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return l;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
1 2 3
4 5 6
7 8 9
It is player 1's turn.
Please select a move (1-9): 5
1 2 3
4 X 6
7 8 9
It is player 2's turn.
Please select a move (1-9): 4
1 2 3
O X 6
7 8 9
It is player 1's turn.
Please select a move (1-9): 1
X 2 3
O X 6
7 8 9
It is player 2's turn.
Please select a move (1-9): 6
X 2 3
O X O
7 8 9
It is player 1's turn.
Please select a move (1-9): 9
X 2 3
O X O
7 8 X
Player 1 wins!
If you want to make a good computer opponent, then I suggest that you take a look at the Wikipedia article on Minimax.
So, I've been trying to validate CNIC because Pakistan requires male CNIC's to end in odd number and female CNIC's to end in even number.
CNIC is stored as a string in a structure containing information about a bank user.
The problem is when i apply the logic, it doesn't seem to work as intended and always prints the invalid CNIC prompt even when it is correctly input.
Here is the relevant code:
struct account//The structure used to store the records
{
int mm,dd,yyyy,Deposit;
long long int accountnum;
char name[50];
char address[50];
char Account[50];
char CNIC[50];
char Num[50];
char gender;
} s[100];
void ValidCNIC(int j) {
int i = 0, check = 0;
char ch;
printf("\n \tCNIC: ");
fgets(s[j].CNIC,sizeof(s[j].CNIC),stdin);
fflush(stdin);
while(i < strlen(s[j].CNIC)-1) {
ch = s[j].CNIC[i];
if(ch >= '0' && ch <= '9') {
i++;
}
else{
printf(" \tThe CNIC can contain numbers only!\n");
fordelay(1000000000);
ValidCNIC(j);
}
}
if (strnlen(s[j].CNIC,sizeof(s[j].CNIC)) < 14)
{
printf(" \tThe CNIC is too short\n \tPlease reenter\n");
fordelay(1000000000);
ValidCNIC(j);
}
else if (strnlen(s[j].CNIC,sizeof(s[j].CNIC)) > 14) {
printf(" \tThe CNIC is too long\n \tPlease reenter\n");
fordelay(1000000000);
ValidCNIC(j);
}
int len = strnlen(s[j].CNIC,sizeof(s[j].CNIC));
if((s[j].gender == 'm') && ((s[j].CNIC[len] !='1')||(s[j].CNIC[len] !='3')||(s[j].CNIC[len] !='5')||(s[j].CNIC[len] !='7')||(s[j].CNIC[len] !='9')))
{
printf("invalid CNIC, male CNIC must always end in an odd number");
ValidCNIC(j);
}
else if((s[j].gender == 'w') && ((s[j].CNIC[len] !='0')||(s[j].CNIC[len] !='2')||(s[j].CNIC[len] !='4')||(s[j].CNIC[len] !='6')||(s[j].CNIC[len] !='8')))
{
printf("Invalid CNIC, female CNIC must end in an even number");
ValidCNIC(j);
}
You ought not take input in your validation function; just validate. Something like:
#include <stdio.h>
#include <ctype.h>
int
isValidCNIC(const char *cnic, char gender)
{
size_t len = 0;
const char *s = cnic;
char c;
if( gender != 'm' && gender != 'f' ){
fprintf(stderr, "invalid gender: %c\n", gender);
return 0;
}
while( *cnic ){
len += 1;
if( ! isdigit(c = *cnic++) ){
fprintf(stderr, "%s: invalid character %c\n", s, c);
return 0;
}
}
if( len != 14 ){
fprintf(stderr, "%s: too %s\n", s, len < 14 ? "short" : "long");
return 0;
}
if( ((c - '0') % 2) != ( gender == 'm' ) ){
fprintf(stderr, "%s: invalid parity\n", s);
return 0;
}
return 1;
}
int
main(void)
{
struct test { char *cnic; int gender; } t[] = {
{ "34576271345678", 'f' },
{ "34576271345677", 'm' },
{ "34576271345678", 'm' },
{ "3457627134678", 'm' },
{ "345762713456788", 'm' },
{ "3457a271345788", 'k' },
{ NULL, 0 }
};
for( struct test *p = t; p->cnic; p++ ){
if( isValidCNIC( p->cnic, p->gender) ){
printf("valid: %s\n", p->cnic);
}
}
}
But note that strspn does most of the work that you are trying to do, and you could refactor to:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int
isValidCNIC(const char *cnic, char gender)
{
char err[256] = "";
size_t len = strspn(cnic, "0123456789");
const char *s = cnic;
if( gender != 'm' && gender != 'f' ){
strcat(err, "invalid gender, ");
}
if( cnic[len] ){
strcat(err, "invalid character, ");
}
if( len != 14 ){
strcat(err, len < 14 ? "too short, " : " too long, ");
}
if( ((cnic[len - 1] - '0') % 2) != ( gender == 'm' ) ){
strcat(err, "invalid parity, ");
}
if( *err ){
err[strlen(err) - 2] = '\0';
fprintf(stderr, "%s, %c: %s\n", s, gender, err);
}
return !*err;
}
int
main(void)
{
struct test { char *cnic; int gender; } t[] = {
{ "34576271345678", 'f' },
{ "34576271345677", 'm' },
{ "34576271345678", 'm' },
{ "3457627134678", 'm' },
{ "345762713456788", 'm' },
{ "3457a271345788", 'k' },
{ NULL, 0 }
};
for( struct test *p = t; p->cnic; p++ ){
if( isValidCNIC( p->cnic, p->gender) ){
printf("valid: %s\n", p->cnic);
}
}
}
Recursion does not seem well suited to this task.
Consider a loop until the input is ok.
strspn can be used to test the input for digits. index will be the first character that is not a digit. Following fgets and all digits, that character should be a newline ( '\n').
Use modulus ( '% 2') to determine if the last digit is odd or even.
This is not exactly what is needed but should give ideas that can be adapted.
#include <stdio.h>
#include <string.h>
#define LENGTH 50
int main ( void) {
char CNIC[LENGTH] = "";
int ok = 0;
int gender = 'm';
while ( ! ok) {
printf ( "enter CNIC\n");
fgets ( CNIC, sizeof CNIC, stdin);
size_t index = strspn ( CNIC, "0123456789");
if ( 14 <= index && '\n' == CNIC[index]) {
int mod = CNIC[index - 1] % 2;
if ( 'm' == gender) {
if ( mod ) {//odd
ok = 1;
}
else {
printf ( "male CNIC must be odd\n");
}
}
if ( 'w' == gender) {
if ( ! mod ) {//even
ok = 1;
}
else {
printf ( "female CNIC must be odd\n");
}
}
}
else {
printf ( "enter digits only, at least 14. try again\n");
}
}
return 0;
}
Use '0' and '9' instead of 48 and 57.
Do not recursively call ValidCNIC from within itself. This can lead to infinite recursion
Add an (e.g.) outer that checks an error flag/value and loops if there is an error
Using s[j].CNIC[i] everywhere is cumbersome. Better to set (e.g.) char *cnic = s[j].CNIC; and use that.
No need to call strlen in the loop. Just call it once and save the value.
Your even/odd check can be simplified
Here's a refactored version. It is annotated. It compiles but I've not tested it:
#include <stdio.h>
#include <string.h>
//The structure used to store the records
struct account {
int mm, dd, yyyy, Deposit;
long long int accountnum;
char name[50];
char address[50];
char Account[50];
char CNIC[50];
char Num[50];
char gender;
} s[100];
#define ERRSET(_fmt) \
{ \
err = _fmt; \
break; \
}
void
ValidCNIC(int j)
{
int i;
char ch;
const char *err;
while (1) {
printf("\n \tCNIC: ");
struct account *acct = &s[j];
fgets(acct->CNIC, sizeof(acct->CNIC), stdin);
char *cnic = acct->CNIC;
// strip the newline
cnic[strcspn(cnic,"\n")] = 0;
size_t cnlen = strlen(cnic);
err = NULL;
do {
// ensure CNIC has only digits
for (i = 0; i < cnlen; ++i) {
ch = cnic[i];
if ((ch < '0') || (ch > '9'))
ERRSET(" \tThe CNIC can contain numbers only!\n");
}
if (err != NULL)
break;
// ensure CNIC length is correct
if (cnlen < 14)
ERRSET(" \tThe CNIC is too short\n \tPlease reenter\n");
if (cnlen > 14)
ERRSET(" \tThe CNIC is too long\n \tPlease reenter\n");
int isodd = cnic[cnlen - 1];
isodd -= '0';
isodd %= 2;
// ensure even/odd of CNIC matches gender
switch (acct->gender) {
case 'm':
if (! isodd)
ERRSET("invalid CNIC, male CNIC must always end in an odd number");
break;
case 'w':
if (isodd)
ERRSET("Invalid CNIC, female CNIC must end in an even number");
break;
}
} while (0);
// no errors
if (err == NULL)
break;
// show the error
printf("%s",err);
}
}
UPDATE:
It still doesn't seem to work either, keeps giving the same prompt of Invalid CNIC. – Bas_Anar
Oops, my bad ... I forgot to remove the newline after the fgets. I've edited the example code above.
Btw what does that preprocessor directive do? – Bas_Anar
The macro arg is _fmt. The macro just does:
err = _fmt;
break;
where it is used.
So, it sets an error string and breaks out of the containing loop.
At the bottom, if err is NULL, there is no error and we're done.
Otherwise, it prints the error string and the outer loop reprompts the user.
Here's an example of the expanded macro text:
// ensure CNIC length is correct
if (cnlen < 14) {
err = " \tThe CNIC is too short\n \tPlease reenter\n";
break;
}
I've been trying to make this simple program that basically a little conversation. The biggest problem I've run into is that whenever I wanted to ask for the age and if someone wrongly answered with something that it's not a number, but a phrase or a word, instead of it beeing impossible it just assume a value. What can I write so that if someone rights something that is not a number it just repeats the loop?
main (){
printf("Can you tell me your age\n");
scanf("%d",&age );
do{
if ( age < 16) {
printf("You're a child!\n");
}
else if ( age == 17){
printf("Me too, cool! Let's meet.\n");
}
else {
printf("Pretty old! You are dying.\n");
}
} while ((age<=0) && (age>130));
}
To check if a character represents a digit or not, you can use the standard function isdigit().
But in your case with scanf() you can just check for its return value.
You might want to "clean stdin" if you don't know what the user will type.
void clean_stdin(void)
{
int c = 0;
while (c != '\n' && c != EOF)
c = getchar();
}
int main(void)
{
int age;
int scanf_ret;
do
{
printf("Can you tell me your age\n");
scanf_ret = scanf("%d", &age);
clean_stdin();
} while (scanf_ret != 1);
/*
Now we know that age contains a valid number
*/
return (0);
}
On success, scanf() returns the number of items of the argument list successfully filled. We've got only one argument, so we can use this return value in the while loop to continually check it against 1 (a valid input):
#include <stdio.h>
int main() {
int age, temp, status;
printf("Can you tell me your age\n");
status = scanf("%d", &age);
while(status!=1) {
while( (temp=getchar()) != EOF && temp != '\n' ) {};
printf("Invalid input... please enter a number: ");
status = scanf("%d", &age);
}
if ( age < 16) {
printf("You're a child!\n");
}
else if ( age == 17) {
printf("Me too, cool! Let's meet.\n");
}
else {
printf("Pretty old! You are dying.\n");
}
}
Hope this helps.
You need to check what scanf is returning in the if statement,you can modify you code like this:
int main()
{
int age;
printf("Can you tell me your age\n");
scan:
if((scanf("%d",&age ))==1)
{
do{
if ( age < 16) {
printf("You're a child!\n");
}
else if ( age == 17){
printf("Me too, cool! Let's meet.\n");
}
else {
printf("Pretty old! You are dying.\n");
}
} while ((age<=0) && (age>130));
}
else
{
printf("Please enter a number\n");
fflush(stdin);
goto scan;
}
return 0;
}
I have written the below code and need help understanding why it's not working the way it should. It compiles, however, it isn't running the if-else in my loops. For example, if I were to take out the while loop in my code everything would work fine, however, I want to know how many tries it takes for someone to guess the "magic number" or random number in this case.
#include <stdio.h>
int main()
{
int magicnum = 1234;
int userguess;
int totalguess = 0;
printf("Try to guess a number between 1 and 10000!: ");
scanf("%d", &userguess);
while(totalguess <= 7 && magicnum != userguess);{
if(magicnum == userguess){
printf("Congratulations, You Win!!\n");
if(totalguess = 1){
printf("Wow you did it on your first try!!\n");
}
else(totalguess >= 2); {
printf("Nice one!! It only took you %d tries!\n", totalguess);
}
}
else if(magicnum > userguess){
printf("Too Low try again!!\n");
}
else{
printf("Too High try again!!\n");
}
totalguess++;
}
return 0;
}
I am looking for an output of either someone answering the correct number which is "1234" if they score too high they should see the response of "Too High try again!!", and if they score too low they should see the response of "Too low try again!!. Also, it is supposed to show how many attempts it took them, and if they got it on the first try or not. The max number of attempts a person should be able to do this should be 7.
Problem #1 problem lies in the line
while(totalguess <= 7 && magicnum != userguess);{
Specifically at the semicolon. The above evaluates to the following
// Sit on this line until a condition is met
while(totalguess <= 7 && magicnum != userguess);
// Some block of code which is unrelated to the while loop
{
...
}
The answer is to remove the extraneous semicolon at the end of the while loop:
while(totalguess <= 7 && magicnum != userguess) {
// No semicolon ^
Problem #2 is in the line
if (totalguess = 1){
Where you are actually assigning totalguess to 1. Fix this by changing = (assignment) to == (comparison).
Problem #3 and #4 are in the line
else(totalguess >= 2); {
Not sure how this is even compiling, but you should have an else if rather than an else. And as with the while loop, you have another extraneous semicolon. Remove it.
Lastly, you are only asking for user input once, so the program will loop 7 times without asking for input. Put your scanf inside the main while loop
According to Levi's findings, a solution:
const int magic_num = 1234;
const uint max_num_guess = 7;
uint num_guess = 1 + max_num_guess;
int user_guess;
printf( "Try to guess a number between 1 and 10000!\n" );
for( uint idx = 0; idx < max_num_guess; ++idx )
{
scanf( "%d", &user_guess );
if( magic_num == user_guess ) { num_guess = 1 + idx; idx = max_num_guess; }
else
{
if( magic_num < user_guess ) { printf( "Too High try again!!\n" ); }
else { printf( "Too Low try again!!\n" ); }
}
}
if( num_guess <= max_num_guess )
{
printf( "Congratulations, You Win!!\n" );
if( 1 == num_guess ) { printf( "Wow did it on your first try!!\n" ); }
else { printf( "Nice one!! %d tries!\n", num_guess ); }
}
To #3 it is valid. Consider:
if(false){}
else(printf("Branch!\n"));
{ printf("Done.\n"); }