| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1577 人关注过本帖
标题:C语言最简单的修改文本文件?
只看楼主 加入收藏
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 9楼 TonyDeng
1    1    1    18177286824    1    2    2    2    18177286824    2
把前面三个1改成2
2015-08-03 15:50
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 9楼 TonyDeng
1    1    1    18177286824    1    2    2    2    18177286824    2
会不会太简单了?把前面的三个1改成了2
2015-08-03 16:24
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:20 
大概是下面的样子。
程序代码:
#include <cstdio>
#include <cstdlib>
#include <conio.h>

struct Student
{
    char Name[11];
    char Sex;
    long Birthday;
    Student* next;
};

void Init(void);
void Save_Data(const char* filename, Student* students, size_t count);
Student* Load_Data(const char* filename);
void Update_Data(const char* filename, const Student* student, size_t index);
void List_Students(Student* students);
void Show_Student(const Student* student);

const char* FileName = "Students.DAT";

int main(void)
{
    Init();

    Student* students = Load_Data(FileName);
    List_Students(students);

    printf_s("Now update record 2\n");
    students->next->Birthday = 19921014;
    students->next->Sex = 0;
    Update_Data(FileName, students->next, 2);    // 用指针students-next所指向的数据,刷写文件中的第2条记录
    students = Load_Data(FileName);
    List_Students(students);

    printf_s("\nPress any key to continue...");
    _getch();
    return EXIT_SUCCESS;
}

void Init(void)
{
    Student students[3] = {
        { "张三", 0, 19920312 },
        { "李四", 1, 19921004 },
        { "王五", 0, 19930120 }
    };
    Save_Data(FileName, students, _countof(students));
}

void Save_Data(const char* filename, Student* students, size_t count)
{
    FILE* file;

    if (fopen_s(&file, filename, "wb") == 0)
    {
        fwrite(&count, sizeof(count), 1, file);
        for (size_t index = 0; index < count; ++index)
        {
            fwrite(&students[index], sizeof(Student), 1, file);
        }
        fclose(file);
    }
    else
    {
        printf_s("File %s create failure.\n", filename);
    }
}

Student* Load_Data(const char* filename)
{
    FILE* file;
    Student* head = NULL;

    if (fopen_s(&file, filename, "rb") == 0)
    {
        size_t count;
        Student* previous = NULL;
        fread(&count, sizeof(count), 1, file);
        for (size_t index = 0; index < count; ++index)
        {
            Student* stu = (Student*)calloc(1, sizeof(Student));
            if (stu != NULL)
            {
                (previous != NULL) ? (previous->next = stu) : (head = stu);
                fread(stu, sizeof(Student), 1, file);
                previous = stu;
            }
            else
            {
                printf_s("Memory allocation error.\n");
                break;
            }
        }
        fclose(file);
    }
    else
    {
        printf_s("File %s read failure.\n", filename);
    }

    return head;
}

void Update_Data(const char* filename, const Student* student, size_t index)
{
    FILE* file;

    if (fopen_s(&file, filename, "rb+") == 0)
    {
        size_t count;
        fread(&count, sizeof(count), 1, file);
        fseek(file, (index - 1) * sizeof(Student), SEEK_CUR);
        fwrite(student, sizeof(Student), 1, file);
        fclose(file);
    }
    else
    {
        printf_s("File %s update failure.\n", filename);
    }
}

void List_Students(Student* students)
{
    while (students != NULL)
    {
        Show_Student(students);
        students = students->next;
    }
}

void Show_Student(const Student* student)
{
    printf_s("%-10s   %2s   %u\n", student->Name, (student->Sex == 0) ? "" : "", student->Birthday);
}


程序功能:首先用一个设定的数组初始化并生成一个数据文件,然后把数据从文件中读入一个链表中,显示给你看原始的数据是什么;修改文件上第2条记录的内容,重新读入,再显示给你,验证的确已经改了。

注:这个代码没有释放链表动态分配的内存。对Windows系统来说,实际上可以不加,但若要养成移植习惯,应自己加上。

程序的效果如下,把第二条记录的性别和生日数据改了:
图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 TonyDeng 于 2015-8-3 18:09 编辑 ]

授人以渔,不授人以鱼。
2015-08-03 18:00
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
所谓二进制文件读写,是指文件数据是以内存原始格式储存的,不是人类阅读的文本。与此相对应,人类平常阅读的那种叫文本格式。这就是fopen()中b和t的区别,b是binary,t是text。文本文件通过诸如fscanf()和scanf()之类的函数读入,是把字符串转换为内存格式,比如字符串"123",人类看认为是十进制数字123456789,但这其实是9个字符构成的字符串,不是计算机内部的int格式(32位机是4字节),scanf()函数族把这种字符串计算转换为int(就像你平时做过的那种数据转换练习),才是数值数据。同样,对printf()函数族,也是这般逆转换。这些转换动作是要花时间的,而且,转换出来的结果,可能是不等长的,比如上面的数据,123456789被转成10个字节的字符数组,但内存中实际上永远是4个字节,这样计算机是好计数了——这就是13楼程序直接用结构体尺寸乘数跳转文件位置指示器读写数据的原理,它不用把数据从头读一次,也仅仅处理需要处理的尺寸,哪怕文件再庞大,也是一般的高效率。不过,二进制文件储存和读写有利也有弊,就是这种数据文档往往是不可移植的,在机器内部尺寸不同的计算机上,用sizeof()算出来的单位不同,必然会出错,而且,有些计算机和系统的类型也是有内部差异的。fread()/fwrite()函数对的使用,必须是自己写的自己读,最起码要是在同一环境中。当然,现实中碰到频繁转换环境的移植性场合不多。

授人以渔,不授人以鱼。
2015-08-03 18:33
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 14楼 TonyDeng
太棒了,我好好研究一下那个程序,然后不懂再问问你蛤,真心好谢谢你。
2015-08-04 02:53
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 13楼 TonyDeng
请问一下你的程序是用什么软件编译的?
2015-08-04 02:53
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
vc

授人以渔,不授人以鱼。
2015-08-04 09:40
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 17楼 TonyDeng
VC++6.0里面printf_s会报错呀,怎么弄?
2015-08-04 19:43
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
超过6的版本都可以

授人以渔,不授人以鱼。
2015-08-04 19:54
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
vc现在已经是版本14了,还在用版本6,都不知道怎么想的。

授人以渔,不授人以鱼。
2015-08-04 19:56
快速回复:C语言最简单的修改文本文件?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020965 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved