Как назначить любые незаполненные части моего массива нулевыми символами, а затем записать его в файл? - PullRequest
1 голос
/ 10 мая 2019

Я пытаюсь получить указанную ниже функцию для помещения трех вещей в файл: first, last и ssn.Первый - 30 символов, последний - 30 символов, а ssn - 9 символов.

В файле я хочу, чтобы я ввел следующую информацию: first: john last: smith ssn: 123456789

это то, что должно быть загружено в файл (все в одну строку):

Джон \ 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 \ 0123456789

Тем не менее, все, что загружается, обычно это Джон (Junk) Смит (Junk) 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:

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 \ 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 \ 0123456789 ", включая нулевые символы.Нет ли способа сделать это?Я хотел бы иметь возможность получить доступ к файлу и эффективно сказать программе «вернуться» на 30 символов от начала ssn к началу фамилии.

Strcpy и strncpy исправляютпроблема с появлением спама, но они не включают символ '\ 0' в файл.

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Код использует fwrite() для выгрузки структуры (struct student) в файл.fwrite() просто пишет двоичный двоичный объект, его не волнуют окончания строк или инициализация данных.

Вы получаете много мусора, потому что входящая структура createStudent содержит много мусора.В нем есть мусор, потому что C не будет инициализировать члены автоматически (это пустая трата времени).Если вы хотите, чтобы они были «чистыми», вы должны явно их кодировать.

Можно очистить структуру перед загрузкой в ​​нее данных с помощью вызова функции memset():

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

Который заполнит его полными 0 / NULL.Поскольку C-строки заканчиваются на '\ 0' (двоичный 0), это очищает строковые массивы от всего мусора.Обратите внимание, что на самом деле это не повредит вашему процессу, если записанные данные содержат нежелательную информацию, так что до тех пор, пока в процессе сохраняется терминатор строки.Массив [abc\0some-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 \0

        // 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
    }
}

Вы должны записать количество записей в верхнюю часть файла перед всеми телами записей.Это позволяет читать и легко обновлять.

0 голосов
/ 10 мая 2019

используйте memset () и strcpy ()

Поместите следующее сразу после malloc():

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

и используйте strcpy() вместо memcpy():

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

Это аннулирует всю структуру и будет копировать только до завершающего нуля, предполагая, что createStudent имеет строки с нулевым завершением, которые никогда не длиннее, чем определенные связанные object строки (весли это не так, вы можете использовать strncpy()).

...