Accepting an input of multiple formats - c

I'm trying to create a code that accepts a date, however I want to give the user the ability to enter the date as dd/mm/yyyy or dd-mm-yyyy. My code is below, I tried to use OR but it does not work
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main ()
{
int dayA, monthA, yearA,
printf("First date in format DD/MM/YYYY or DD-MM-YYYY: ");
scanf("%d/%d/%d" || "%d-%d-%d", &dayA, monthA, yearA);

Here is a simple way to do it. It inputs into a string, and then checks if one of the format methods works. It's always essential to check the return value from the scanf function family, to know if the conversion succeeded.
#include<stdio.h>
int main(void)
{
int dayA, monthA, yearA;
puts("Enter a date dd/mm/yyyy or dd-mm-yyyy");
char datestr[32];
if(fgets(datestr, sizeof datestr, stdin) != NULL) {
if(sscanf(datestr, "%d/%d/%d", &dayA, &monthA, &yearA) == 3 || // added missing &
sscanf(datestr, "%d-%d-%d", &dayA, &monthA, &yearA) == 3) {
printf("Date is day %d, month %d, year %d\n", dayA, monthA, yearA);
}
}
}
Here are two runs of the program:
Enter a date dd/mm/yyyy or dd-mm-yyyy
23/4/2020
Date is day 23, month 4, year 2020
Enter a date dd/mm/yyyy or dd-mm-yyyy
23-4-2020
Date is day 23, month 4, year 2020

Related

Probelm in facing about Structure Types in c

i'm currently working on Structure Types in my examples i'm working on I've currently made
#include <stdio.h>
#include <string.h>
typedef struct {
int day, month, year;
} Date;
typedef struct {
char customer_name[1000]; //Name of the customer placing the order
int order_number; //The order number
Date order_date; //The date on which the order was placed
double total_price;
} Order;
/* print_order(the_order)
Given an Order object, print the order's details in the same format
described in the section above.
*/
void print_order(Order the_order){
printf("Order %d: Placed by %s on %d/%d/%d (price: $%f)\n",the_order.order_number,
the_order.customer_name, the_order.order_date.month, the_order.order_date.day,
the_order.order_date.year, the_order.total_price);
}
int main(){
//Create an order with order number 111, placed on November 25, 2021
Order orderA = {111, 11, 25, 2021, "Rebecca Raspberry"};
strcpy(orderA.customer_name, "Rebecca Raspberry");
orderA.order_number = 111;
orderA.order_date.year = 2021;
orderA.order_date.month = 11;
orderA.order_date.day = 25;
orderA.total_price = 6.10;
//Make a second order, this time with order number 116, placed on November 29, 2021
//This order is created using the { } initializer syntax. Notice the nested initializer
//for the date.
Order orderB = { "Fiona Framboise", 116, { 29, 11, 2021 }, 17.0 };
print_order(orderA);
print_order(orderB);
printf("Order %d: Placed by %s on %d/%d/%d (price: $%f)\n", orderA.order_number,
orderA.customer_name, orderA.order_date.month, orderA.order_date.day,
orderA.order_date.year, orderA.total_price);
return 0;
}
I've wanted to know what does print_order(the_order) mean is it asking for a typedef of days, month and year? And for OrderB do i formatt them in the same way as the orderA or is this wrong? The output that i need is:
Order 111: Placed by Rebecca Raspberry on 11/25/2021 (price: $6.10)
Order 116: Placed by Fiona Framboise on 11/29/2021 (price: $17.00)
Would appericate a reposnse/help :)
void print_order(Order the_order) means print_order expects copy (value) of the type Order which is struct with 4 members (pointer, int, struct with 3 ints, and a double). Usually, you pass structured by address to avoid copying large structs.
You both initialize and assign values to orderA which is confusing. The order of initialization (of orderA) must match the order of the struct:
Order orderA = { "Rebecca Raspberry", 111, { 11, 25, 2021 }};
or use a designator list in which case you can choose the order:
Order orderA = { .customer_name = "Rebecca Raspberry", .order_number = 111, .order_date = { 11, 25, 2021 }};
Note: total_price is not initialized, but do you do assign it the value 6.10. orderB is correct. #RetiredNinja already told you how to fix the format string:
void print_order(Order the_order){
printf("Order %d: Placed by %s on %d/%d/%d (price: $%.2f)\n",the_order.order_number,
the_order.customer_name, the_order.order_date.month, the_order.order_date.day,
the_order.order_date.year, the_order.total_price);
}
I don't know why you print orderA twice both using print_order() and printf statement in main().
Your code is formatted unconventionally (i.e. poorly) which makes it hard to reader:

When checking the validity of date of birth separated by dashes, an error rises when entering characters, and i can't solve that issue

