hm_cxy 2024-12-18 11:22 采纳率: 0%
浏览 15

c语言在文件中读取数据,排序,写入数据

题目:
下面是一个控制点文件的样本,第一行代表控制点数,后面每一行为一个控制点,其数据信息从左到右分别为ID(控制点编号),x,y,z坐标。要求编写一个函数读取控制点数据并按照x坐标从小到大排序,保存到一个文件中。

5
Wuhan 29.76 69.46 294.35
Beijing 65.84 50.83 275.34
Shanghai 59.36 26.68 286.82
Tianjing 37.37 49.21 300.50
Guangzhou 50.55 30.46 276.53

代码:

#include<iostream>
#include<stdio.h>
using namespace std;


struct GCP {
    char ID[32];
    double x;
    double y;
    double z;
};
bool Read(const char*strfile,GCP**pGCP,int *nGCP) {
    FILE* fp = NULL;
    fopen_s(&fp, strfile, "rt");
    if (!fp) {
        cout << "erorr"; return 0;
    }
    fscanf_s(fp, "%d", nGCP);
    *pGCP = new GCP[*nGCP];
    memset(*pGCP, 0, *nGCP * sizeof(GCP));
    for (int i = 0; i < *nGCP; i++) {
        /*if (fscanf_s(fp, "%s %lf %lf %lf", (*pGCP)[i].ID, 32, &(*pGCP)[i].x, &(*pGCP)[i].y, &(*pGCP)[i].z) != 4) {
            delete[] * pGCP;
            fclose(fp);
            return false;
        }*/fscanf_s(fp, "%s %lf %lf %lf", (*pGCP)[i].ID, 32, &(*pGCP)[i].x, &(*pGCP)[i].y, &(*pGCP)[i].z);

    }
    fclose(fp);
    return true;
};
int main() {
    int num = 0;
    GCP* p = NULL;
    FILE* fp1 = NULL;
    fopen_s(&fp1, "D:\\test2.txt", "w");
    if (Read("D:\\test1.txt", &p, &num)) {
        for (int i = 0; i < num; i++) {
            for (int j = 0; j < num - 1 - i; j++) {
                if (p[j].x > p[j + 1].x) {
                    GCP t = p[j]; p[j] = p[j + 1]; p[j + 1] = t;
                }
            }
            
        }
        for (int i = 0; i < num; i++) {
            fprintf(fp1,"%s %lf %lf %lf\n", p[i].ID,p[i].x, p[i].y, p[i].z);

        }
    }delete[]p;
    fclose(fp1);
}

有没有人解释一下为什么要用GCP**pGCP,定义指向指针的指针?
还有其实用不用if(fscanf!=4)都无所谓对吗?
还有我发现delete不能在Read函数里,要在main函数里,不然就报错,为什么啊?

  • 写回答

1条回答 默认 最新

  • Struart_R 2024-12-18 20:56
    关注

    根据要求,引自GPT-4o mini:
    1、为什么使用 GCP** pGCP ?

    在 C++ 中,使用指向指针的指针(GCP** pGCP)是在需要在函数内部动态分配内存并将其返回到调用函数时使用的一种方式。具体来说:

    GCP* pGCP 是一个指向 GCP 结构体数组的指针。在 Read 函数中,你想要动态分配内存(new GCP[nGCP]),并将这个数组的地址传回调用者。在C++中,直接返回指针是可行的,但如果希望通过函数修改指针值,就需要用到指向指针的指针(GCP* pGCP)。
    调用 Read 的时候,传入的是 &p,而 p 是一个指向 GCP 的指针变量的地址,这样在 Read 函数内部可以修改 p 的值,使得它指向新分配的内存区域。

    2、使用 if (fscanf(...) != 4) 重要吗?

    通常情况下,使用 if (fscanf(...) != 4) 这条语句可以确保你成功读取到预期的四个数据项。如果没有读取到四个项,表示出现了错误(比如文件格式不对、读取结束等),此时你应当采取适当的错误处理措施。因此,这样的检查是比较重要的。虽然你的代码中如果不使用这个检查,在一些情况下也许不会导致程序崩溃,但潜在的错误难以检测和处理,可能导致数据错误。

    3、为什么 delete 在 Read 函数里无法进行?

    这里的关键在于内存的管理和指针的作用域:

    在 Read 函数中,*pGCP 是一个局部变量指向的内存。当你使用 new 分配内存时,这块内存是动态分配的,应该根据它的生命周期进行管理。
    delete[] 在 Read 函数内部进行,如果在此时执行,实际上你会删除掉 Read 函数内部分配的内存。这样当 main 中试图使用 p 时,它指向的内存已经被释放,导致未定义行为和程序崩溃。
    你在 main 中使用 delete[] p,这是正确的做法,因为此时 p 仍然有效并指向之前在 Read 中分配的内存。这确保了内存的管理是正确的。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 12月18日