วิธีโปรแกรมจำลองที่หยุดทำงานก่อนหรือเวลาจำลอง 24 ชั่วโมง

มีถังน้ำขนาด 500 แกลลอนที่ใช้จับปลาเพื่อทอดปลาใน 24 ชั่วโมง ถังเป็นถังรั่วซึ่งมีการสูญเสียน้ำในอัตรา 10% ของน้ำคงเหลือทุกชั่วโมง ฉันจะแก้ไขโค้ดของฉันเพื่อให้หยุดทำงานหลังจาก 24 ชั่วโมงหรือหลังจากปริมาตรถังถึง 100 แกลลอนได้อย่างไร ด้วยเหตุผลบางอย่าง ฉันไม่สามารถคาดศีรษะรอบ for loop ได้

int main()
{
    double add, gal = 500, vol, newVol, hour;

    printf("Please enter additional water added per hour: ");
    scanf("%f", &add);

    for (int hour = 0; hour <= 24; hour++)
    {
        vol = gal * 0.90 + add;
    }
    printf("The volume is %f gallons after %d hours. \n", &vol, &hour);

}

person intriguedandconfused    schedule 26.03.2019    source แหล่งที่มา
comment
แบบง่าย: จดบันทึกเวลาไว้ตั้งแต่ต้น และในช่วงเวลาหนึ่ง ให้ตรวจสอบการประทับเวลาต่อไป   -  person Sourav Ghosh    schedule 26.03.2019
comment
เพิ่มเงื่อนไขในลูปของคุณเพื่อตรวจสอบระดับเสียงด้วยหรือไม่   -  person Some programmer dude    schedule 26.03.2019
comment
เพิ่ม if (vol >= 100.0) break; ในลูปใช่ไหม ถึงจะไม่เข้าใจ 100 ถ้าถังมีความจุ 500 แกลลอน...   -  person Stefan Becker    schedule 26.03.2019
comment
หรือกำหนดค่าเริ่มต้น vol = 0.0 เมื่อประกาศ จากนั้น for (int hour = 0; hour <= 24 && vol >= 100; hour++) (สมมติว่าคุณต้องการทอดต่อไปจนกว่าปริมาณน้ำมันจะลดลงต่ำกว่า 100 แกลลอน - ปรับการทดสอบตามต้องการ) และ &vol, &hour); ควรเป็น vol, hour); (ไม่มีเครื่องหมาย '&' ให้พิมพ์)   -  person David C. Rankin    schedule 26.03.2019
comment
ซึ่งหมายความว่าคุณไม่ได้เปิดใช้งานคำเตือนคอมไพเลอร์อย่างเพียงพอ สำหรับ gcc/clang ให้เพิ่ม -Wall -Wextra -pedantic ลงในสตริงการคอมไพล์ของคุณ สำหรับ VS ให้เพิ่ม /W3 และอย่ายอมรับโค้ดจนกว่าจะคอมไพล์โดยไม่มีคำเตือน   -  person David C. Rankin    schedule 26.03.2019
comment
ฉันแก้ไขชื่อเรื่องเพื่อพูดถึงการจำลอง เนื่องจากโค้ดของคุณดูเหมือนจะไม่ได้ใช้แบบเรียลไทม์ และดูเหมือนเป็นการจำลอง หากควรใช้แบบเรียลไทม์ โปรดย้อนกลับ   -  person hyde    schedule 26.03.2019
comment
@hyde -- ฉันคิดว่าคุณปลอดภัย ไม่มีอะไรเกี่ยวกับปลาที่ต้องทำก่อนตี 5   -  person David C. Rankin    schedule 26.03.2019


คำตอบ (3)


