如何为数组的任何未填充部分分配空字符,然后将其写入文件?

How do I assign any non-filled parts of my array with null characters, and then write it into a file?

我正在尝试使用以下函数将三项内容放入文件中:first、last 和 ssn。首先是 30 个字符,最后是 30 个字符,ssn 是 9 个字符。

我希望在文件中输入以下信息: 第一名:约翰 最后:史密斯 ssn: 123456789

这是应该加载到文件中的内容(全部一行):

john[=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=]smith[=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=][=32=]23456789

但是,加载的内容通常是 john(junk)smith(junk)123456789。

我如何做到这一点,当我将这 3 个东西写入文件时,它们在每个未使用的 space 中也有空字符?

void addStudents(struct student createStudent) {

    struct student *object = malloc( sizeof( struct student ) );

    memcpy(object->first, createStudent.first, 30);
    memcpy(object->last, createStudent.last, 30);
    memcpy(object->ssn, createStudent.ssn, 9);
    FILE *fp;
    fp = fopen("students.db", "a");

    fseek( fp, numStudents * sizeof( struct student ), SEEK_SET );
    fwrite( object, sizeof( struct student ), 1, fp );

}

这是学生结构的定义:

struct student {
    char first[30];
    char last[30];
    char ssn[9];
};

编辑:我想要文件中的空字符。就像,打开文件并让它完全按照 "john[=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=]smith[=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=][=30=]23456789" 读取,包括空字符。有没有办法做到这一点?我希望能够访问该文件并有效地告诉程序 "go back" 从 ssn 开头到姓氏开头的 30 个字符。

Strcpy 和 strncpy 确实解决了出现垃圾的问题,但它们没有在文件中包含“\0”字符。

使用 memset() 和 strcpy()

将以下内容紧跟在 malloc() 之后:

memset(object, 0, sizeof(struct student));

并在 memcpy() 上使用 strcpy()

strcpy(object->first, createStudent.first);
strcpy(object->last, createStudent.last);
strcpy(object->ssn, createStudent.ssn);

这将使整个结构无效,并且只会复制直到终止空,假设 createStudent 具有空终止字符串,这些字符串永远不会长于定义的相关 object 字符串(如果它是不,你可以使用 strncpy()).

代码使用 fwrite() 将结构 (struct student) 转储到文件中。 fwrite() 只写一个二进制 blob,它不关心 string-endings 或数据初始化。

您得到了很多垃圾,因为传入的 createStudent 结构包含很多垃圾。它里面有垃圾,因为 C 不会自动初始化成员(这是浪费时间)。如果你想要它们 "clean",你必须明确地编码。

可以在调用 memset() 函数将数据加载到其中之前清除结构:

memset( object, 0, sizeof( *object ) );

这将填满 0 / NULL。由于 C-strings 以 '\0'(二进制 0)结尾,这会清除字符串数组中的所有垃圾。请注意,如果写入的数据中有垃圾,它实际上不会损害您的进程,因此只要在进程中保留字符串终止符即可。当用作字符串时,数组 [abc[=17=]some-junk] 看起来就像 "abc"。

无论如何,所以在结构最初写入数据之前,对其进行初始化。 OP 的代码不包括这部分,所以我将它加入了 addStudents() 函数。 (请注意:您根本没有处理 numStudents)。

#define MAX_NAME_SIZE 29  
#define MAX_SSN_SIZE   8

struct student 
{
    char first[ MAX_NAME_SIZE + 1 ];
    char last[ MAX_NAME_SIZE + 1 ];
    char ssn[ MAX_SSN_SIZE + 1 ];
};

void addStudents(struct student createStudent) 
{
    struct student *object = malloc( sizeof( struct student ) );

    if ( object != NULL )
    {    
        memset( object, 0, sizeof( *object ) );  // fill with [=11=]

        // Note: string buffers zeroed and 1-char bigger, so strncpy() is safe
        strncpy( object->first, createStudent.first, MAX_NAME_SIZE );
        strncpy( object->last,  createStudent.last,  MAX_NAME_SIZE );
        strncpy( object->ssn,   createStudent.ssn,   MAX_SSN_SIZE );

        FILE *fp;
        fp = fopen("students.db", "a");
        if ( fp != NULL )
        {
            // TODO: check these functions don't return error
            fseek( fp, numStudents * sizeof( struct student ), SEEK_SET );  // Necessary when open "a"?
            fwrite( object, sizeof( struct student ), 1, fp );
            fclose( fp );  // Don't forget to close
        }
        else
        {
             // TODO: handle file error
        }
    }
    else
    {
        // TODO - handle memory error
    }
}

您应该考虑将记录数写入文件顶部,在所有 record-bodies 之前。这使您可以轻松阅读和更新它。