from the requirements of my final project is to validate the scanned date of birth in the following format (DD-MM-YYYY).
the date of birth is a struct formed of 3 integers, day, month and year. So, I scan it from the user as follow:
scanf("%d-%d-%d",&dob.day,&dob.month,&dob.year);
However, when I enter a character, of course it enters an infinite loop.
I tried to use the flushinput concept (as I've used it with other scanned integers). It prevents the infinite loop. However, when re-scanning (through a certain loop), it keeps showing the "INVALID EMAIL" message, even though the entered email is correct! I guess this arises due to the presence of the dashes in the input.
So, can anybody tell me what to do?
Here's the part of the code where the issue arises (without the flushinput function):
void dobCheck(DATE dob) ///validates date of birth and rescans it if wrong
{
while(1)
{
if (dob.year<1806 || dob.year>2021 || dob.month<1 || dob.month>12 || dob.day<1 || dob.day >31)
{
dobCheckAct(dob); continue;
}
if ((dob.year%4)==0 && dob.month ==2 && dob.day >29)
{
dobCheckAct(dob); continue;
}
if (dob.year%4)!=0 && dob.month ==2 && dob.day >28)
{
dobCheckAct(dob); continue;
}
if (dob.month == 4 ||dob.month == 6 || dob.month == 9 || dob.month == 11) && dob.day> 30)
{
dobCheckAct(dob); continue;
}
break;
}
}
void dobCheckAct(DATE dob) ///action taken in case of invalid date of birth
{
printf("\a\n**INVALID DATE OF BIRTH!\n");
scanf("%d-%d-%d",&dob.day,dob.month,dob.year);
}
Thanks in advance!!

How to change a variable from a structure from integer to string?

The question assume
typedef struct {
int day;
int month;
int year;
} Date;
Date mfgDate = {17, 10, 2016}, expiryDate;
printf("%d-%d-%d", mfgDate.day, mfgDate.month, mfgDate.year);
By doing this i can display the date to the form of 17-10-2016, the question requires me to display the date in the form of DD-MMM-YYYY which is 17-OCT-2016, how can i do that? the question provides a tip which is to use switch statement but i can't seems to find out how, thanks a lot for help.
You could use strftime() for that:
char buffer[BUFFER_SIZE];
errno=0; //clear errno since we need it to detect errors in strftime()
//tm_year is years since 1900
//%d prints the day of the month, %B or %b the month name according to the locale
//and %Y prints the year, results in the format DD-MMMM-YYYY
int r = strftime
(buffer, sizeof buffer, "%d-%b-%Y", &(struct tm){.tm_year=2016-1900, .tm_mon=9, .tm_mday=17} );
if(!r && errno)
{
//do some error handling here
}
printf("%s\n",buffer);
If you are just starting with C and have not learned about arrays, a switch statement is a viable choice, just for the execise
const char* monthname(int month)
{
switch (month) {
case 1: return "JAN";
case 2: return "FEB";
// you can fill the remaining month yourself here
case 12: return "DEC";
// handle the error case
default: return "???";
}
}
to print your date then use:
printf("%d-%s-%d", mfgDate.day, monthname(mfgDate.month), mfgDate.year);
Simply have months names in the table.
char *months[] = {"JAN", "FEB","MAR", ......};
printf("%d-%s-%d", mfgDate.day, months[mfgDate.month - 1], mfgDate.year);

Why do I keep getting compiler errors with strtok in C?

