อ่านไฟล์ข้อความและการเรียงลำดับสองอาร์เรย์

ฉันมี "Temp.dat" ที่มี 200 บรรทัดที่มีลักษณะดังนี้:

0.060493 1 0.5 1
1.596961 0 0.1 2
0.87758  1 0.3 1.5
0.165453 1 0   3
0.07085  1 0.3 4
0.125379 1 0.2 3
0.454202 1 0.2 2
0.373227 1 0.3 1
0.131486 1 0.3 3
0.867477 0 0.5 4
0.122609 0 0.8 9

ฉันกำลังพยายามอ่านแต่ละบรรทัดและเก็บข้อมูลแต่ละคอลัมน์ไว้ในอาร์เรย์แยกกันด้วยรหัสต่อไปนี้:

#include <stdio.h>
#include <stdlib.h>
#define MAX 200

int main(){

  double x[MAX], y[MAX];
  double a, b;
  int m = 0;
  FILE* file; 
  file = fopen("Temp.dat", "r");
  if ( file != NULL ){
      /* Read the two columns. */
      while(fscanf(file, "%d %d", &a, &b) == 2)
      { x[m] = a;
        y[m] = b;
        m++;
      }
  }
  printf("%d %d\n", x[4], y[1]); # Test the stored inputs of the two arrays
  return(0);
}    

