2017-08-08 97 views
2
#!/usr/bin/perl 

@month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); 
@week = ("Sunday", "Monday","Tuesday", "Wednesday","Thursday", "Friday", 
    "Saturday"); 

print "date:\n"; 
$date=<STDIN>; 
print "mon:\n"; 
$mon=<STDIN>; 
print "year:\n"; 
$year=<STDIN>; 

if (($year % 400 == 0) || ($year % 4 == 0) && ($year % 100 != 0)) 
{ 
    $month[1] = 29 ; 
    for($i = 0 ; $i < $mon - 1 ; $i++) 
    {  
     $s = $s + $month[$i] ; 
     $s = $s + ($date + $year + ($year/4) - 2) ; 
     $s = $s % 7 ; 
    } 
} 
print $week[$s+1] ; 

我一直在試圖學習perl幾天,我寫了代碼來查找給定日期的一天。實際上我從C代碼轉換了它。但它並不正確。輸出總是星期一。我在哪裏犯錯?從給定的日期找到一天

+2

你應該縮進代碼COS這是非常難讀,但我看不到如果'$ year'不是閏年,它會在哪裏更新'$ s'? –

回答

2

不要自己動手。使用一個模塊。近十年來,它一直是Perl發行版的標準組成部分。

#!/usr/bin/perl 

use strict; 
use warnings; 
use feature 'say'; 

use Time::Piece; 

print "date:\n"; 
chomp(my $date = <STDIN>); 
print "mon:\n"; 
chomp(my $mon = <STDIN>); 
print "year:\n"; 
chomp(my $year = <STDIN>); 

my $tp = Time::Piece->strptime("$year-$mon-$date", '%Y-%m-%d'); 

say $tp->fullday; 

我做了一些其他的調整:

  • 始終use strictuse warnings
  • 聲明變量與my
  • 使用chomp()從輸入

更新刪除換行符:我現在已經更詳細地查看了你的代碼。那裏只有一個錯誤。

你的邏輯是這樣的:

if (we're in a leap year) { 
    Change the @months array to deal with leap years 
    Do the maths to calculate the day 
} 

當它應該是這個樣子的:

if (we're in a leap year) { 
    Change the @months array to deal with leap years 
} 
Do the maths to calculate the day 

所以,除非你的輸入年份是閏年,你跳過所有的計算。這意味着$ s永遠不會被賦予價值。 Perl將未定義的值視爲0,因此您的最終聲明總是在打印$week[0 + 1],即星期一。

如果像時間::件模塊是不可用的,一個Perl程序員會寫你這樣的代碼:

#!/usr/bin/perl 

# Force us to declare variables. 
use strict; 
# Get Perl to tell us when we're doing something stupid 
use warnings; 
# Allow the use of say() 
use feature 'say'; 

# Declare variables with my() 
my @month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); 
# qw(...) defines a list without all that tedious punctuation 
my @week = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday); 

print "date:\n"; 
# Use chomp() to remove newlines from input 
chomp(my $date = <STDIN>); 
print "mon:\n"; 
chomp(my $mon = <STDIN>); 
print "year:\n"; 
chomp(my $year = <STDIN>); 

# This logic can be cleaned up a lot. 
if (($year % 400 == 0) || ($year % 4 == 0) && ($year % 100 != 0)) { 
    $month[1] = 29 ; 
} 

# Initialise $s to avoid warnings later 
my $s = 0; 
# A foreach look is almost always cleaner than for (;;) 
foreach my $i (0 .. $mon - 2) { 
    # Haven't checked your calculations (but they seem to work 
    # += is useful shortcut 
    $s += $month[$i]; 
    $s += ($date + $year + ($year/4) - 2); 
    $s %= 7; 
} 

# say() is like print() but with an extra newline 
say $week[$s+1]; 
+2

這是一個很好的和可理解的解釋。順便說一下,我認爲OP的重新發明之後,爲了學習輪子如何工作而不是用於計算日期值的庫存模塊。我喜歡。 – PerlDuck

1
use Time::Local qw(timegm); 

my @dow_names = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday); 

my $Y = ...; 
my $m = ...; 
my $d = ...; 

my $epoch = timegm(0, 0, 0, $d, $m-1, $Y-1900); 
my $dow = (gmtime($epoch))[6]; 
my $dow_name = $dow_names[$dow]; 

更重要的是,

use POSIX  qw(strftime); 
use Time::Local qw(timegm); 

my $Y = ...; 
my $m = ...; 
my $d = ...; 

my $epoch = timegm(0, 0, 0, $d, $m-1, $Y-1900); 
my $dow_name = strftime("%A", gmtime($epoch)); 

您也可以使用DateTime;使用起來更簡單,但它不像上面所用的模塊那麼輕。

+0

我不能使用當地時間,我必須計算日期。但是謝謝 –

+3

這不是很合理。正如你已經注意到的那樣,它的工作量更大,而且更容易出錯。 – ikegami

5

正如@Chris Turner指出的那樣,代碼中沒有路徑來處理不是閏年的情況。爲了解決這個問題,並完成您的既定目標,只需對您的代碼進行一些小改動。

if(($year % 400 == 0) || ($year % 4 == 0) && ($year % 100 != 0)) { 
    $month[1] = 29 ; 
    for($i = 0 ; $i < $mon - 1 ; $i++) { 
     ... 
    } 
} 
print $week[$s+1] ; 

應重新編寫和重新縮進作爲

if(($year % 400 == 0) || ($year % 4 == 0) && ($year % 100 != 0)) { 
    $month[1] = 29 ; 
} 
for($i = 0 ; $i < $mon - 1 ; $i++) { 
    ... 
} 
print $week[$s+1] ; 

使$month[1]只更新閏年,但在你的for循環的代碼始終運行。


有經驗的Perl程序員也總是會提醒你開始每個腳本與

use strict; 
use warnings; 

,因爲這些編譯早期發展促進良好的編程習慣和幫助捕捉許多錯誤。他們不會幫助解決這個問題,但是如果你開始使用他們,他們會幫助下一個。

2

要還引進了最廣泛使用的模塊的日期和時間,在這裏它與DateTime

use warnings; 
use strict; 
use feature qw(say); 

use DateTime; 

# ... acquire input ($year, $mon, $date) 

my $dt = DateTime->new(year => $year, month => $mon, day => $date); 

say $dt->day_name; 

這是一個非常大和「沉重」的模塊,用了很多的功能。還有其他人。

雖然我支持手工作爲學習的一部分,但一旦涉及到處理日期和時間,您將需要使用一個模塊。

相關問題