#c
#c
Вопрос:
Я только что нашел кое-что, чего не могу понять. У меня есть функция, которую я хочу не только запустить в main (), но и использовать ее в другой функции (для редактирования файла), и я не хочу создавать дополнительные глобальные переменные.
int fileOut(bool = 1, char filename[] = 0); //... int fileOut(bool output, char filename[15]){ cin gt;gt; filename; // and if I do so, Ill got the error like this: // Exception thrown: Write access violation. _Str was 0x1110112. cout lt;lt; filename; return 0; }
Су, есть ли решение, как это исправить и сделать возможным изменение имени файла?
Комментарии:
1. используйте строковый объект
2. Какова цель
fileOut()
этого ?3.
cin gt;gt; filename
создает хороший вектор атаки переполнения буфера.4. @FredLarson я собираюсь прочитать файл и вывести результат в таблицу
5. @SaMartinell:
fileOut()
собираетесь ли вы все это делать?
Ответ №1:
В параметре функции char filename[15]
компилятор фактически обрабатывает его как простой char *filename
, который вы используете по умолчанию 0
, он же NULL
/ nullptr
. Таким образом, если вызывающий абонент не предоставит буфер для filename
, он не укажет ничего полезного, поэтому вы не сможете записать в него данные, отсюда и сбой.
В этой ситуации вы можете использовать локальную переменную для записи, например:
int fileOut(bool output, char filename[15]){ char buffer[15] = {}; if (!filename) filename = buffer; cin gt;gt; filename; cout lt;lt; filename; return 0; }
Просто будьте осторожны с переполнением буфера, так как пользователь может ввести более 15 символов! Вы можете использовать cin.get()
, чтобы смягчить это:
cin.get(filename, 15);
Хотя, вам действительно следует использовать std::string
вместо char[]
, например:
int fileOut(bool = 1, std::string filename = ""); //... int fileOut(bool output, std::string filename){ cin gt;gt; filename; cout lt;lt; filename; return 0; }
В любом случае, какой смысл позволять пользователю передавать строку ввода, если функция просто собирается ее перезаписать? Если функция всегда запрашивает пользователя, то просто используйте локальную переменную вместо параметра:
int fileOut(bool = 1); //... int fileOut(bool output){ char filename[15] = {}; cin.get(filename, 15); cout lt;lt; filename; return 0; }
Или:
int fileOut(bool = 1); //... int fileOut(bool output){ std::string filename; cin gt;gt; filename; cout lt;lt; filename; return 0; }
В противном случае, если вы хотите, чтобы вызывающий абонент мог указать имя файла, а затем запросить пользователя, если имя файла не указано, попробуйте вместо этого что-то более похожее:
int fileOut(bool = 1, char filename[15] = 0); //... int fileOut(bool output, char filename[15]){ char buffer[15] = {}; if (!filename) filename = buffer; if (*filename == 0) cin.get(filename, 15); cout lt;lt; filename; return 0; }
Или:
int fileOut(bool = 1, std::string filename = ""); //... int fileOut(bool output, std::string filename){ if (filename.empty()) cin gt;gt; filename; cout lt;lt; filename; return 0; }