เมื่อฉันลองพิมพ์ผลลัพธ์ มันให้ 1 13258992 แทนที่จะเป็น 0.165453 0 ฉันไม่เข้าใจว่ามันได้คู่ 1 13258992 มาจากไหน เพราะฉันคิดว่าบรรทัด fscanf(file, "%d %d", &a, &b) == 2 ทำในสิ่งที่ควรจะทำ: ดูแต่ละแถวของไฟล์ Temp.dat และอ่านจำนวนเต็ม double-type สองตัว จากนั้นจัดเก็บไว้ในอาร์เรย์ทั้งสอง x[MAX] และ `y[MAX ] ดังนั้นใครสามารถช่วยฉันแก้ไขปัญหานี้ได้บ้าง

คำถามอื่น: หลังจากเก็บสองคอลัมน์ด้านบนไว้ในอาร์เรย์ 2 ชุด x[MAX] และ y[MAX] แล้ว ฉันต้องการจัดเรียงทั้งสองอาร์เรย์ตามลำดับที่เพิ่มขึ้นตามค่าในอาร์เรย์แรก x[MAX] สิ่งนี้จะมีลักษณะดังนี้:

    0.060493 1
    0.07085  1
    0.122609 0
    0.125379 1
    0.131486 1
    0.165453 1
    0.373227 1
    0.454202 1
    0.867477 0

ฉันจะทำรูทีน sorting ใน C ได้อย่างไร เนื่องจากการจัดเรียงองค์ประกอบใน y[MAX] ให้เป็นไปตามลำดับองค์ประกอบที่เกี่ยวข้องใน x[MAX] ค่อนข้างยาก


person user177196    schedule 19.02.2018    source แหล่งที่มา
comment
@Pablo: ขอบคุณสำหรับความช่วยเหลือของคุณ ฉันเพิ่มเงื่อนไขใน while แล้วเปลี่ยน %d เป็น %lf แต่ผลลัพธ์ยังคงไม่ถูกต้อง ตอนนี้มันให้ฉัน -1 34902256 สำหรับ x[4] y[1] เดียวกัน คุณช่วยให้คำแนะนำเกี่ยวกับวิธีการเรียงลำดับอาร์เรย์ที่สองในขณะที่ฉันกำลังสลับแต่ละองค์ประกอบของอาร์เรย์แรกได้หรือไม่?   -  person user177196    schedule 19.02.2018
comment
ฉันลบความคิดเห็นของฉันและโพสต์เป็นคำตอบ คุณมีข้อผิดพลาดเดียวกันในการเรียก printf ดูคำตอบของฉัน   -  person Pablo    schedule 19.02.2018


คำตอบ (3)


คุณสามารถประกาศโครงสร้างด้วย x และ y เพื่อให้ทั้งสองค่าเชื่อมโยงกัน x และ y จะรักษาความสัมพันธ์ไว้เมื่อมีการสลับองค์ประกอบอาร์เรย์ระหว่างการเรียงลำดับ ตัวอย่าง:

struct data_t
{
    double x;
    int y;
};

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;
    if(m->x == n->x)
        return m->y > n->y;
    return m->x > n->x;
}

int main(void) 
{
    struct data_t data[MAX];
    FILE* file = fopen("Temp.dat", "r");
    int count = 0;
    while(fscanf(file, "%lf %d", &data[count].x, &data[count].y) == 2)
    {
        count++;
        if (count == MAX)
            break;
    }

    qsort(data, count, sizeof(struct data_t), compare);
    for(int i = 0; i < count; i++)
        printf("%lf %d\n", data[i].x, data[i].y);
    return 0;
}

ใช้ %lf สำหรับค่า double หรือใช้ %f สำหรับ float ดังที่แสดงในคำตอบอื่นๆ

เกี่ยวกับฟังก์ชันเปรียบเทียบ สมมติว่าคุณมีค่าเหล่านี้ในข้อมูลของคุณ:

0.060493 1
0.060493 5
0.060493 2

ในกรณีนี้ ค่า x จากองค์ประกอบแรกจะเหมือนกับค่า x จากองค์ประกอบอื่น หากคุณทดสอบเฉพาะ m->x > n->x การเรียงลำดับจะไม่เกิดขึ้น ดังนั้น คุณต้องการเปรียบเทียบ m->y > n->y ถ้า x เหมือนกัน

qsort เป็นฟังก์ชัน C มาตรฐาน มันไม่รู้จักประเภทข้อมูลของคุณ เราต้องบอกมันเกี่ยวกับประเภทข้อมูล เสร็จสิ้นภายในฟังก์ชันการเปรียบเทียบซึ่งรับพอยน์เตอร์ a และ b เรารู้ว่าสิ่งเหล่านี้คือพอยน์เตอร์ไปยังองค์ประกอบในอาร์เรย์ data นั่นคือเหตุผลเบื้องหลังการแปลง

ชุดข้อมูลสามารถมีได้สูงสุด 200 รายการ เนื่องจากเราประกาศว่าเป็น struct data_t data[MAX]; โดยที่ MAX คือ 200


แก้ไข 3 ******
ทำงานกับอาร์เรย์ ประกาศอาร์เรย์:

double arr[MAX + 1][8]

โปรดทราบว่าดัชนีแรกของอาร์เรย์คือแถวตั้งแต่ 0 ถึง MAX ตั้งค่าไว้แบบนี้จึงสามารถจัดเรียงได้ทีหลัง ตอนนี้เราสามารถอ่านไฟล์ลงในอาเรย์ได้โดยตรง และเรียงลำดับอาเรย์ได้ (ไม่จำเป็นต้องใช้โครงสร้าง) ตรวจสอบให้แน่ใจว่าคุณไม่ปะปนกับโซลูชันเก่าซึ่งมี arr[8][MAX + 1]

int compare_2d_array(const void *pa, const void *pb)
{
    double a = *(double*)pa;
    double b = *(double*)pb;
    return a > b;
}

int main(void)
{
    //array with MAX + 1 rows, and 8 columns, initialized to zero
    double arr[MAX + 1][8] = { 0 };
    FILE* file = fopen("temp.dat", "r");
    int count = 0;
    while(fscanf(file, "%lf %lf", &arr[count][0], &arr[count][1]) == 2)
    {
        count++;
        if(count == MAX) break;
    }

    qsort(arr, count, sizeof(arr[0]), compare_2d_array);

    //arr[0] and arr[1] are ready, now set up the other columns:
    for(int i = 0; i < count; i++)
    {
        //make modifications to other columns
        arr[i][2] = i ? arr[i - 1][0] : 0;
        arr[i][3] = arr[i][0];
        arr[i + 1][4] = i + 1;

        printf("%.6lf %.0lf %.6lf %.6lf %.0lf\n", 
                    arr[i][0], arr[i][1], arr[i][2], arr[i][3], arr[i][4]);
    }
    return 0;
}
person Barmak Shemirani    schedule 19.02.2018
comment
ฉันลองใช้โค้ดของคุณแล้ว และมันใช้งานได้กับชุดข้อมูลอย่างน่าอัศจรรย์!! ขอบคุณมากสำหรับความช่วยเหลือของคุณ. ฉันมีคำถามอยู่บ้าง คุณช่วยอธิบายให้ฉันฟังได้ไหมว่าทำไมถึงส่งคืน m->y > n->y ในฟังก์ชัน compare() ของคุณ? นอกจากนี้การประกาศตัวชี้ const struct data_t *m = a ยังช่วยได้?? struct data_t = ชุดข้อมูลที่มีคู่ $200$ เป็น (x,y) หรือไม่ - person user177196; 19.02.2018
comment
ขอบคุณมากสำหรับความช่วยเหลือของคุณ เพราะมันค่อนข้างชัดเจน!! ฉันมีคำถามอื่น: จากทั้งสองคอลัมน์ สมมติว่าคอลัมน์แรกหมายถึงเวลา $T$ และคอลัมน์ที่สองหมายถึง 1= Death occurs และ 0 = Censor occurs ฉันต้องการสร้างอาร์เรย์สองชุด ซึ่งจัดเก็บปริมาณที่คำนวณได้ต่อไปนี้: อาร์เรย์แรกเก็บจำนวนบุคคลที่ มีชีวิตอยู่ และ ไม่ ที่ถูกเซ็นเซอร์ระหว่างสอง ต่อเนื่องกัน ช่วงเวลา และอาร์เรย์ที่สองจะเก็บจำนวนการตายที่เกิดขึ้นในช่วงเวลา เดียวกัน คุณช่วยได้ไหมว่าฉันควรทำอย่างไรกับลูป int array[MAX] และ for - person user177196; 19.02.2018
comment
ฉันพยายาม for (int i = 0; i<m; i++){sum[i] = MAX - i;} แต่แล้ว printf("%d", &sum[4]) ก็ไม่แสดงผลอะไรเลยสำหรับฉัน ไม่แน่ใจว่าทำไมจึงไม่เก็บไว้ในอาร์เรย์ sum[]? นอกจากนี้ ฉันต้องการจัดเก็บคอลัมน์แรกลงในอาร์เรย์โดยที่แต่ละองค์ประกอบ = ช่วงเวลาที่ต่อเนื่องกันซึ่งจุดสิ้นสุดสอดคล้องกับ 1 ในคอลัมน์ที่สอง (ดังนั้น ไม่มีจุดสิ้นสุดใดที่จะสอดคล้องกับ 0) แต่ฉันสะดุดกับวิธีการเขียนเงื่อนไขที่ซับซ้อนเช่นนี้ คุณช่วยหน่อยได้ไหม? - person user177196; 19.02.2018
comment
ฉันลอง printf("%d", sum[4]) แล้วเหมือนกัน แต่ก็ยังไม่สามารถพิมพ์อะไรเลย (แม้ว่าจะไม่มีข้อความแสดงข้อผิดพลาดเกิดขึ้นก็ตาม) อย่างไรก็ตาม คุณช่วยแสดงวิธีจัดเก็บช่วงเวลาต่อเนื่องในอาร์เรย์ที่มีจุดสิ้นสุดทั้งสองเท่ากับ 1 ในคอลัมน์ที่ 2 ได้ไหม ตัวอย่างเช่น อาร์เรย์ที่มีองค์ประกอบ [0, 0.060493), [0.060493, 0.07085), [0.07085, 0.122609) เป็นต้น ฉันคิดว่าฉันอาจต้องใช้อาร์เรย์ 2 มิติ ซึ่งหนึ่งในนั้นคือการจัดเก็บช่วงเวลา อีกอย่างคือเพื่อเก็บผลลัพธ์การคำนวณ และดัชนีของทั้งสองนี้ตรงกันทุกประการ ( เช่น สำหรับ t\in [0, 0.060493) เรามี result 1) - person user177196; 19.02.2018
comment
ให้เราสนทนาต่อในการแชท - person user177196; 19.02.2018
comment
ดูที่ (แก้ไข 3 ****) รวมสิ่งนั้นไว้ในคำถามใหม่ของคุณพร้อมกับตัวอย่างอินพุตและผลลัพธ์ที่คาดหวัง - person Barmak Shemirani; 20.02.2018
comment
ถ้าฉันเพิ่มสองคอลัมน์เพิ่มเติมลงในชุดข้อมูลดั้งเดิม คุณรู้วิธีจัดเรียงองค์ประกอบในสองคอลัมน์นั้นตามผลการเรียงลำดับของคอลัมน์แรกหรือไม่ ฟังก์ชัน compare() ของคุณ แต่มีตัวชี้เพิ่มเติม 2 ตัวในการตั้งค่าอินพุต ยังคงใช้งานได้ (เช่น ` int comparison(const void *a, const void *b, const void *c, const void *d)`) หรือไม่ - person user177196; 01.03.2018
comment
คุณช่วยฉันด้วยคำถามของฉันในความคิดเห็นด้านบนได้ไหม ฉันแก้ไขชุดข้อมูลดั้งเดิมเพื่อความชัดเจน ฉันพยายามเขียน int compare_4d_array(const void *a, const void *b, const void *c, const void *d) แต่กลับล้มเหลว - person user177196; 08.03.2018
comment
ฉันไม่ได้ตั้งใจจะเรียงลำดับสิ่งอื่นใด ยกเว้นการเปลี่ยนแถวที่สอดคล้องกันของรายการในคอลัมน์ 2 และ 3 ด้านบนเป็นแถวที่ถูกต้องหลังจากเรียงลำดับตามคอลัมน์ 0 และ 1 ด้านบนตามที่คุณนำเสนอ แต่ฉันจะเริ่มคำถามใหม่แล้ว - person user177196; 09.03.2018
comment
ฉันสับสน. ความคิดเห็นก่อนหน้าของฉันไม่สมเหตุสมผล คุณยังคงมีอาร์เรย์ 2 มิติ หนึ่ง ไม่มีอาร์เรย์ 4 มิติ คงฟังก์ชัน proc เป็น compare_2d_array(const void *element1, const void *element2) - person Barmak Shemirani; 09.03.2018
comment
คุณสามารถถามคำถามใหม่โดยยึดตามการเรียงลำดับอาร์เรย์ 2 มิติ โดยยึดตาม 2 คอลัมน์ขึ้นไป นอกจากนี้ อีกคำถามหนึ่ง ฉันได้แสดงวิธีจัดเรียงโครงสร้าง ซึ่งเป็นแนวคิดที่คล้ายกัน - person Barmak Shemirani; 09.03.2018
comment
ขอบคุณมากสำหรับความช่วยเหลือของคุณ. คุณช่วยแชร์ลิงก์ไปยังคำถามนั้นกับฉันได้ไหม - person user177196; 09.03.2018
comment
ฉันโพสต์อันใหม่แล้ว! stackoverflow .com/questions/49183054/. กรุณาช่วย. - person user177196; 09.03.2018

สำหรับผู้เริ่มต้น ให้ลอง:

double a;
int b;

...

fscanf(file, "%f %d", &a, &b)

คุณกำหนดค่าเริ่มต้น a และ b เป็นประเภทคู่ แต่คุณกำลังอ่านจำนวนเต็ม (%d) จากไฟล์ copy.dat b เป็นค่า int ดังนั้นให้ปล่อย %d ไว้ใน fscanf และเปลี่ยนการกำหนดค่าเริ่มต้น

person Tukanuk    schedule 19.02.2018
comment
ฉันเข้าใจแล้ว. ขอบคุณมากมาย คุณช่วยเกี่ยวกับฟังก์ชั่นการเรียงลำดับได้ไหม? - person user177196; 19.02.2018
comment
ทำการค้นหาการเรียงลำดับแบบฟอง มันไม่ใช่การเรียงลำดับที่มีประสิทธิภาพที่สุดหรือสวยที่สุด แต่ง่ายต่อการเขียนโค้ด และโดยทั่วไปจะทำงานได้ถึง 200 ค่าในทันที - person Tukanuk; 19.02.2018
comment
ในการรับอาร์เรย์ y ตามการเรียงลำดับของอาร์เรย์ x ให้ใช้ตรรกะการค้นหากับอาร์เรย์ x เท่านั้น แต่สลับทั้งอาร์เรย์ x และ y ในเวลาเดียวกัน - person Tukanuk; 19.02.2018

ขั้นแรกให้เพิ่ม && m < MAX ในเงื่อนไข while เพื่อที่คุณจะได้ไม่ทำให้บัฟเฟอร์ล้น

scanf คาดหวังด้วย %d ตัวชี้ไปที่ int ไม่ใช่ double และจะแยกวิเคราะห์เนื้อหาเป็นจำนวนเต็ม คุณต้องใช้ %lf เพื่อแยกวิเคราะห์ doubles เช่นเดียวกับการโทร printf:

while(fscanf(file, "%lf %lf", &a, &b) == 2 && m < MAX)
    ...

...

printf("%lf %lf\n", x[4], y[1]);

ฉันเข้าใจ

0.070850 0.000000

ซึ่งเป็นบรรทัดที่ห้าของไฟล์ dat ของคุณ (ไม่ใช่บรรทัดที่สี่ ดัชนีอาร์เรย์เริ่มต้นด้วย 0 ไม่ใช่ 1)

สำหรับคำถามอื่นของคุณ:

ฉันเกรงว่าคุณจะต้องเขียนฟังก์ชันการเรียงลำดับของคุณเอง

person Pablo    schedule 19.02.2018
comment
มาแล้วภาคแรก!! ขอบคุณมากสำหรับความช่วยเหลือของคุณปาโบล ฉันใช้ OS ของ Mac คุณช่วยแสดงวิธีดำเนินการกับ qsort_r ให้ฉันดูได้ไหม - person user177196; 19.02.2018
comment
อย่างที่ฉันบอกไป qsort_r เป็นส่วนขยาย GNU ของคอมไพเลอร์ GCC คุณจะต้องคอมไพล์ด้วยคอมไพเลอร์ GCC ขออภัยที่ทำให้คุณสับสน แต่แม้แต่ qsort_r ก็คงไม่ช่วยอะไรในที่นี้ เพราะคุณจำเป็นต้องรู้ว่ามีการเปรียบเทียบดัชนีใดในอาร์เรย์ และ qsort ส่งผ่านค่า ไม่ใช่ดัชนี ฉันเกรงว่าคุณจะต้องเขียนฟังก์ชันการเรียงลำดับของคุณเอง - person Pablo; 19.02.2018