Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.233.219.31] |
|
Сообщ.
#1
,
|
|
|
Всем хай! Сходу к делу!
Есть текстовый файл. Там по идее должны быть целые числа, разделенные, например пробелом или табуляцией. Если встречается не число, то обработку нужно прекращать. Написал прожку, которая прекрасно работает, если будут числа. Если встречается строка, то программа зацикливается. Подскажите, как быть то? const int N = 100; int main() { setlocale(LC_ALL, ""); char nameFile[N]; cout << "Введите название файла для обработки: "; cin.getline(nameFile, N - 1); fstream f; f.open(nameFile, ios::in); if (f.is_open() == false) cout << "Ошибка открытия файла!"; else { int x; //cin.exceptions(ifstream::failbit | ifstream::badbit); - не помогло while (f.eof() == false) { try { f >> x; } //catch (ifstream::failure e) catch(...) // не реагирует { cout << endl << endl << "Случилась страшная ошибка!\n\n"; } cout << x << '\t'; } } cout << endl << endl; f.close(); system("pause"); return 0; } |
Сообщ.
#2
,
|
|
|
Цитата FasterHarder @ catch(...) // не реагирует И не должен if (f >> x) { } else { } RTFM Добавлено Альтернативный вариант с исключениями http://en.cppreference.com/w/cpp/io/basic_ios/exceptions |
Сообщ.
#3
,
|
|
|
shm, спс, ясно, значит блок try-catch вообще тут не нужен, а это очень хАрошо...
|
Сообщ.
#4
,
|
|
|
Тут еще проблема возникла)
Есть текстовый файл, в котором "спрятан" двумерный массив. Могут быть пустые строки + любое количество пробелов и табуляций в любом месте. Типа нужно узнать, можно ли получить матрицу из этого файла. Очевидно, что кол-во элементов в каждой строке матрицы должно быть одинаковым. Такое достаточно просто реализовать в стиле С, используя strtok, но нужно все через потоки o/i/fstream(, которые плоховато знаю, т к мало их практикую! И я вот чегот не выкупаю логику. В принципе, нужно сначала получить кол-во элементов для 1-й строки, чтобы потом можно было сверять их кол-во с остальными. В примере выше было показано, как считать числа из файла. При этом пропускаются/игнорируются пробелы, табуляции и переход на новую строку. В ДАННОМ считывании это нужно учитывать. Вот какие методы в этом могут помочь, там их полно. Тупо я не знаю мат.часть этой обработки хорошо, т е какие методы применять, в каком порядке и пр. подскажите, а... |
Сообщ.
#5
,
|
|
|
Ну, тебе не надо учитывать разделители. Нужно лишь выделять новую строку. Чтение строки в массив – метод std::istream<>::getline(), чтение строки в std::string – функция std::getline(). Из массива ты можешь по старинке strtok()нуть, из std::string ты можешь создать опять-таки поток std::istringstream, вводить из которого тем же operator>>().
|
Сообщ.
#6
,
|
|
|
Qraizer, уже стало понятнее.
вот, что получилось: void CheckFile(char* pnameFile) { fstream f; f.open(pnameFile, ios::in); while (f.eof() == false) // пока не достигнут конец файла { string currentString; getline(f, currentString); // получили текущую строку из файла if (currentString.length == 0) // пустая строка, т е нет ни одного символа continue; // создаем поток из строки std::stringstream ss; ss << currentString; // записали строку в поток while (ss.eof() == false) // пока не дошли до конца текущей строки { int val; ss >> val; // читаем очередное целое число, пропуская пробелы и табуляции cout << val << '\t'; } cout << currentString << endl; } f.close(); } компиляция выдает одну ошибку... Но мне главное понять логику, т е в целом тут все на своем месте или вообще не так?? |
Сообщ.
#7
,
|
|
|
В целом верно. (Ошибка, по ходу, в 9-й строке: std::string::length() – это метод.)
Я бы чтение с контролем написал примерно так: std::ifstream inFile(/*...*/); std::string buf; std::vector<std::vector<int>> vv; // целевая матрица int row_size = -1; while (inFile.good()) { std::getline(inFile, buf); if (!(inFile.good() || inFile.eof() && !buf.empty())) continue; std::istringstream line(buf); std::vector<int> row((std::istream_iterator<int>(line)), std::istream_iterator<int>()); if (row_size == -1) row_size = row.size(); else if (row_size != row.size()) throw std::runtime_error("row `" + buf + "` is inconsistent to prev"); vv.emplace_back(std::move(row)); } |
Сообщ.
#8
,
|
|
|
Цитата Qraizer @ В целом верно. (Ошибка, по ходу, в 9-й строке: std::string::length() – это метод.) ты абсолютно прав! в общем как и всегда... Цитата Qraizer @ Я бы чтение с контролем написал примерно так: я бы тоже, если бы знал С++ на твоем уровне Ты прекрасно владеешь мат.частью (просто виртуозно) и имеешь колоссальнейшую вариативность в реализации. Цитата Qraizer @ и ещё можно соптимизировать чуток. Возможно, слишком сложно написано, можно упростить. нет-нет, нормально. Сложно только нубам, типа меня. В общем у меня все получилось "моим" способом. Огромное спс Qraizer за помощь! Скрытый текст P.S. в С++ нет ничего сверхсложного, но нужно знать на зубок мат.часть + постоянно практиковаться...)) |
Сообщ.
#9
,
|
|
|
Еще уточняющий вопрос есть по обработке файлов: используя потоки fstream читаем текстовый файл, в котором числа должны быть. Но вдруг встретилось не число, а например СЛОВО. В этом случае это проверка вернет 0:
if (f >> current) // если успешно прочитано число из текст.файла как получить значение, на котором сбойнуло?? Придется прокручивать файл в самое начало, потом считывать нужное кол-во раз норм.числа, и затем в стр.переменную считать ошибочное значение?? Или можно в разы проще и быстрее?? |
Сообщ.
#10
,
|
|
|
Позиция в файле при ошибке чтения не меняется. Можно просто читать дальше. Но есть нюанс, да: если поток находится в состоянии ошибки, её сначала нужно сбросить, иначе поток и дальше не будет ничего делать, а продолжать возвращать состояние ошибки. std::basic_ios<>::clear(), например.
|
Сообщ.
#11
,
|
|
|
Цитата Qraizer @ Позиция в файле при ошибке чтения не меняется. Можно просто читать дальше. Но есть нюанс, да: если поток находится в состоянии ошибки, её сначала нужно сбросить, иначе поток и дальше не будет ничего делать, а продолжать возвращать состояние ошибки. std::basic_ios<>::clear(), например. понятно, спс. я не знаю, это нюанс или я туплю, но есть такое, что, если читать файл так: f >> intVal; а потом "резко" перейти на ch = f.get() то он не может продолжать читать посимвольно. А вот если поставить f.clear() между этими чтениями, то он норм. переключается на посимвольное чтение после числового. Возможно я сильно туплю и нет такой проблемы в принципе) но мне показалось, что есть) Добавлено кажется, понял, как раз происходит сброс ошибки f.clear(), о чем ты писал выше... |