มีปัญหาหลายประการในโปรแกรมของคุณ:

  • คุณควรรวม <stdio.h>
  • ข้อกำหนดการแปลง scanf() สำหรับประเภท double คือ %lf ไม่ใช่ %f
  • คุณควรทดสอบค่าที่ส่งคืนเป็น scanf() เพื่อหลีกเลี่ยงการทำงานที่ไม่ได้กำหนดกับอินพุตที่ไม่ถูกต้อง
  • การวนซ้ำจะวนซ้ำ 25 ครั้งแทนที่จะเป็น 24 ครั้ง
  • นิพจน์ vol = gal * 0.90 + add; เพื่ออัปเดตวอลุ่มไม่ถูกต้อง: คุณควรอัปเดต gal หรือใช้เพียง vol นอกจากนี้ หากเติมน้ำทุกต้นชั่วโมง ควรเป็น vol = (gal + add) * 0.90; แต่ถังจะบรรจุได้ไม่เกิน 500 แกลลอน หากเติมน้ำทุกสิ้นชั่วโมง คุณควรทดสอบว่ามีปริมาณถึง 100 แกลลอนหรือไม่จึงค่อยเติมน้ำเพิ่ม
  • คุณไม่ได้ทดสอบขีดจำกัดที่ 100 แกลลอน
  • รูปแบบ printf ไม่ถูกต้อง เช่นเดียวกับอาร์กิวเมนต์: ควรเป็น printf("The volume is %f gallons after %f hours. \n", vol, hour); หรือดีกว่า printf("The volume is %f gallons after %d hours. \n", vol, hour); และ hour ควรถูกกำหนดเป็น int
  • main ควรส่งคืน 0

นี่คือเวอร์ชันที่ได้รับการแก้ไข:

#include <stdio.h>

int main() {
    double add, gal = 500, vol;
    int hour;

    printf("Please enter additional water added per hour: ");
    if (scanf("%lf", &add) != 1) {
        printf("invalid input\n");
        return 1;
    }
    for (vol = gal, hour = 1; hour <= 24; hour++) {
        vol = vol * 0.90;
        if (vol <= 100)
            break;
        /* water is added at the end of each hour */
        vol += add;
        /* the tank cannot hold more than 500 gallons */
        if (vol > gal)
            vol = gal;
    }
    printf("The volume is %f gallons after %d hours.\n", vol, hour);
    return 0;
}

คุณอาจต้องการคำนวณเวลาที่แน่นอนที่ปริมาตรลดลงเหลือ 100 แกลลอน แต่จะซับซ้อนกว่า

person chqrlie    schedule 26.03.2019
comment
ใน C (เนื่องจากฉันคิดว่า C99) คุณไม่จำเป็นต้องใช้ return ใน main และหากหายไปก็คาดว่าจะส่งคืนค่า 0 - person hyde; 26.03.2019
comment
@hyde: ถูกต้องสำหรับ C99 และใหม่กว่า คณะกรรมการแฮ็กข้อกำหนด C เพื่อให้แน่ใจว่าโค้ดดั้งเดิมที่เลอะเทอะจะส่งกลับ 0 โดยปริยายหาก main ออกไปโดยไม่มีคำสั่ง return การทำให้สิ่งนี้โดยนัย return 0; ชัดเจนถือเป็นรูปแบบที่ดี - person chqrlie; 26.03.2019
comment
vol เป็น <= 100 ได้อย่างไรตั้งแต่ด้านบน vol = gal * 0.90 และ gal มีค่าคงที่ในลูป นั่นควรจะต่ำกว่า for (vol=gal, hour... และ vol *= 0.9 ไม่ใช่เหรอ? - person Breaking not so bad; 26.03.2019
comment
@RingØ: คุณพูดถูกจริงๆ! มีข้อผิดพลาดอีกหนึ่งข้ออยู่เสมอ :) - person chqrlie; 26.03.2019
comment
@chqrlie ฉันคิดว่านั่นเป็นเรื่องของความคิดเห็น ใน C ความชัดเจนเป็นสิ่งที่สำคัญ (เมื่อเทียบกับ C++ เช่น โดยที่ Constructor สามารถประมวลผลจำนวนที่ไม่ทราบจำนวนในการประมวลผลเป็นสำเนา เป็นต้น) OTOH ทุกบรรทัดที่ไม่นำสิ่งใดมาสู่โค้ดถือเป็นบรรทัดที่ไม่ดี เป็นเพียงความยุ่งเหยิง ฉันคิดว่าวิธีแก้ปัญหาที่ถูกต้องคือเปลี่ยนประเภทการส่งคืนเป็น void main() เนื่องจากได้รับอนุญาตใน C (IIRC) - person hyde; 26.03.2019
comment
@hyde: void main() ไม่ได้รับอนุญาตตามมาตรฐาน C เครื่องหมาย return 0; ที่ชัดเจนหมายถึง คืนความสำเร็จกลับสู่สภาพแวดล้อมการดำเนินการ การทำสิ่งที่โดยนัยให้ชัดเจนเป็นเรื่องของสไตล์และความชัดเจนของ IMHO ตัวอย่างเช่น char *p = NULL; จะดีกว่า char *p = 0; ซึ่งเทียบเท่ากันทุกประการแต่มีความชัดเจนน้อยกว่า - person chqrlie; 30.03.2019
comment
@chqrlie หลังจาก googling ดูเหมือนว่ามาตรฐาน C จะอนุญาตให้มีการใช้งานลายเซ็นหลักที่กำหนดไว้ (ฉันเชื่อว่าต่างจาก C ++) นี่อาจเป็นสิ่งที่ฉันจำได้ มันยังอยู่นอกเหนือจากประเด็นนี้ เนื่องจากเห็นได้ชัดว่าไม่ควรใช้อุปกรณ์ทำลายการพกพาโดยไม่มีเหตุผลที่น่าสนใจ - person hyde; 30.03.2019
comment
@hyde: C19 5.1.2.2.1 การเริ่มต้นโปรแกรม ฟังก์ชันที่ถูกเรียกเมื่อเริ่มต้นโปรแกรมมีชื่อว่า main การใช้งานไม่ได้ประกาศต้นแบบสำหรับฟังก์ชันนี้ โดยจะต้องกำหนดด้วยประเภทการส่งคืน int และไม่มีพารามิเตอร์: int main(void) { /* ... */ } หรือด้วยพารามิเตอร์สองตัว (ในที่นี้เรียกว่า argc และ argv แม้ว่าอาจใช้ชื่อใดก็ได้ เนื่องจากเป็นชื่อท้องถิ่นของฟังก์ชันที่ประกาศไว้): int main(int argc, char *argv[]) { /* ... */ } หรือเทียบเท่าหรือในลักษณะที่กำหนดการใช้งานอื่น ๆ - person chqrlie; 30.03.2019
comment
ลักษณะการใช้งานอื่นๆ ที่กำหนด มักจะอ้างถึงการเพิ่มอาร์กิวเมนต์ที่สามของระบบยูนิกซ์ เช่น: int main(int argc, char **argv, char** envp) {...} ฉันไม่สามารถคิดถึงสภาพแวดล้อม C ใด ๆ ที่ void main() จะทำให้เกิดปัญหาได้ แต่มันก็ไม่ถูกต้อง - person chqrlie; 30.03.2019

