Как решить конфликт данных между строкой и inFile.open - PullRequest
0 голосов
/ 01 октября 2010
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>

using namespace std;

**int main()
{
    double write();
    double read();
    string choice;

    while(1)
    {
      cout<<"Enter read to read a file and write to write a file.\n";
      cin>>choice;
      if (choice == "read")
        cout<< read();
      if (choice == "write")
        cout<< write();
    }
}

double read()
{    
    const int size = 60;
    ifstream inFile;
    char filename[size];
    cout<<"Enter the name of the file you want to read \n";
    cin.getline(filename, size);
    inFile.open(filename);**

    if(!inFile.is_open())
    {
      cout<<"could not open  "<<filename<<endl<<"program terminating";
      exit(EXIT_FAILURE);
    }

    double value;
    double sum = 0.0;
    int count = 0;
    inFile >> value;
    while(inFile.good()) 
    {
      cout<<value<<"\n";
      ++count;
      sum += value;
      inFile >> value;
    }

    if (inFile.eof())
      cout<<"End of file reached. \n";
    else if (inFile.fail())
      cout<<"Input Terminated by data mismatch.\n";
    else
      cout<<"input terminated for unknown reason";

    if (count == 0)
      cout<<"no data processed";
    else 
    {
      cout<<"Items read: "<<count<<endl;
      cout<<"Sum: "<<sum<<endl;
      cout<<"Average: "<<sum / count << endl;
    }
    inFile.close();
    return 0;
}

double write() 
{
    char type[81];
    char filename[81];

    cout<<"this program is more or less pointless, any text edtor on earth is better than this for writing"<<endl;
    cout<<"files; However This is the first step in learning how to create my file tranfer program."<<endl;
    cout<<"Enter the name of a file you want to create.\n";
    cin>>filename;
    ofstream outFile;
    outFile.open(filename);

    outFile<<fixed;
    outFile.precision(2);
    outFile.setf(ios_base::showpoint);
    while(!cin.fail()){
         cin.getline(type,81);
         outFile<<type<<endl;
    }

    outFile.close();
}

Проблема заключается в том, что когда я набираю «read», программа делает то, что должна, пока не доберется до cin >> filename;в этот момент я думаю, что это присваивает значение выбора имени файла, потому что программа пропускает if (! inFile.is_open ()) {после того, как я ввожу «read». (функция записи моей программы работает нормально.1003 * Может кто-нибудь сказать мне, как решить эту проблему или каким-либо другим способом для компьютера выбрать погоду для выбора функций чтения или записи на основе ввода текста.

Я новичок в C ++, поэтому буду признателенОтвет прост, спасибо.

PS Я, м, на Ubuntu, если это имеет значение.

Ответы [ 4 ]

0 голосов
/ 01 октября 2010

Спасибо всем; Я нашел свой ответ с помощью Brent Nash'а, поместив этот заголовок вверху исходного файла;

(#) включают в себя

и поставив этот код после моего выбора cin >>;

cin.ignore (СТД :: numeric_limits :: макс (), '\ п');

Я посмотрю другие ответы, хотя;

0 голосов
/ 01 октября 2010

Проблема в том, что вы не читаете "последовательность EOL" (AKA '\ n') из входного потока:

cin>>choice;

Это читает одно слово. Но не читает символ '\ n' из ввода.
Так что читайте следующее:

cin.getline(filename, size);

Просто читает символ '\ n', который вы оставили в потоке после последнего чтения (а не следующую ожидаемую строку).

При чтении ввода от пользователя.
Я всегда предпочитаю читать строку ввода и затем обрабатывать ее внутренне.

std::string  command;
std::getline(std::cin, command); // reads the whole line (but discards the '\n')

if (command == "read") { /* Stuff */ }

Тогда ваш код для получения имени файла должен работать:

std::string  filename;
std::getline(std::cin, filename);

std::ifstream(filename.c_str());

Все сделано.

Пока мы здесь: Это разумно, так как вы избегаете обычной проблемы с зацикливанием потока.
Но есть лучшее решение (лучше я имею в виду более компактный):

inFile >> value;
while(inFile.good()) 
{
  cout<<value<<"\n";
  ++count;
  sum += value;
  inFile >> value;
}

Попробуйте это:

while(inFile >> value) 
{
  cout<<value<<"\n";
  ++count;
  sum += value;
}

Совет 2: предпочитайте использовать std :: string вместо буфера char фиксированного размера.

0 голосов
/ 01 октября 2010

Вам просто нужно согласовать использование "cin >>" и "getline", когда вы хотите читать в строке. Их поведение немного отличается.

Помните, что при использовании cin для чтения с консоли каждое нажатие пользователем клавиши попадает в буфер cin , включая \ n для клавиши возврата .

Таким образом, когда ваш пользователь вводит слово «read» и нажимает «return», чтобы ввести свой выбор, содержимое cin в этот момент:

чтения \ п

Тогда вы делаете:

string choice;
cin >> choice;

Проблема в том, что оператор >> определен для чтения до тех пор, пока не достигнет пробела, поэтому он будет читать в режиме "чтение", но он оставит \ n все еще сидеть в буфере cin.

Итак, после вашего заявления cin >> choice содержимое cin будет:

\ п

Тогда вы идете, чтобы сделать это:

char filename[size];
cout<<"Enter the name of the file you want to read \n";
cin.getline(filename, size);

Проблема здесь в том, что оператор >> определен для чтения до пробела (например, \ n), но getline определен для чтения до тех пор, пока не достигнет \ n, и будет читать все до тех пор, пока он не увидит \ n , а затем прочитает \ n и отбросит его.

Хорошо, ваша проблема в том, что когда вы переходите к своему выражению cin.getline(filename,size), в буфере cin все еще остается символ \ n, поэтому getline сразу видит \ n и отбрасывает его, сохраняя пустую строку в filename.


У вас есть несколько вариантов здесь.

Если вы указали имя файла в виде строки и изменили имя файла на:

cin >> filename;

Он будет работать правильно, потому что оператор >> также игнорирует начальные пробелы.

Вы также можете изменить начальное чтение choice, чтобы оно было таким (используя getline из заголовка строки здесь):

string choice;
getline(cin,choice);

И это будет работать, потому что getline не оставит беспризорный символ \ n, сидящий в буфере cin.

Вы можете использовать функцию cin.ignore для очистки буфера cin. Вы не хотите просто слепо использовать ignore, если вы не знаете, что делаете, но в этом случае мы знаем, что вы оставляете паразит \ n на cin, поэтому, если вы хотите получить избавиться от этого, вы можете сделать это:

#include <limits>

string choice;
cin >> choice;
cin.ignore(std::numeric_limits<int>::max(),'\n');

Этот оператор ignore, по сути, стирает оставшиеся данные в cin, говоря: «отбросьте следующие символы INT_MAX или все, вплоть до \ n.» *

Надеюсь, что прояснит, что происходит для вас.

0 голосов
/ 01 октября 2010

Вы можете использовать cin.ignore (INT_MAX); очистить буфер ввода перед cin.getline (имя файла, размер);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...