I am very new to C programming. I was trying to use the scanf function to ask the user to enter a date and display it in the console. So wrote the following codes:
#include <stdio.h>
#include <stdlib.h>
int main() {
int date, month, year;
printf("Please enter the date in the form of dd/mm/yyyy: ");
scanf("%d/%d/%d", &date, &month, &year);
printf("the date you entered was: %d-%d-%d\n", date, month, year);
return 0;
}
But the output am getting is not in a proper format, for example, I type in "10-12-2016", but the result I get was "10-554502544-32766". Any idea guys? Thanks in advance.
In your scanf(), you have this format - %d/%d/%d but you are giving the input as 10-12-2016, so you are doing wrong!
Instead, you should give input as - 10/12/2016 and the %d/%d/%d part in scanf() will ignore the / part from the input.
I type in 10-12-2016, but the result I get was 10-554502544-32766. Any idea guys?
Yes, when you are giving 10-12-2016 as input, scanf() assigning only 10 to date variable but no value to the other variables. Since the other two variables month and year is uninitialized, you are getting garbage value (554502544 and 32766) when you print the value of variable month and year.
One way to check this: Just initialize the variable and then take input.
int date = 0, month = 0, year = 0;
scanf("%d/%d/%d", &date, &month, &year);
Now, if you give 10-12-2016 as input, you will get 10-0-0 as output. Hopefully you can understand what is actually happening!
scanf() is a fairly kludgy tool. It expects the format to be exactly as you specified and if it isn't you get weird behaviour.
You either need to enter the text exactly as specified (dd/mm/yy, not dd-mm-yy) or change how you go about things.
Consider having scanf() scan in a string that you then lex yourself to get the values you want - you can be much more tolerant of variances in the input that way, as well as be more proof against someone trying to break your program by deliberately giving it invalid input.
You need to check the return value from scanf - See the manual page
#include <stdio.h>
#include <stdlib.h>
int main() {
int date, month, year;
printf("Please enter the date in the form of dd/mm/yyyy: ");
if (scanf("%d/%d/%d", &date, &month, &year) == 3) {
printf("the date you entered was: %d-%d-%d\n", date, month, year);
} else {
printf("You have made an error\n");
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main() {
int date, month, year;
printf("Please enter the date in the form of dd press enter then enter mm then press enter then enter year then press enter.. ");
scanf("%d", &date);
scanf("%d", &month);
scanf("%d", &year);
printf("the date you entered was: %d/%d/%d\n", date, month, year);
return 0;
}
Related
I have this piece of code to check whether second date is earlier than the first date the program works normally when I input these with this order without commas 9,9,2021 but when I do input 09 for the first input It skips the second input and directly jumps into the third input I can't figure out why this is the case since I am fairly new to C
#include <stdio.h>
// Array format [DD,MM,YYYY]
int date[3];
int secondDate[3];
// ANSI color codes
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
int main()
{
printf("Enter the day of first date: ");
scanf("%i", &date[0]);
printf("Enter the month of first date: ");
scanf("%i", &date[1]);
printf("Enter the year of first date: ");
scanf("%i", &date[2]);
printf("Enter the day of the second date: ");
scanf("%i", &secondDate[0]);
printf("Enter the month of the second date: ");
scanf("%i", &secondDate[1]);
printf("Enter the year of the second date: ");
scanf("%i", &secondDate[2]);
return 0;
}
The %i formar specifier is recognizing the number base prefixes (that is "0x" for hexadecimal, and '0' for octal). The '0' prefix is for octal. And 09 is an invalid octal, as octal numbers contain digits 0-7.
You can use the %d specifier instead of %i, which is only interpreting decimal numbers.
Was working on a program that prompts a user to enter a phone number and than prints it out using . instead of - so and when I run it it doesn't even let me input anything it just runs and gives me random values. So here's a look at the full program.
int item_number, year, month, day, first, middle, last;
//float unit_price;
printf("Enter item number: ");
scanf("%d", &item_number);
printf("Enter unit price: ");
scanf("%f", &unit_price);
printf("Enter purchase date (mm/dd/yyyy): ");
scanf("%d /%d /%d", &month, &day, &year);
printf("Item\t\tUnit\t\tPurchase\n\t\tPrice\t\tDate");
printf("\n%d\t\t$%6.2f\t\t%.2d/%.2d/%.2d\n", item_number, unit_price, month, day, year);
//here is the code that gives me the problem explained above.
//also if i comment the code above it works.
printf("Enter phone number [(xxx) xxx-xxxx] : ");
scanf("(%d) %d - %d", &first, &middle, &last);
printf("You entered %d.%d.%d", first, middle, last);
The problem you have encountered, is probably one of the most common problems encountered by new C programmers -- the improper use of scanf. Specifically, when you attempt to read the telephone number, stdin contains, e.g.:
"\n(888) 555-1212"
(the '\n' the result of pressing Enter after (mm/dd/yyyy) is entered)
As a result, the input waiting in stdin does not match "(%d...", and a matching failure results. Why? There is a newline at the beginning of the characters in stdin. The "%d" format specifier (all numeric conversion specifiers) will skip leading whitespace.
However, the leading whitespace does not precede the integer, it precedes the "(" which is not skipped by your format string. With scanf, a " " (space) in the format string, will cause any number of whitespace characters to be skipped/discarded. So as BLUEPIXY correctly notes, you need to add the space before the "(" in the format string to have scanf ignore the '\n' waiting in stdin.
Beyond that, you make the same mistake and misuse of scanf that nearly all new C-programmers do -- failing to check the return. scanf returns the number of successful conversions that take place based on the conversion specifiers in the format string.
At minimum, you must check the return of scanf (and in fact on ALL USER INPUT functions) to provide minimal validation that you do in fact have valid input stored in your variables to proceed forward with in your code. If you fail to check the return, you can have no confidence that undefined behavior isn't being invoked from that point forward. So validate all user input.
A minimal rewrite of your code that puts those pieces together would be:
#include "stdio.h"
int main (void) {
int item_number, year, month, day, first, middle, last;
float unit_price;
printf("Enter item number: ");
if (scanf ("%d", &item_number) != 1) { /* validate item */
fprintf (stderr, "error: invalid input (item_number)\n");
return 1;
}
printf("Enter unit price: ");
if (scanf ("%f", &unit_price) != 1) { /* validate unit */
fprintf (stderr, "error: invalid input (unit_price)\n");
return 1;
}
printf("Enter purchase date (mm/dd/yyyy): ");
/* validate date */
if (scanf ("%d /%d /%d", &month, &day, &year) != 3) {
fprintf (stderr, "error: invalid input (mm/dd/yyyy)\n");
return 1;
}
printf ("\t\tUnit\t\tPurchase\nItem\t\tPrice\t\tDate");
printf ("\n%d\t\t$%6.2f\t\t%.2d/%.2d/%.2d\n",
item_number, unit_price, month, day, year);
printf ("Enter phone number [(xxx) xxx-xxxx] : ");
/* validate phone */
if (scanf (" (%d) %d - %d", &first, &middle, &last) != 3) {
fprintf (stderr, "error: invalid input [(xxx) xxx-xxxx]\n");
return 1;
}
printf ("You entered %d.%d.%d\n", first, middle, last);
return 0;
}
Example Use/Output
$ ./bin/scanf_phone
Enter item number: 3
Enter unit price: 19.95
Enter purchase date (mm/dd/yyyy): 03/01/2017
Unit Purchase
Item Price Date
3 $ 19.95 03/01/2017
Enter phone number [(xxx) xxx-xxxx] : (800) 555-1212
You entered 800.555.1212
(note I tweaked the format to put Item on the 2nd line...)
Look things over, and spend the time it takes to understand man 3 scanf. It is time well spent.
If you are using Xcode, then write your printf statements like so:
printf("Enter item number:\n");
Put a newline(\n) at the end.
I am doing this C program where I need to input a date and see whether it is a valid date. However, I do not know how to scan a "0" in front of the days and months that have one digits. Also, the program requires to scan "/" as well. If the user inputs "07-14-1999" it has to be invalid because the user did not input "/". What should I do with these two problems? The following is the code I have so far. Thank you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int day, month, year;
printf("Please enter a date to check validity (in the form of MM/DD/YYYY): ");
scanf("%i%i/%i%i/%i%i",&month, & month, &day, &day, &year, &year, &year &year);
printf("%i%i/%i%i/%i%i",month, month, day, day, year, year, year, year);
}
You want to scan three integer numbers, so you should use %d once for each number in scanf:
scanf("%d/%d/%d", &month, &day, &year);
To validate input it makes sense to check number of successfully scanned integers:
int res = scanf("%2d/%2d/%4d", &month, &day, &year);
if (res != 3) {
/* error */
}
Here %2d means that the max length of that input integer is 2 digits.
If everything is scanned correctly you can validate ranges for month, day and year.
To print leading zero:
printf("%02d/%02d/%04d", month, day, year);
Here %02d means that the integer is printed by minimum two symbols and zero is prepended if there is only one symbol.
It is trickier to make sure that the number of input symbols is correct. The above scan pattern also accepts date "1/1/1999". To simplify and to avoid scanning each symbol separately it is possible to read input as a string:
int day, month, year;
/* buffer length is enough for 10 date symbols + 1 null terminating
* character + 1 for too long input */
char buf[12];
char dummy_end_test;
printf("Please enter a date to check validity (in the form of MM/DD/YYYY): ");
/* scan as a string with maximum field width 11, check that the number
* of input characters is exactly 10 */
if (scanf("%11s", buf) != 1 || strlen(buf) != 10) {
printf("incorrect input length\n");
return 1;
}
/* parse integer numbers from string
* try to read symbol dummy_end_test to filter input as 11/1/19999 or 11/11/199x
* if it is possible to read one more character after four digits of year
* the number of scanned entries is 4 that is invalid input */
int ret = sscanf(buf, "%2d/%2d/%4d%c", &month, &day, &year, &dummy_end_test);
if (ret != 3) {
printf("error\n");
return 1;
}
Here I used sscanf that scans formatted input from string.
Anyway it is needed to validate ranges for day, month and year. All those numbers must be greater than 0. Maximum day depends on month and/or on leap year.
I am trying to figure out why I can't get this to run properly. I just want four inputs from the user, and run the calculation at the end.
#include <stdio.h>
#include <math.h>
int main(){
double amount; /* amount on deposit */
double principal; /* what's the principal */
double rate; /* annual interest rate */
int year; /* year placeholder and no. of total years */
int yearNo;
printf("What is the principal? ");
scanf("%d", &principal);
printf("What is the rate (in decimal)? ");
scanf(" .2%d", &rate);
printf("What is the principal? ");
scanf(" %d", &principal);
printf("How many years? ");
scanf(" %d\n", yearNo);
printf("%4s%21s\n", "Year", "Amount on deposit");
/* calculate the amount on deposit for each of ten years */
for (year = 1; year <= yearNo; year++){
amount = principal * pow(1.0 + rate, year);
printf("%4d%21.2f\n", year, amount);
}
return 0;
}
It properly asks for the principal and rate, but then skips over the question about Principal and asks for years. Then it just sits there waiting for a "ghost" entry?
I've been reading that the scanf() adds some whitespace when hitting enter but thought the space before the %d would fix that?
I also saw you could add do { c=getchar(); } while ( c != '\n'); after each scanf but that seems to crash the program (I added int c = 0; to the beginning too).
Thanks for any help or ideas!
EDIT:
When I change the erroneous format specifier from:
scanf(" .2%d", &rate);
to:
scanf(" %d", &rate);
I then get a crash after entering my values.
.2%d is not a valid format string.
For a start, the % has to come first. In addition, if you're after a floating point value, d is not the right character - it's for integral values.
You should be using something like %f (you don't need width or precision modifiers).
On top of that, you've made a minor mistake of not using a pointer for one of your scanf calls:
scanf(" %d\n", yearNo);
That's probably going to cause a crash, and should be changed to:
scanf(" %d\n", &yearNo);
And, as a final suggestion, it's totally unnecessary to use whitespace before (or a newline after) %d or %f family of format specifiers. The scanner automatically skips whitespace before both of those.
So, the only two scanf format strings you need in this program are "%d" and "%lf" (f is for floats, lf is for doubles).
I've got to read a date format (dd-mm-yyyy;) from a char* string using sscanf with this line of code:
sscanf(string, "%[^-]-%[^-]-%[^;];", day, month, year)
where day/month/year are char* string of 3/3/5 elemets each.
In this way it works but when i try to use day/moth/year as integer variables (with same sscanf), I got a 0 0 0 value when i use printf on them. If i change sscanf to
sscanf(string, "%d-%d-%d;", day, month, year)
I got segmentation fault.
Anyone can help me? Using K&R book, I didn't find a solution.
You need to pass the address of the int variables:
int day, month, year;
sscanf(string, "%d-%d-%d;", &day, &month, &year);
sscanf() returns the number of assignments made, recommend checking the return value before using day, month and year:
if (3 == sscanf(string, "%d-%d-%d;", &day, &month, &year))
{
}