Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
1 / 3 / 4
Регистрация: 02.07.2011
Сообщений: 90
1

Запись указателя на строку в массив

19.08.2011, 15:50. Показов 2276. Ответов 22
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет! Вот у меня проблемка появилась, не знаю, что делать. Помогите пожалуйста!
Есть структура
C++
1
2
3
4
5
struct golf
{
       char fullname[Len];
       int handicap;
};
и прототип функции
C++
1
void setgolf(golf & g, char *name, int hc);
этой функции надо передать имя структуры, полное имя игрока в гольф и его гандикап(handicap)<- не знаю, что это такое

Вот вызов функции
C++
1
setgolf(ann, "Ann Birdfreee", 24);
А вот и сам функция
C++
1
2
3
4
5
void setgolf (golf & g, char *name, int hc)
{
     g.fullname = name;
     g.handicap = hc;
}
проблемма в том, что name - указатель на char, а g.fullname это массив и компиль не даёт
их приравнять, пишет: incompatible types in assignment of `char*' to `char[40]' . Как решить эту проблемму?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.08.2011, 15:50
Ответы с готовыми решениями:

Возвращение неконстантного указателя из константного указателя на строку
Не могу до конца понять один момент. Допустим, у нас есть функция searchSymbol, которая принимает...

Запись в массив чисел написанных в строку через запятую
Реализовал программу для подсчета доходов расходов на windows forms. Данные(название категории и...

Проблема с описанием указателя на запись в процедуре
Здравствуйте. Прошу Вас: помогите, пожалуйста, найти ошибку. Это быстро! В общем, у меня в...

Возвращение указателя на соответствующую строку
Доброго времени суток. Есть задача: по номеру дня недели вывести его название Есть код: #include...

22
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
19.08.2011, 15:53 2
C++
1
2
3
4
5
6
7
#include<string.h>
 
void setgolf (golf & g, char *name, int hc)
{
     strcpy(g.fullname, name);
     g.handicap = hc;
}
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.08.2011, 15:54 3
Используй strcpy, Люк!
2
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
19.08.2011, 17:58 4
Можно еще использовать объект типа string.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <string>
#include <iostream>
 
using  namespace std;
 
struct golf
{
       string fullname;
       int handicap;
};
 
void setgolf (golf &g, string name, int hc)
{
     g.fullname = name;
     g.handicap = hc;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    golf ann;   
 
  setgolf(ann, "Ann Birdfreee", 24);
 
  cout << ann.fullname << endl;
  cout <<ann.handicap << endl;
 
    system("pause");
    return 0;
}
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.08.2011, 18:00 5
germeticus, всё же я полагаю, что человек на чистом С пишет, так что...
0
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
19.08.2011, 18:34 6
Цитата Сообщение от silent_1991 Посмотреть сообщение
germeticus, всё же я полагаю, что человек на чистом С пишет, так что...
Если чистый С, то тогда уж так:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include"string.h"
#include"stdio.h"
#include"stdlib.h"
 
#define MAX 100
 
struct golf
{
       char fullname[MAX];
       int handicap;
};
 
void setgolf (golf *g, char* name, int hc)
{
     strcpy(g->fullname, name);
     g->handicap = hc;
}
 
int main()
{
    golf ann;   
 
  setgolf(&ann, "Ann Birdfreee", 24);
 
  printf("%s\n",ann.fullname);
  printf("%d\n",ann.handicap);
 
    system("pause");
    return 0;
}
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
19.08.2011, 20:53 7
Цитата Сообщение от germeticus Посмотреть сообщение
Если чистый С, то тогда уж так...
Если чистый Си, то действительно так и только так
0
Заблокирован
19.08.2011, 21:21 8
Здесь, как обычно, вам не правильно подсказали! Вы не можете использовать strcpy, так как у вас может быть выход за границу вашего массива, определенного в структуре.

Поэтому правильно будет использовать функцию strncpy

Например,

C++
1
2
strncpy( g->fullname, name, Len );
g->fullname[Len - 1] = '\0';
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
19.08.2011, 21:26 9
Цитата Сообщение от Сыроежка Посмотреть сообщение
Здесь, как обычно, вам не правильно подсказали! Вы не можете использовать strcpy, так как у вас может быть выход за границу вашего массива, определенного в структуре.
Ну уж этот детский сад был всем очевиден, просто корректно промолчали
Сыроежка, учебные программы не должны быть педантичными, начинающий программист может совсем ничего не понять
0
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
19.08.2011, 21:47 10
Цитата Сообщение от Сыроежка Посмотреть сообщение
Здесь, как обычно, вам не правильно подсказали! Вы не можете использовать strcpy, так как у вас может быть выход за границу вашего массива, определенного в структуре.

Поэтому правильно будет использовать функцию strncpy

Например,

C++
1
2
strncpy( g->fullname, name, Len );
g->fullname[Len - 1] = '\0';

Если быть все же педантичным, то такой код будет побезопасней
C
1
2
strncpy(g->fullname, name,sizeof(g->fullname) - 1);
     g->fullname[sizeof(g->fullname) - 1] = '\0';
Ну и конечно обработать исключение, когда длина name больше fullname.
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
19.08.2011, 21:53 11
Да и такой вариант не больно уж подойдет. А как пользователь узнает, что строки обрезанными вышли, поэтому не стоит все усложнять
0
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
19.08.2011, 22:01 12
Я потом написал, про обработку исключения.
0
848 / 190 / 18
Регистрация: 01.08.2011
Сообщений: 505
19.08.2011, 22:09 13
Цитата Сообщение от germeticus Посмотреть сообщение
Я потом написал, про обработку исключения.
Ах да, спасибо
0
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
19.08.2011, 22:28 14
А вот и обработка:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int setgolf (golf *g, char* name, int hc)
{
    if (sizeof(g->fullname) <= strlen(name))
    {
        printf("The length of Name is too big\n");
        return 1;
    }
     strncpy(g->fullname, name,sizeof(g->fullname) - 1);
     g->fullname[sizeof(g->fullname) - 1] = '\0';
     g->handicap = hc;
 
     return 0;
}
 
int main()
{
    golf ann;   
 
     if( !setgolf(&ann, "aaaaaaaaaaaaaa", 24))
     {
      printf("%s\n",ann.fullname);
      printf("%d\n",ann.handicap);
     }
 
    system("pause");
    return 0;
}
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
20.08.2011, 00:57 15
Цитата Сообщение от germeticus Посмотреть сообщение
Если быть все же педантичным, то такой код будет побезопасней
Чем это он более безопасный, интересно знать.
Цитата Сообщение от germeticus Посмотреть сообщение
Ну и конечно обработать исключение, когда длина name больше fullname.
Исключение? В каком смысле исключение?
0
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
20.08.2011, 01:19 16
Исключение - проблема, которая может возникнуть при работе программы и приведет к невозможности (бессмысленности) дальнейшей отработки программой её базового алгоритма.
Сперто из Вики.

В данном случае этот термин вполне применим.

А код более безопасен, тем, что исключение никак не может возникнуть в рамках этих двух строчек. В предыдущем случае, теоретически могла возникнуть какая-нибудь ошибка вне рамок этих строк, влияющая на их работу.

Как-то так, благодарен за въедливые вопросы)))))
Если не прав поправьте)
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
20.08.2011, 01:28 17
Ну ладно, чёрт с ними с исключениями Считать ли данную ситуацию исключением или нет, зависит от разных обстоятельств. Пусть исключения.

Итак, речь о том, что код
C
1
2
strncpy(g->fullname, name,sizeof(g->fullname) - 1);
g->fullname[sizeof(g->fullname) - 1] = '\0';
якобы более безопасен, чем
C
1
2
strncpy( g->fullname, name, Len );
g->fullname[Len - 1] = '\0';
Вот мне и стало интересно, чем же он более безопасен, и что за ошибки могут повлиять на работу второго кода (не влияя на первый).
0
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
20.08.2011, 01:45 18
Цитата Сообщение от grizlik78 Посмотреть сообщение
Вот мне и стало интересно, чем же он более безопасен, и что за ошибки могут повлиять на работу второго кода (не влияя на первый).
уххх)))
1. Мы могли бы перепутать названия. Например массив задавать fullname[Lan], а у нас еще где есть переменная или константа Len. Все бы прекрасно откомпилировалось бы, а вот ошибку бы замучились искать.
2. Константа Len могла бы быть задана не как константа, со всеми вытекающими последствиями.
3. Может возникнуть конфликт переменных вообще говоря.

Примерно так. То есть, в случае каких-то ляпов в других местах программы, эти две строчки более устойчивы.

Еще раз спасибо)))
1
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
20.08.2011, 02:11 19
Ну перепутать-то можно что угодно и где угодно, и ничего от этого не спасает, как показывает практика.
От конфликта имён и "перепутываний" лучше помогают более осмысленные и многословные идентификаторы, в неком выдержанном стиле.
А вот в устойчивости я всё равно не уверен. Массив может быть заменён динамическим, тогда sizeof() будет давать размер указателя.
Тип элементов массива может измениться с char на wchar_t, к примеру, тогда заменив strncpy на wcsncpy про sizeof() опять же можно и подзабыть. И хотя переполнения в данном случае не произойдёт, но всё-равно, приятного мало.
Дело вкуса, короче.

Добавлено через 9 минут
Цитата Сообщение от grizlik78 Посмотреть сообщение
И хотя переполнения в данном случае не произойдёт
А, нет, наврал. Как раз в данном случае оно вполне возможно.
1
27 / 27 / 1
Регистрация: 21.06.2011
Сообщений: 82
20.08.2011, 02:14 20
Да, вы правы, код не переносим. Но мы про переносимость и не говорили) Надо еще делить на размер элемента.
0
20.08.2011, 02:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.08.2011, 02:14
Помогаю со студенческими работами здесь

Возврат указателя на строку из фукнции
Снова я пришел к вам со строками. Читаю &quot;Как программировать на С++&quot; и там везде пишут про...

Передача указателя на строку в функцию
Нужно написать функцию, которая бы удаляла из строки &quot;все вхождения заданного символа в эту...

Вернуть строку в качестве указателя
Как добавлять элементы в строку вида char* string = &quot;blablabla&quot;; Либо как вернуть массив символов...

Не выводит строку из-за нулевого указателя
Здравствуйте, почему не выводит даже значение указателя b, когда я в cout добавляю указатель a (Без...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru