我正在尝试获取以下功能,将三件事放入文件中:第一,最后和ssn。首先是30个字符长,最后30个字符长,而SSN长9个字符。
我想在文件中发生的事情是我输入以下信息:第一:约翰最后:史密斯SSN:123456789
这是应该加载到文件中的内容(所有一行(:
john 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0smith 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0123456789
但是,所有负载通常是约翰(垃圾(史密斯(垃圾(123456789。
我如何做到这一点,以便当我将这3件事写入文件中时,它们在每个未使用的空间中也有空字符?
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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0smith 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0123456789",包括空字符。有没有办法这样做?我希望能够访问该文件,并有效地告诉程序从SSN的开头到姓氏的开头"回去" 30个字符。
strcpy和strncpy确实可以通过垃圾出现解决问题,但它们不包括文件中的" 0"字符。
代码正在使用fwrite()
将结构(struct student
(转储到文件中。fwrite()
只是写一个二进制斑点,它不在乎弦线或数据初始化。
您会得到很多垃圾,因为传入的createStudent
结构包含很多垃圾。它有垃圾,因为C不会自动初始化成员(这是浪费时间(。如果您要它们"清洁",则必须明确编码。
可以通过调用memset()
函数将数据加载到其中之前清除结构:
memset( object, 0, sizeof( *object ) );
它将填充为0/nulls。由于C-串以" 0"(二进制0(终止,这清除了所有垃圾的字符串阵列。请注意,如果书面数据中有垃圾,它实际上不会损害您的过程,因此只要在此过程中保留字符串终结器即可。阵列[abc 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
// 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
}
}
在所有记录体之前,您应该考虑将记录数写入文件顶部。这使您可以阅读并轻松更新它。
使用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
的null终止字符串,这将使整个结构无效,并将仅复制直到终止NULL,这些字符串永远不会超过定义的相关object
(如果不是,则可以使用strncpy()
(。<</