Reputation:
For example in input.txt file there is date 20210405
. Date is in rrrrmmdd
format without any '/'
or '.'
. How do you check if date is in correct format not in 20211405
?.
My code works only for numbers that dont have zero in day for example 05
,07
,08
, my code works only for 10
or 11
. How do I fix that?
int main() {
char load[50];
long year, day, month;
int lenght, lenght2, lenght3;
int i = 0;
FILE *file;
file = fopen("input.txt", "r");
while (fgets(load, sizeof load, file) != NULL) {
if (i == 0) {
if (strlen(load) == 8) {
year = strtol(load, NULL, 10);
month = year;
day = year;
year = year * 0.0001;
lenght = (log10(abs(year))) + 1;
if (lenght == 4) {
day = day % 100;
lenght2 = (log10(abs(day))) + 1;
if (lenght2 == 2 && day <=31) {
month = (month % 10000) - 30;
month = month / 100;
lenght3 = (log10(abs(day))) + 1;
if (month <= 12 && lenght2 == 2) {
printf("Datum: %s", load);
} else {
printf("Invalid input.");
}
} else {
printf("Invalid input.");
}
} else {
printf("Invalid input.");
}
} else {
printf("Invalid input.");
}
}
}
}
Upvotes: 1
Views: 201
Reputation: 144750
It is a bad idea to use floating point arithmetics to split the value into the year, month and day parts. The main reason for this is floating point numbers are represented internally in base 2 so 0.0001
is not represented exactly, so converting the multiplication result to long
may cause truncation of the value.
You should instead use integer arithmetics this way:
long value = strtol(load, NULL, 10);
year = value / 10000;
month = (value / 100) % 100;
day = value % 100;
You could also use sscanf()
to parse the line directly into 3 int
values:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main() {
char load[50];
int year, day, month;
int i = 0;
FILE *file = fopen("input.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open input.txt: %s\n", strerror(errno));
return 1;
}
while (fgets(load, sizeof load, file) != NULL) {
if (i++ == 0) {
static const int mlen[] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char c[2];
/* accept up to 4 bytes for year, 2 for month, 2 for day and check for a trailing newline */
if (sscanf(load, "%4d%2d%2d%1[\n]", &year, &month, &day, c) != 4) {
fprintf(stderr, "invalid date line: %s", load);
break;
}
if (year < 1901 || year > 2099
|| month < 1 || month > 12
|| day < 1 || day > mlen[month]
|| (day == 29 && month == 2 && year % 4 != 0)) {
fprintf(stderr, "invalid date: %d/%d/%d\n", day, month, year);
break;
}
printf("Datum: %s", load);
} else {
/* handle other lines */
...
}
}
fclose(file);
return 0;
}
Upvotes: 0
Reputation: 12404
You have a few flaws in your code:
fgets
includes a \n
at the end of your string if it is found in the file. Unless you read the last line where no more \n
is present, you will get 9 characters in your buffer.
Your condition if (strlen(load) == 8)
will fail in the other cases.
You should not use floating point operations on integers.
year = year * 0.0001;
In best case it is identical to year = year / 10000;
, in worst case you get some rounding errors.
You check the "length" of the value for day
and month
by taking log10
. That means that the numerical value must be >10 to get a length of 2. That is exactly what you are complaining about.
A proper check for valid valued would be to check whether the numerical value is in proper range.
For some reason to reduce month
by 30. That doesn't really make much sense.
You don't use variable i
at all. The corresponding if (i==0)
is rather useless.
A fixed version could look like this:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main(void) {
char load[50];
long year, day, month;
bool valid = false;
FILE* file = fopen("input.txt", "r");
// TODO: Check for NULL
while (fgets(load, sizeof load, file) != NULL) {
// Remove trailing '\n'
int len = strlen(load);
if (load[len-1] == '\n') {
load[len-1] = 0;
}
// Do we have exactly 8 digits?
if (strlen(load) == 8) {
long value = strtol(load, NULL, 10);
year = value / 10000;
month = (value / 100) % 100;
day = value % 100;
if (year >= 1000) {
if (day > 0 && day <= 31) {
if (month > 0 && month <= 12) {
valid = true;
}
}
}
}
if (valid) {
printf("Datum: %s", load);
}
else {
printf("Invalid input.");
}
}
}
}
Upvotes: 1