2016-02-14 3 views
1

Допустим, у меня есть этот student struct определено:Использование strncpy на структуры

struct student { 
    char *name; 
}; 
typedef struct student Student 

Теперь у меня есть следующая функция:

void add_student(const char *student_name) { 

    // create new student 
    Student *new_s; 
    new_s = malloc(sizeof(Student)); 

    strncpy(new_s->name, student_name, sizeof(new_s->name) - 1) 
} 

Я хочу, чтобы добавить student_name на имя нового студента структуры , Однако, поскольку const char и char разные, я должен использовать strncpy.

Я пробовал это таким образом, однако я получаю ошибку сегментации, что не так?

+2

Вместо 'strncpy' вы можете взглянуть на' strdup'. Звучит очень близко к тому, что вы пытаетесь архивировать здесь. –

+1

** НИКОГДА не используйте 'strncpy' **, это никогда не будет подходящим инструментом для работы. – chqrlie

ответ

3

Вы только выделение памяти для структуры new_s в этой линии

new_s = malloc(sizeof(Student)); 

Это включает в себя переменную char* name, которая является pointer to a char. Хотя вам также нужна память, на которую указывает этот указатель.

Итак, вам нужно выделить память для указателя на символ name внутри структуры.

// create new student 
Student *new_s; 
new_s = malloc(sizeof(Student)); 

new_s->name = malloc(100); //assuming you need to store a string of len 100 
+0

поэтому после выделения new_s-> name, я могу использовать strncpy как таковой? strncpy (new_group-> name, group_name, ) – bakedturtle

+0

@bakedturtle, Единственная проблема заключалась в том, что вы не выделили память. В противном случае ваш код должен работать после добавления этой строки. почему бы вам не запустить и проверить. – Haris

+0

Хммм - выглядит как-на-1 для меня. "' ... 100); '-> // Предполагая, что вам нужно сохранить строку len 100". Длина строки обычно не включает нулевой символ, поэтому предложите «сохранить строку длиной до 99». – chux

1

Харис дал хорошее решение. Но, как сказал Флориан Zwoch в комментариях вы можете также использовать strdup так:

void add_student(const char *student_name) 
{ 
    Student *new_s = malloc(sizeof(Student)); 
    new_s->name = strdup(student_name); 
} 

Имейте в виду, что вы должны freenew_s->name и чем freenew_s.

Вы также должны проверить возвращаемое значение malloc и strdup за NULL значение. Поскольку он возвращает NULL, если доступно недостаточно памяти.

Как примечание стороны, вы можете сократить вверх struct и typedef на одно выступление так:

typedef struct student { 
    char *name; 
} Student; 
2

Как Йохан Wentholt правильно изложил в своем ответе, вы должны выделить память для обоих Student структуры и строки его член name указывает, но вы должны вернуть новую структуру таким образом, вызывающий абонент может сделать что-то с ним:

Student *add_student(const char *student_name) { 
    Student *new_s = malloc(sizeof(Student)); 
    if (new_s) { 
     new_s->name = strdup(student_name); 
    } 
    return new_s; 
} 

вы код вызывает неопределенное поведение, потому что вы не сделали аль найти память для строки, что еще хуже, вы оставили член name неинициализированным (malloc не инициализирует память, которую он возвращает).

Кроме того, вы не должны использовать strncpy. Это не некоторая безопасная версия strcpy, очень очень ошибка склонная функция, семантика которой слабо понимается большинством программистов. НИКОГДА не используйте эту функцию. Если вы видите, что это используется, есть вероятность, что вы либо перед ошибкой, либо есть лучший способ ее заменить.

Для полноты код:

strncpy(new_s->name, student_name, sizeof(new_s->name) - 1); 
  • бы попытаться скопировать в большинстве sizeof(char*)-1 символов из student_name в указатель массива на по new_s->name.

  • Если student_name больше, адресат не будет нулем,

  • Если он короче, адресат будет дополнен нулевыми байтами Шифрование до заданного размера.

  • Здесь указатель адресата неинициализирован и информация о размере является фиктивной в любом случае: вы действительно хотите скопировать все символы в строке плюс нулевой терминатор, что и делает то, что делает strcpy. Но для этого вам нужно выделить достаточно памяти. Вы можете использовать:

    new_s->data = malloc(strlen(student_name) + 1); 
    strcpy(new_s->data, student_name); 
    

Функция Posix strdup() делает обе операции в одном вызове:

new_s->data = strdup(student_name); 
+0

Это правда, но я использовал пример, предоставленный bakedturtle. –

Смежные вопросы