ตามที่ฉันเข้าใจ นี่เป็นเพียงการจำลองที่ไม่จำเป็นต้องมีแบบเรียลไทม์

เพียงเพิ่มบรรทัด:

if (vol <= 100) break;

ดังนั้นมันจึงออกจาก for loop

โปรดทราบว่ามีข้อผิดพลาดอื่นๆ ในโค้ดของคุณอย่างแน่นอน ตัวอย่างเช่น vol จะเป็นค่าเดียวกันเสมอ นอกจากนี้ตัวแปร hour ของคุณที่ใช้สำหรับลูป for ก็ไม่เหมือนกับที่คุณใช้ภายนอก (ใน printf เป็นต้น) คุณควรทำอะไรแบบนั้นเพื่อให้มันได้ผล:

vol = gal
for (hour = 0; hour <= 24; hour++)
{
    vol = vol * 0.90 + add;
    if (vol <= 100) break;
}
person Puck    schedule 26.03.2019

คุณสามารถใช้ฟังก์ชัน gettimeofday() เพื่อรับเวลาเริ่มต้น (เมื่อกระบวนการเริ่มต้น) จากนั้นใช้ gettimeofday() ซ้ำๆ เพื่อรับเวลาปัจจุบัน เมื่อความแตกต่างระหว่างเวลาปัจจุบันและเวลาเริ่มต้นคือ 24 ชั่วโมง ให้แยกออกจากวง

สำหรับการอ้างอิงโปรดตรวจสอบ http://man7.org/linux/man-pages/man2/gettimeofday.2.html

person Shrishty Deorari    schedule 26.03.2019
comment
ใช่แล้ว แต่การวนซ้ำ hour = 0; hour <= 24; ... ทำได้โดยอาศัยการนับลูป :) - person David C. Rankin; 26.03.2019
comment
ฉันไม่คิดว่าคำถามเกี่ยวกับการรอ 24 ชั่วโมงจริง ๆ แต่การรันการจำลองให้เร็วที่สุดแทน ดังนั้น gettimeofday จึงไม่มีประโยชน์ - person hyde; 26.03.2019