scanf หยุดทำงานหลังจากการกำหนดอาร์เรย์ 0.o?

ฉันเรียกใช้โค้ดนี้และมันจะขอให้ผู้ใช้ป้อนข้อมูล จากนั้นแฮงค์เมื่อมันเริ่มป้อนตัวเลขทั้งหมดเหล่านั้นลงในตำแหน่งอาเรย์ ฉันได้ทำการทดสอบบางอย่างไว้ที่นี่เพื่อช่วยฉันค้นหาว่าอะไรเป็นสาเหตุของการแฮงค์ ฉันไม่สามารถเข้าใจได้ มันอาจจะเป็นเรื่องง่ายอย่างโง่เขลาหรือมันจะเป็นอะไรบางอย่างกับคอมไพเลอร์ของฉัน (Code::Blocks)

    // Chapter 9 Programming Project #1

    #include <stdio.h>

    #define N 10

    void selection_sort(int n, int a[]);

    int main(void)
    {
        int i, a[N];

        printf("Enter a series of integers: ");
        for (i = 0; i < N; i++) {
            scanf("%d", &a[i]);
            printf("Scanf Test #%d and %d\n", i, a[i]);
        }

        printf("Scanf Test\n");
        selection_sort(N - 1, a);

        // iterate through array
        for (i = 0; i < N; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");

        return 0;
    }

    void selection_sort(int n, int a[n])
    {
        // Search for the highest value
        // Place that value at the end
        // Call the function with the end of the array removed
        // Create a way for it to break the cycle
        int i, temp, high = n;
        printf("Function Called\n");
        for (i = 0; i < n; i++) {
            printf("Test: %d", i);
            if (a[i] > a[high]) {
                temp = a[high];
                a[high] = a[i];
                a[i] = temp;
                printf("Test Pass: %d\n", i);
                if (n - 1 > 1)
                    selection_sort(n - 1, a);
            }
        }
    }

หมายเหตุ::โปรแกรมนี้พิมพ์ Scanf Test #0 and 1 ซ้ำไปซ้ำมาจนกระทั่งหมายเลขสุดท้ายถูกกำหนดให้กับตำแหน่งใน a[i]....โดยที่ #0 and 1, 1 จะเป็นหมายเลขแรกที่ผู้ใช้ป้อน

แก้ไข: เพื่อขจัดความสับสน หากผู้ใช้ป้อนเพียง 1 หมายเลขเป็น "1" โปรแกรมจะกำหนดค่านั้นและ/หรือค่าอื่น ๆ ทั้งหมดที่ป้อน และสามารถตรวจสอบได้ด้วย "การทดสอบ Scanf" ที่ฉันป้อน ซึ่งจะ พิมพ์ตำแหน่งในอาร์เรย์ตามด้วยหมายเลขที่กำหนด หลังจากกำหนดค่าทั้งหมดให้กับอาร์เรย์แล้ว ตามทฤษฎีแล้ว ควรรันการทดสอบถัดไปซึ่งอยู่ต่ำกว่าค่า for loop พอดี ปัญหาคือไม่มี โปรแกรมแฮงค์แทนหลังจากพิมพ์ตำแหน่งและหมายเลขล่าสุดที่ได้รับมอบหมาย....

โปรแกรมไม่ได้ทำอะไรอย่างอื่นนอกจากนั่งเฉยๆ มีคนด้านล่างระบุว่าเขารันโค้ดนี้และทำงานได้ดี...ซึ่งทำให้ฉันเชื่อว่านี่เป็นปัญหาในการคอมไพล์ใน IDU ของฉัน (Code::Blocks)


person John Conner    schedule 16.04.2014    source แหล่งที่มา
comment
แล้วจะเกิดอะไรขึ้นหลังจาก #0 และ 1 ซ้ำแล้วซ้ำอีก?   -  person M.M    schedule 16.04.2014
comment
ให้ฉันบอกว่าโค้ดนี้ดูเหมือนจะใช้ได้สำหรับฉัน (Apple LLVM 5.1) มันถามฉันถึงจำนวนเต็ม 10 ตัว และมันพิมพ์บางอย่างออกมา และสุดท้ายมันก็พิมพ์จำนวนเต็ม 10 ตัวตามลำดับที่เพิ่มขึ้น   -  person carlosdc    schedule 16.04.2014
comment
ไม่ควรเปลี่ยน if (n - 1 > 1) เป็น if (n - 1 >= 1) ใช่ไหม   -  person Mohit Jain    schedule 16.04.2014
comment
ขออภัย ฉันหมดสติหลังจากโพสต์สิ่งนี้ มันค้าง มันไม่เคยได้รับการทดสอบหลังจากวนซ้ำ   -  person John Conner    schedule 17.04.2014
comment
ขอบคุณ carlosdc ฉันคิดว่านี่เกี่ยวข้องกับคอมไพเลอร์ของฉัน ... เมื่อพิจารณาจากโค้ดเดียวกันที่ทำงานในโปรแกรมอื่น ๆ ทั้งหมดที่กำหนดอินพุตให้กับอาร์เรย์ในลักษณะเดียวกัน   -  person John Conner    schedule 17.04.2014
comment
โอ้ และอีกอย่าง นอกประเด็นนิดหน่อย แต่ฉันจะเปลี่ยนชื่อจาก user3404748 ได้อย่างไร XD   -  person John Conner    schedule 17.04.2014
comment
โอ้และ Mohit Jain นั่นเป็นการแก้ไขที่ฉันทำก่อนที่จะเพิ่มการทดสอบ เพราะในตอนแรกฉันคิดว่าฟังก์ชันของฉันทำให้เกิดการวนซ้ำไม่สิ้นสุด ดังนั้นฉันจึงเพิ่มสิ่งนั้นเพื่อให้แน่ใจว่าการเลือกจะไม่ทำงานหลังจากที่ไปถึงจุดที่ เหลือเพียงตัวละครเดียวเท่านั้น ฉันใช้วิธีการที่จะจำกัดการวนซ้ำให้แคบลงอย่างต่อเนื่อง เฉพาะค่าที่ยังไม่ได้จัดเรียงเท่านั้น   -  person John Conner    schedule 17.04.2014


คำตอบ (2)


โปรแกรมนี้พิมพ์ "Scanf Test #0 และ 1" ซ้ำไปซ้ำมา

นี่เป็นผลมาจากการไม่ตรวจสอบผลลัพธ์ของ scanf หาก scanf ไม่สามารถอ่านจำนวนเต็มได้ จะทำให้สตรีมไม่ถูกแตะต้องและรายงานความล้มเหลว คุณไม่ได้ตรวจสอบสิ่งนี้ ดังนั้นจึงทำงานได้ครั้งเดียวและล้มเหลว 9 ครั้ง

หากคุณป้อนจำนวนเต็ม 10 ก็จะทำงานได้ดี อย่างไรก็ตาม เห็นได้ชัดว่าคุณกำลังป้อนข้อมูลอื่นๆ เช่น ตัวอักษร ซึ่งทำให้การแยกจำนวนเต็มล้มเหลว

เมื่อมีข้อกำหนดการแปลงเดียว ("%d") ในสตริงรูปแบบ scanf จะสามารถส่งคืน:

  • 1 - สำเร็จ
  • 0 - ป้อนอักขระขยะ
  • EOF - ข้อผิดพลาดในการสตรีม

คุณควรตรวจสอบค่านี้และดำเนินการตามความเหมาะสม คุณสามารถยกเลิกโปรแกรมได้หากไม่ใช่ 1 แม้ว่าการล้างขยะและถามอีกครั้งในกรณี 0 จะเป็นการดี

ก้าวไปสู่การเรียงลำดับที่แท้จริง อินเทอร์เฟซของคุณแปลกเมื่อคุณส่ง N-1 ไปยังฟังก์ชัน จากนั้นให้ฟังก์ชันเข้าถึง 1 รายการที่อยู่เลยจุดสิ้นสุดของอาร์เรย์ มันจะชัดเจนกว่าถ้าทำ selection_sort(N, a) จากนั้นภายในฟังก์ชัน high = n-1 และ for (i = 0; i < n-1; i++) เป็นต้น

ขณะนี้มีปัญหาเล็กน้อยเกี่ยวกับบรรทัด:

void selection_sort(int n, int a[n])

บรรทัดนี้ไม่ตรงกับต้นแบบ คุณสามารถแก้ไขปัญหาของคุณได้โดยแทนที่บรรทัดด้วย:

void selection_sort(int n, int a[])

เวอร์ชันดั้งเดิมทำให้โปรแกรมทำงานโดยไม่คาดคิดสำหรับฉัน แต่เฉพาะเมื่อฉันเรียกใช้ gcc ในโหมดเริ่มต้น (เช่น ไม่เป็นไปตามมาตรฐาน C) จะต้องมีส่วนขยาย GNU บางอย่างในการเล่นที่ทำให้เกิดปัญหากับ int a[n]

ใน Standard C รหัสต้นฉบับควรใช้งานได้ (และหากเรียกใช้ gcc ในโหมดมาตรฐานผ่าน -std=c99 ซึ่งเป็นสิ่งที่ฉันแนะนำอย่างยิ่งให้ทำต่อไป)

person M.M    schedule 16.04.2014
comment
ขอบคุณ ฉันจำไม่ได้ว่ารหัส std=c99 หลังจากที่ฉันรีเซ็ตการตั้งค่าคอมไพเลอร์เป็นค่าเริ่มต้น (คิดว่ามันเป็นปัญหาคอมไพเลอร์) ฉันยังเขียนโค้ดไม่เสร็จเรียบร้อยและขอขอบคุณการแก้ไขอื่น ๆ ฉันไม่ได้คิดที่จะเพิ่มเช็คเข้าไปในนั้น ฉันคิดว่ามันทำให้ฉันรู้สึกแย่ที่ฉันทำ 10 ตำแหน่งในอาเรย์จริง ๆ และไม่เพิ่มการป้องกันการวิ่งหนี…ฉันจำไม่ได้ว่ามีปัญหากับ ไหลบ่าใช้วิธีนั้นมาก่อน แต่ยังไงก็เป็นแนวทางปฏิบัติที่ดีใช่ไหม? - person John Conner; 17.04.2014
comment
ในบันทึกย่อของ void select_sort(int n, int a[n])... ฉันคิดว่ามาตรฐาน C99 ช่วยให้คุณสามารถกำหนดขนาดของอาร์เรย์ในลักษณะนี้ได้ตราบใดที่คุณประกาศตัวแปรขนาดก่อนใช้งาน ฉันเชื่อว่าสิ่งนี้มีไว้สำหรับรูปลักษณ์มากกว่าอย่างอื่น แต่ใช้เพื่อช่วยเหลือผู้อื่นที่กำลังดูหรือแก้ไขโค้ดเป็นหลักเท่านั้น ฉันยังค่อนข้างใหม่กับ C ดังนั้นโปรดแก้ไขฉันด้วยถ้าฉันผิด ขอบคุณทุกท่านที่เข้ามาชม ขอบคุณมากครับ :) - person John Conner; 17.04.2014
comment
มันอนุญาตให้เป็นเช่นนั้น รหัสใช้งานได้ใน C99 แต่ใช้ไม่ได้ในโหมดที่ไม่ใช่ C99 GNU (BTW ในกรณีนี้ไม่ใช่ VLA อาเรย์จะถูกส่งผ่านเหมือนอาเรย์อื่นๆ) คำจำกัดความของฟังก์ชันควรตรงกับต้นแบบโดยไม่คำนึงถึง - person M.M; 17.04.2014
comment
ขอบคุณ Matt และ Jonathan นั่นคือปัญหาของฉัน โปรแกรมไม่มีการเช็คอินและยอมรับเพียง 10 ค่าในแต่ละครั้ง ซึ่งเป็นสิ่งหนึ่งที่ฉันไม่คิดว่าจะตรวจสอบ XD - person John Conner; 17.04.2014

