@ElinMyers

Как передавать строки в поле структуры Си?

Привет. У меня есть строка, просящая ввести слово, это слово сохраняется в переменную name.
char name[10];
scanf("%s", name);


Как правильно оформить структуру, а именно поле строки?
struct Node
{
        char *str; // Или char str           или char str[10]
        struct Node* next;
};


И как передать, то что сохранилось в name в поле объекта структуры?
Я делаю связный список;

Например, заполняю элемент списка:
struct Node* head = malloc(sizeof(struct Node));
head->str = name;

Но это не работает.
  • Вопрос задан
  • 1393 просмотра
Решения вопроса 1
CityCat4
@CityCat4
Внимание! Изменился адрес почты!
Гуглим односвязный список.

Кстати, зачем списку связность? Для поиска? Тогда лучше двусвязный, вперед и назад, правда заполнение становится сложнее.
И память брать не только для структуры, но и для поля данных. И чистить сразу, чтобы не вляпаться.
#define MAXLEN 1024 // Задаемся максимальной длиной строки
struct Node *head;

if ((head = calloc(sizeof(struct Node) + MAXLEN,1)) == NULL)
  puts("Cannot alloc memory");

head->str = head + sizeof(struct Node); // тут данные
strncpy(head->str¸ name, strlen(name));

Почему нельзя просто переадресовать name? Если оно из кучи, оно запросто будет переписано, лучше хранить отдельно. Тупо но надежно.

UPD: Немного поправил код - переставил неверно поставленную скобку в calloc()
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
zagayevskiy
@zagayevskiy
Android developer at Yandex
char name[10]; выделяется на стеке. После выхода из зоны видимости указатель становится невалидным, поэтому нельзя его писать в поле структуры, чтобы дальше где-то использовать. Можно выделить память также с помощью malloc, это будет нормально. Не забудь её очистить, когда структуру будешь очищать.
Ответ написан
Комментировать
@Vladunet
Просто мимо проходил...
как я понимаю ответ уже был получен но все же если разрешите вставлю свой пятак.
Для изучения языка использовать подход CityCat4 не очень то правильно так как наверняка не совсем понятно. для изучения списков у вас должна быть подобная структура:
  • объявление списка
  • функция добавления объекта\элемента в список
  • функция для создания объекта\элемента


например
typedef struct		s_list
{
	char			*content;
	struct s_list	*next;
	struct s_list	*prev; // если список 2-связный
}					t_list;

t_list	*lstnew(void const *content) // создаем елемент\объект
{
	t_list	*obj;

	obj = (t_list *)malloc(sizeof(t_list)); // выделяем память
	//(можно проверить если выделение не произощло то вернуть NULL)
	obj->content = //(копировать, дублировать данные из content)
	obj->next = NULL; // инитить указатель на следующий
	obj->prev = NULL; // инитить указатель на предыдущий если 2связный
	return (obj); // вернуть указатель на созданый елемент\объект
}

void	lstadd(t_list **lst, t_list *obj)
{
	if (obj)
		obj->next = *lst;
	*lst = obj;
	// только этот вариант не всем подходит так как условий есть много
	// например:
	// 	добавить в конец списка
	// 	добавить в начало списка
	// 	добавить по середине списка (и их вариации как в 2 связный или односвязный списки)
	// для каждого из них реализация модернизируется а потому и код другой
}

и как итог можно вызвать функцию следующим образом
{
	t_list	*list;
	char	*str
	//...
	list = NULL;
	//...
	lstadd(&list, lstnew("твоя строка или другой контент"));
}


таким образом ты точно не запутаешься в том что происходит и тебе не понадобится переходить в памяти таким образом как это показали ранее. хотя такой подход в чем то хорош.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы