C++: strcpy и "нарушение прав доступа при записи"
UPD, коротко. В современных версиях Studio не забывайте указывать модификатор
const
дляchar *
, ибо неконстантные указатели теперь вне закона:const char *s = "Hello";
Если Вы, как и многие, обучались программировать на древней Сишной консоли, то Вам, как и мне, естественным кажется код вроде
char *s = "строка";
В хорошем учебнике, конечно, всегда оговорено, что это не копирование строки, а просто установка указателя на некоторую область памяти - фактический массив символов. Проблема в том, что в новых средах, например, в той же Visual Studio, "права" указателей сильно урезаны, так что область "строка"
, скорее всего, будет только read only, и писать в неё новые данные - потенциально опасное занятие.
Так, указанный выше подход приведёт к Runtime-ошибке нарушения прав доступа при использовании функции strcpy
для копирования в строку s
нового значения:
strcpy (s,"новая");
Кстати, "естественное"
char s[6]; strcpy (s,"строка");
тоже ошибочно - функция strcpy
скопирует строку вместе с нуль-терминатором, так что для строки из N
байт нужен буфер размерностью N+1
байт (конечно, если строки у нас - однобайтовые). Верным решением будет
char s[7]; strcpy (s,"строка");
Пример более-менее корректной программы на Studio с использованием char *
и strcpy
:
Вывести на экран показания часов.
Исходные данные – часы и минуты в формате целых чисел. Результат должен быть представлен в смешанной текстово-числовой форме с учетом падежных окончаний, например:
2 48 – 2 часа 48 минут ночи,
5 00 – 5 часов утра ровно,
12 00 – полдень,
12 23 – 12 часов 23 минуты дня,
13 12 – 1 час 13 минут дня,
21 33 – 9 часов 33 минуты вечера,
00 00 – полночь,
03 01 – 3 часа 1 минута ночи.
Использовать следующие границы частей суток:
5 час. <= утро < 12 час.,
12 < день < 18 час.,
18 <= вечер <= 23 час.,
0 час. < ночь < 5 час.
В случае ввода невозможных показаний часов выдать соответствующее сообщение, например:
24 03 – введены недопустимые данные.
Консольное приложение Visual C++ для решения задачи:
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> using namespace std; char *goodwordform(int k,char *w,char *o1,char *o2,char *o5) { char *r = new char [strlen(w)+max(strlen(o1),max(strlen(o2),strlen(o5)))+1]; strcpy (r,w); if ( (k%100>10 && k%100<20) || k%10>4 || k%10==0) r=strcat(r,o5); else if (k%10==1) r=strcat(r,o1); else r=strcat(r,o2); return r; } int main () { setlocale(LC_ALL, "rus"); int h,m; int timetags[4] = { 4, 11, 17, 23 }; char *timemessages[4] = { "ночи" ,"утра","дня","вечера"}; cout << "Введите часы и минуты: "; cin >> h >> m; if (h<0 || h>23 || m<0 || m>59) { cout << "Недопустимое время!"; cin.sync(); cin.get(); return 1; } int index=0; while (h>timetags[index]) index++; if (h>12) h%=12; if (m==0) { if (h==0) cout << "полночь"; else if (h==12) cout << "полдень"; else cout << h << " " << goodwordform(h,"час","","а","ов") << " " << timemessages[index] << " " << "ровно"; } else cout << h << " " << goodwordform(h,"час","","а","ов") << " " << m << " " << goodwordform(m,"минут","а","ы","") << " " << timemessages[index]; cin.sync(); cin.get(); return 0; }
11.09.2014, 14:07 [12276 просмотров]