2013-07-06 2 views
2

Итак, я сейчас пишу редактор строк в качестве учебного проекта по вводу-выводу, записи файлов и тому подобного. Он написан на C++, и в настоящее время я пытаюсь записать файл по выбору пользователя. У меня есть аргументы CLI, но я в настоящее время не знаю, как реализовать программный способ указания файла для записи.C++: cin >> * char

char *filename; 
if (argc >= 2){ 
     filename = argv[1]; 
} else{ 
     cout << "file>"; 
     cin >> filename; 
     cin.ignore(); 
} 

Это прекрасно работает, когда я использую аргументы командной строки; однако, когда я этого не делаю, как только я запускаю программу, это происходит с ошибками сегментации. Место, где я использую фактическое имя файла, находится в команде сохранения:

void save(char filename[], int textlen, string file[]){ 
     ofstream out(filename); 
     out << filestring(textlen, file); 
     out.close(); 
} 

Которая также работает отлично. Есть ли способ помочь мне? Полный исходный код для обзора: https://github.com/GBGamer/SLED

+1

Используйте [ 'станд :: string'] (http://en.cppreference.com/w/cpp/string/basic_string) и [читать это] (Http: //chris-sharpe.blogspot. co.uk/2013/05/reading-input-with-stdgetline.html) (self plug). – BoBTFish

+0

Проблема в том, что instream, если я правильно помню, не может использовать строки как входные данные. Есть ли у вас альтернативы, которые используют строки? – ubsan

+1

строка имеет функцию преобразования 'c_str()', которая возвращает тип const char *. – suspectus

ответ

2

Проблема в том, что char* filename - это всего лишь указатель на некоторую память, содержащую символы. Он не владеет самой памятью. Когда вы используете аргумент командной строки, программа обрабатывает эту строку где-то, и вы получаете указатель на нее. Когда вы пытаетесь читать с использованием cin >> filename, на самом деле нет места для хранения прочитанных данных.

Решение: Заменить char* filename на std::string filename#include <string>).

Затем, чтобы открыть выходной файл, вам понадобится строка c-стиля (нулевой конец char). std::string имеет функцию для этого. Вы бы написать

std::ofstream out(filename.c_str()); 
          ^^^^^ 

Или, на самом деле, если вы можете использовать свежий компилятор с C++ 11 функций, вам не нужно даже использовать c_str(). Новый std::ofstream constructor был добавлен, чтобы принять std::string.

+0

Но как насчет использования потока? Есть ли альтернатива, которая позволяет использовать строки? РЕДАКТОР: Ничего, увидишь подозрительный. – ubsan

+0

Большое вам спасибо! Он работает отлично. – ubsan

0

Ваши filename переменная указывает на argv[1], когда обеспечивается аргумент командной строки, он не нуждается в памяти, чтобы быть выделены, но при переходе в else блоке, вы не выделили память filename. Его просто указатель.

Используйте malloc, чтобы присвоить filename некоторую память, а затем взять пользовательский ввод.

filename = (char *)malloc(sizeof(char)*(FILE_NAME_LENGTH+1)) 
+0

Whoa, whoa, whoa! Шутки в сторону? Вы считаете, что лучшим решением для тех, кто только начал изучать ввод данных, является управление ручной памятью с помощью 'malloc'? – BoBTFish

+0

Я думаю, что кто-то учит C перед использованием функций пространства имен std. Я изучил malloc задолго до использования std :: string и такой вещи. Если кто-то получает ошибку сегментации, вы не можете избежать объяснения памяти, если нужно объяснить причину. И просто распределение памяти на какую-то переменную указателя не является мамом в ручном управлении памятью. –

+0

Вот как вы должны научиться писать 'std :: string', прежде чем научиться его использовать. И хотя я согласен с тем, что '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'И ваш ответ (и не принимайте это лично, я имею в виду что-то достаточно короткое, чтобы быть ответом SO) нигде не является достаточно подробным, чтобы что-то делать, но вызывает путаницу в отношении этих тем. – BoBTFish

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