ฉันรู้ว่าวิธีที่ฉันทำสิ่งนี้ค่อนข้างแหวกแนว แต่ฉันสามารถใช้ได้เฉพาะสิ่งที่ฉันได้เรียนรู้มาจนถึงตอนนี้เท่านั้น การทำเช่นนี้ทำให้ผู้ใช้สามารถป้อนจำนวนเต็ม ตัวเลขหนึ่งหรือสองหลักได้ และไม่ต้องกังวลกับการป้อนค่าจำนวนหนึ่ง...โปรดวิพากษ์วิจารณ์และเพิ่มหรือปรับปรุงวิธีการของฉันได้ตามสบาย

ขอบคุณที่ช่วยฉันในเรื่องนี้

    // Chapter 9 Programming Project #1

    #include <stdio.h>
    #include <ctype.h>

    #define N count

    void selection_sort(int n, int a[]);

    int main(void)
    {
        int i, temp, temp2, a[20], count_dgts = 0, count = 0;
        char ch;

        printf("Enter a series of integers\n");
        printf("Enter only one or two digit numbers: ");
        ch = getchar();
        for (i = 0; ch != '\n';) {
            switch (ch) {
                case '0': temp = 0; count_dgts += 1; break;
                case '1': temp = 1; count_dgts += 1; break;
                case '2': temp = 2; count_dgts += 1; break;
                case '3': temp = 3; count_dgts += 1; break;
                case '4': temp = 4; count_dgts += 1; break;
                case '5': temp = 5; count_dgts += 1; break;
                case '6': temp = 6; count_dgts += 1; break;
                case '7': temp = 7; count_dgts += 1; break;
                case '8': temp = 8; count_dgts += 1; break;
                case '9': temp = 9; count_dgts += 1; break;
                default: count_dgts = 0; break;
            }
            ch = getchar();
            if (count_dgts == 2) {
                a[i++] = (temp2 * 10) + temp;
                count += 1;
            }
            if (ch != ' ' && count_dgts == 1) {
                temp2 = temp;
            }
            if ((ch == ' ' && count_dgts == 1) ||
                (ch == '\n' && count_dgts == 1)) {
                a[i++] = temp;
                count += 1;
            }
        }
        selection_sort(N, a);
        // iterate through array
        printf("\nYour numbers in ascending order are: \n");
        for (i = 0; i < N; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");
        return 0;
    }

    void selection_sort(int n, int a[])
    {
        // Search for the highest value
        // Place that value at the end
        // Call the function with the end of the array removed
        // Create a way for it to break the cycle
        int i, temp, high = n - 1;
        for (i = 0; i < n; i++) {
            if (a[i] > a[high]) {
                temp = a[high];
                a[high] = a[i];
                a[i] = temp;
                if (n - 1 > 1)
                    selection_sort(n - 1, a);
            }
        }
    }
person Community    schedule 17.04.2014
comment
และใช่ ฉันเพิ่งรู้ว่าการเพิ่ม ctypes.h นั้นค่อนข้างไร้จุดหมาย...ฉันคิดว่าฉันจะใช้มัน แต่สุดท้ายก็ไม่จำเป็นต้องใช้มัน...ฉันกำลังทำงานกับตัวเลขไม่ใช่ตัวอักษร ดังนั้น..... - person John Conner; 17.04.2014