My assignment is to create a progrma that asks the users for a date then prints if its valid or not. I am only allowed to use strings and no int %d.
Why does my program get so many compiler errors dealing with the strtok and calling the function?
Severity Code Description Project File Line Suppression State
Warning C4024 'getInput': different types for formal and actual parameter 1 dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 26
Warning C4047 'function': 'char *' differs in levels of indirection from 'char' dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 26
Warning C4024 'getInput': different types for formal and actual parameter 2 dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 26
Warning C4024 'getInput': different types for formal and actual parameter 3 dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 26
Warning C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 19
Warning C4996 'strtok': This function or variable may be unsafe. Consider using strtok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 21
Warning C4996 'strtok': This function or variable may be unsafe. Consider using strtok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 22
Warning C4996 'strtok': This function or variable may be unsafe. Consider using strtok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 24
Warning C4098 'getInput': 'void' function returning a value dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 90
Warning C4477 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'int' dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 47
Warning C4477 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 2 has type 'int' dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 47
Warning C4477 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 3 has type 'int' dating c:\users\chris\documents\visual studio 2015\projects\dating\dating.c 47
Error LNK2019 unresolved external symbol _WinMain#16 referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ) dating c:\Users\Chris\documents\visual studio 2015\Projects\dating\MSVCRTD.lib(exe_winmain.obj) 1
Error LNK1120 1 unresolved externals dating c:\users\chris\documents\visual
studio 2015\Projects\dating\Debug\dating.exe 1
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Declares function
void getInput(char *userInput1, char *userInput2, char *userInput3);
//Declares variables.
int main(void) {
char userInput[100];
printf("Enter a date in this format : MM/DD/YY:");
//Captures users input
scanf("%s", &userInput);
//Divides the 3 dates entered into 3 variables.
char *userInput1 = strtok(userInput, "/");
char *userInput2 = strtok(NULL, "/");
//Used X to capture the last end of integers entered.
char *userInput3 = strtok(NULL, "X");
//Called function.
getInput(*userInput1, *userInput2, *userInput3);
system("pause");
return 0;
}
void getInput(char *userInput1, char *userInput2, char *userInput3)
{
// If user inputs a valid date this will run.
if (0 > *userInput1<12, 0>*userInput2<31, 0>*userInput3 < 99) {
// If user month input is this...
switch (*userInput1) {
//if User month input is 02 this will run
case 02:
//If user year is a leap year this will run
if (*userInput3 % 4 == 0) {
//If user day is inbetween 0-29 it will say the date is valid.
if (0 > *userInput2 > 29) {
printf("You entered a valid date, %s/%s/%s", *userInput1, *userInput2, *userInput3);
}
// If the day of the February isn't 0-29 it will print it is invalid.
else
printf("Invalid date.");
}
case 04:
//Their are only 30 days in April, if user Inputs 31 it is invalid.
if (*userInput2 == 31) {
printf("Invalid date.");
}
//Every other date should be valid because the main if else statement filters it all out.
else {
("You entered a valid date, %s/%s/%s", *userInput1, *userInput2, *userInput3);
}
case 06:
if (*userInput2 == 31) {
printf("Invalid date.");
}
//Every other date should be valid because the main if else statement filters it all out.
else {
("You entered a valid date, %s/%s/%s", *userInput1, *userInput2, *userInput3);
}
case 11:
if (*userInput2 == 31) {
printf("Invalid date.");
}
//Every other date should be valid because the main if else statement filters it all out.
else {
("You entered a valid date, %s/%s/%s", *userInput1, *userInput2, *userInput3);
}
break;
}
}
//If the user enters a date that isn't valid , Invalid date prints.
else {
printf("Invalid date.");
}
return 0;
}
You pass characters instead of pointers to getinput():
getInput(*userInput1, *userInput2, *userInput3);
Try this instead:
getInput(userInput1, userInput2, userInput3);
The warning you get from the compiler regarding scanf() are indications of potential problems:
scanf is unsafe: indeed you do not limit the number of characters to store into the userInput array, and you should not pass the address of the array, but the address of its first entry, and you should check the return value:
if (scanf("%99s", userInput) != 1) {
/* handle input failure */
}
strtok is unsafe to use in nested contexts. You do not do this in the above code, but it is difficult for the compiler to verify and it would be safer to use strtok_s or strtok_r instead.
You have further problems in function getInput():
You should check if any of the arguments are NULL.
if (0 > *userInput1<12, 0>*userInput2<31, 0>*userInput3 < 99) { is a valid C expression, but not what you intend to test. Write this instead:
if (*userInput1 > 0 && *userInput1 < 12
&& *userInput2 > 0 && *userInput2 < 31
&& *userInput3 > 0 && *userInput3 < 99) {
...
}
But note however that you are testing characters, not the decimal value encoded into these characters. You should first convert these strings into numbers with atoi() or strtol(), or use a different scanf() conversion.
Note that leap years are not strictly multiples of 4, you might need to use the Gregorian rule if you want to handle years outside the 1901..2099 range. I assume YY implies 20YY, but this would be incorrect if you ask for birthdays.
You missed that September also has 30 days.
Here is a corrected and simplified version:
#include <stdio.h>
#include <string.h>
int check_date(int month, int day, int year);
int main(void) {
char userInput[100];
int day, month, year;
printf("Enter a date in this format : MM/DD/YY:");
//Captures users input
if (scanf("%d/%d/%d", &month, &day, &year) == 3) {
check_date(day, month, year);
} else {
printf("incorrect input\n");
}
system("pause");
return 0;
}
int check_date(int month, int day, int year) {
int valid = 1;
// If user inputs a valid date this will run.
if (month <= 0 || month > 12 || day <= 0 || day > 31 || year < 0 || year > 99) {
valid = 0;
} else {
switch (month) {
//if User month input is 02 this will run
case 02:
//If user year is a leap year this will run
if (year % 4 == 0) {
if (day > 29)
valid = 0;
} else {
if (day <= 28)
valid = 0;
}
break;
case 4:
case 6:
case 9:
case 11:
if (month > 30)
valid = 0;
break;
}
}
if (valid) {
printf("You entered a valid date, %d/%d/%d\n", month, day, year);
return 1;
} else {
printf("Invalid date\n");
return 0;
}
}

How to use integer 2D in C language?

I'm doing my college's task. I wrote like this
int debut[10][100];
char ngroup[10][100];
do
{
printf("1. Group name [1..25] : ");
gets (ngroup[0]);
}while (strlen(ngroup[0])< 1 || strlen(ngroup[0])>25);
do
{
printf("2. Year debute [1900-2011] : ");
scanf("%d",&debut[0]);
} while (debut[0] < 1900 || debut[0] > 2011);
I mean, I want to save a lot of group name which can be added by users, and also the year debut. But, when I made the validation of the year debut from 1900 until 2011 it's not work. Does anyone know the solution?
debut[0] is a pointer to array of 100 ints, and you try to compare it with an integer value.
You need something like this:
int debut[10];
...
scanf("%d",&debut[0]);
} while (debut[0] < 1900 || debut[0] > 2011);

Resources