C 从一个文件读取数据并将其写入另一个文件

标签 c file-io

问题:

我正在开发一个项目,该项目使用二叉搜索树和文件输入/输出。二叉搜索树似乎运行正常,但是要求之一是能够通过文件的输入将数据添加到二叉树(然后输出所有二叉树数据)。我使用 fgets+sscanf 方法查看文件,看起来它正确地获取了所有项目,但字符串发生了很大的改变。我怀疑这是一个空终止符问题,但无法确定我可以在哪里修复它。当我手动将节点添加到二叉树(而不是从文件中)时,它们会毫无问题地添加,并毫无问题地写入新的文本文件。唯一的问题来自于从文件中读取数据,这会引发一些奇怪的错误,从而修改我的数据(例如,字符串以奇怪的格式出现,如 é@—Ç,而不是 FirstName1 LastName1 的预期输出)。

还要道歉,我对 C 还很陌生。所以它可能看起来有点困惑。

<小时/>

我的(徒劳的)尝试:

如下面的代码所示,我尝试手动向字符串添加空终止符,因为我认为这是问题所在。我尝试更改文件内容并在其中添加空终止符,并且我也尝试使用 fscanf 方法来读取文件。我研究了其他 stackoverflow 页面,寻找我可能丢失的东西,但我没有找到任何东西。我确信这是我忽略的一些愚蠢的事情。

<小时/>

我的文本文件:

同样,下面的这些文本文件内容仅与从文件中添加的内容有关。我通过使用字符串文字调用 addNode 函数手动添加的任何内容都可以正常工作

我尝试从中添加学生的“输入”文本文件(又名 addFile 在我的测试中使用):

400085 FirstName1 LastName1 3.88 CompSci
400076 FirstName2 LastName2 2.77 LibertyArts

writeFile 使用的我的“输出”文本文件:

400085  é@—Ç 3.880000 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
400076  é@—Ç 2.770000 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
<小时/>

代码:

添加文件 获取字符串名称,查找文件并打开其内容

void addFile(char* name) {
    FILE* myFile = fopen(name, "r");
    if (myFile == NULL) {
        perror(name);
        return;
    }
    int tempId = 0;
    char firstName[100];
    char lastName[100];
    double GPA = 0.0;
    char major[100];
    int res = 0;
    char line[10000];

    while (fgets(line, 1000, myFile) != NULL) {
        res = sscanf(line, "%d %s %s %lf %s", &tempId, firstName, lastName, &GPA, major);
        firstName[99] = '\0';
        lastName[99] = '\0';
        major[99] = '\0';
        addNode(tempId, firstName, lastName, GPA, major);
    }

    fclose(myFile);
}

写入文件 将二叉搜索树的内容写入文本文件 testFile.txt

void preorder(struct Node* nodeAt) {
    char buffer[10000];
    snprintf(buffer, sizeof(buffer), "%d %s %s %lf %s \n", nodeAt->id, nodeAt->firstName, nodeAt->lastName, nodeAt->GPA, nodeAt->major);
    strcat(tempString, buffer);
    if (nodeAt->leftChild != NULL)
        preorder(nodeAt->leftChild);
    if (nodeAt->rightChild != NULL)
        preorder(nodeAt->rightChild);
}

void writeFile() {
    FILE* fp = fopen("testFile.txt", "w");
    tempString = (char*) malloc(sizeof(char*) * 10000);
    preorder(root);
    fprintf(fp, "%s", tempString);
    free(tempString);
    tempString = "";
}

addFile调用的其他相关函数

/*
createNode() method
"safe" way of creating the node. Also cleans up the code.
*/
struct Node* createNode(int id, char* firstName, char* lastName, double GPA, char* major) {
    struct Node* myNode = (struct Node*) malloc(sizeof(struct Node));

    if (myNode != NULL) {
        myNode->id = id;
        myNode->firstName = firstName;
        myNode->lastName = lastName;
        myNode->GPA = GPA;
        myNode->major = major;
        myNode->rightChild = NULL;
        myNode->leftChild = NULL;
        myNode->parent = NULL;
        return myNode;
    }
    else
        return NULL;
}

/*
addNode() + addNodeHelper() methods
Adds a node to the binary tree. The helper method is just recursive to make searching easier
*/
struct Node* addNodeHelper(struct Node* nodeAt, int id, struct Node* nodeToAdd) {
    struct Node* temp = nodeAt;

    if (temp->leftChild == NULL && id < temp->id) {
        nodeAt->leftChild = nodeToAdd;
        nodeAt->leftChild->parent = nodeAt;
    }
    else if (temp->rightChild == NULL && id > temp->id) {
        nodeAt->rightChild = nodeToAdd;
        nodeAt->rightChild->parent = nodeAt;
    }

    if (id < temp->id)
        addNodeHelper(temp->leftChild, id, nodeToAdd);
    else if (id > temp->id)
        addNodeHelper(temp->rightChild, id, nodeToAdd);
}

void addNode(int id, char* firstName, char* lastName, double GPA, char* major) {
    struct Node* myNode = createNode(id, firstName, lastName, GPA, major);
    if (myNode != NULL) {
        struct Node* findTheNode = findNode(root, myNode->id);
        if (root == NULL) {
            root = myNode;
            return;
        }
        if (findTheNode != NULL) {
            printf("ERROR: Student ID must be unique!\n");
            return;
        } else
            addNodeHelper(root, myNode->id, myNode);
    }
}

非常感谢任何提示/建议:)

最佳答案

createNode 只是保存指向它所给定字符串的指针。 addFile 每次循环都会覆盖相同的字符串,因此每个节点都有相同的指针。此外,这些是局部变量,因此在 addFile 返回后指针将变得无效。

您需要复制字符串。

        addNode(tempId, strdup(firstName), strdup(lastName), GPA, strdup(major));

关于C 从一个文件读取数据并将其写入另一个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59278444/

相关文章:

c - 如何找到程序的堆栈内存的起始和结束地址?

c - 在顶层理解 "' const',这可能会在不提高 const 正确性的情况下降低代码可读性”

python根据条件替换单词

c++ - 不使用系统定义的头文件位置的 gcc 编译

c - 超出分配内存的指针访问不会导致段错误

c - VB6字符串到char*转换: avoid null character

Java程序比较两个文本文件,然后将第一个文本文件中找到的变量替换为第二个文件中的变量到第三个文件中

javascript - 如何在 HTML 文档中插入文本文件的单行?

C 编程 : Error in program. 不会显示用户输入的文件的最大/最小/平均值

Java OutputStream 相当于 getClass().getClassLoader().getResourceAsStream()