Сохранить файл в местоположении и с именем, определенными пользователем, введенными в C

#c #string #file #text #user-input

#c #строка #файл #текст #пользовательский ввод

Вопрос:

У меня возникли некоторые проблемы с сохранением текстового файла, созданного в окне консоли, в пользовательское местоположение, определенное пользовательским вводом. Я хочу, чтобы он принял строку, filepath которая будет местоположением сохранения, и объединил ее со строкой, filename которая будет именем текстового файла, выбранного пользователем. Например, так C:usersbobbertdesktopc .txt затем я хочу иметь третью строку, которая была бы фактическим текстом для записи в c .txt файл. Вот мой код:

 cout<<"Please enter a name for your file: "<<endl;
cin>>filename;

cout<<"Please enter a directory to save your file in: "<<endl;
cin>>filepath;

//user is now typing data into the text file
cin>>data;
//the data is now being grabbed and put into the "Data" string

FILE * pFile;
pFile = fopen (filepath.c_str()   filename.c_str(),"a");

//trying to combine the users selected directory   the selected filename here

if (pFile!=NULL)
{
    fputs(data.c_str(), pFile);
    //here i am trying to take the data of the .txt file
    //string and put it into the new file
}

fclose (pFile);
  

Спасибо, что нашли время прочитать это! 🙂

Комментарии:

1. Для дальнейшего использования было бы лучше, если бы вы действительно описали, что не так. Вы никогда не задавали здесь вопрос.

Ответ №1:

filepath.c_str() filename.c_str() строки не объединяются, поскольку они являются указателями на массивы символов, а не на объекты C std::string . Вы просто [пытаетесь] выполнить арифметику над указателями.

Попробуйте:

 std::string filename, filepath, data;

cout << "Please enter a name for your file: " << endl;
cin >> filename;

cout << "Please enter a directory to save your file in: " << endl;
cin >> filepath;

//user is now typing data into the text file
cin >> data;

//the data is now being grabbed and put into the "Data" string
ofstream fs((filepath   "/"   filename).c_str(), ios_base::app);

//trying to combine the users selected directory   the selected filename here
if (fs)
   fs << data;
  

Я заменил ваше использование C-style fopen на объект stream C , исправил вашу проблему со строками и добавил обратную косую черту между filepath и filename (для безопасности на случай, если пользователь ее не напишет).

Обратите внимание, что вам все равно нужно выполнить .c_str() обработку std::string результата конкатенации при передаче готового пути в ofstream конструктор, потому что iostreams были разработаны до библиотеки strings. Это просто отвратительный C -изм.

Комментарии:

1. 1, но на самом деле он не выполняет арифметику указателей, поскольку указатели не могут быть суммированы (эта строка, вероятно, вызвала бы ошибку компиляции).

2. @Matteo: Попытка * 🙂 То, что он не может, является, конечно, источником его проблем, и если бы он мог, то проблемы было бы просто немного сложнее обнаружить и отладить. Кстати, мы обычно говорим «строка», а не «row».

Ответ №2:

В истинном духе c

 #include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string filename, filepath, data;

    std::cout << "Please enter a name for your file: " << std::endl;
    std::cin >> filename;

    std::cout <<" Please enter a directory to save your file in: " << std::endl;
    std::cin >> filepath;

    std::ofstream file((filepath   "/"   filename).c_str());

    //std input is being copied to the file
    file << std::cin.rdbuf();
    file << std::flush;
    file.close();

    return 0;
}
  

В духе C объединить путь

 {
    char* fspec;
    if (-1 == asprintf(amp;fspec, "%s/%s", filepath.c_str(), filename.c_str()))
        { perror("asprintf"); return 255; }
    std::cout << fspec << std::endl;
    free(fspec);
}
  

Мне было не совсем ясно, как вы потребуете, чтобы входные данные обрабатывались;
При желании вы можете прочитать его в буфер памяти, используя потоки строк многими способами, например
без потери пробелов:

 std::stringstream ss;
ss << std::cin.rdbuf();

// OR
std::copy(std::istreambuf_iterator<char>(std::cin) ,
        std::istreambuf_iterator<char>(),
        std::streambuf_iterator<char>(ss));
  

…. и несколько альтернатив, которые удаляют пробелы:

 std::copy(std::istream_iterator<std::string>(std:: cin),
        std::istream_iterator<std::string>(),
        std::stream_iterator<std::string>(ss));

bool my_isspace(char c) { return std::isspace(c); } // in namespace scope
std::remove_copy_if(std::istreambuf_iterator<char> (std::cin),
        std::istreambuf_iterator<char>(),
        std::streambuf_iterator<char>(ss), my_isspace);
  

Комментарии:

1. Эй, это здорово! Именно то, что я искал. Однако есть одна проблема: каждый раз первое слово вырезается. Например, я набираю «Привет, Салли» в консоли, в текстовом файле отображается «Салли». Также я использовал ctrl C для выхода out, потому что ввод не сработал (что хорошо, потому что мне нужно иметь возможность написать более одной строки) есть ли правильный способ выхода? Спасибо!

2. В моем коде нет слов, смотрите здесь . Я почти уверен, что вы оставили инструкцию stray cin>>data из своего старого кода? Компьютеры имеют привычку подчиняться вашим командам 🙂 Правильный способ выхода — EOF (Ctrl-D в UNIX / linux, Ctrl-Z в Windows)

3. Конечно, я забыл удалить cin>>данные из моего старого кода. Теперь это работает, за исключением Ctrl-Z. Для меня он завершается только при нажатии Ctrl-C. Работает ли у вас Ctrl-z? Я использую 32-разрядную версию Windows 7.

4. Хотя я уверен, что изучение того, как управлять консольной клавиатурой Windows, не является целью вашего курса, я только что запустил старую виртуальную машину Windows, и вот: Ctrl-Z работает. Попробуйте это с copy con: nul: . Кстати, вы можете попробовать нажать клавишу F6, чтобы вставить Ctrl-Z, если ваша клавиатура работает

Ответ №3:

Завершает ли пользователь вводимую строку обратной косой чертой? Если нет, то ваш путь неверен.