На форуме запрещена публикация любого незаконного материала, нарушающего авторские права создателей, а также просьбы выложить это! МЫ поможем ВАМ найти бесплатную альтернативу! О публикации ключей, креков, пиратского ПО, игр, музыки, фильмов и т.д. - сообщать СЮДА!
Насколько я понял, прописал лишний include? в результате Visual Studio не может понять, какую функцию использовать.
Нет. По ошибке видно, что "отсутствуют экземпляры перегруженная функция "std::getline", соответствующие списку аргументов". Второй аргумент в функции std::getline не верный.
Вот мой работающий код (компилил под компилятором g++. Под студией возможно еще, что настройках проекта указано использовать UNICODE)
Код:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::string str;
std::ifstream f("file.txt");
if (!(f.is_open()))
{
std::cout << "ERROR: not file ";
}
else
{
while(!f.eof()) // чтении из файла
{
std::getline(f, str);
// тут делаю что-то ещё
}
}
return 0;
}
При использовании FILE.
Код:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <fstream>
int main()
{
FILE *file = _wfopen(L"file.txt", L"r");
if (!file)
{
std::cout << "ERROR: not file ";
}
else
{
while(!feof(file)) // чтении из файла
{
static char str[255];
fgets(str, 255, file);
// тут делаю что-то ещё
}
fclose(file); // закрываем файл
}
return 0;
}
Замечания:
Как я сказал раннее, все было откомпилировано под g++, поэтому в инклудах отсутствует "windows", но на работу программы это не скажется в этих моментах.
Использовал _wfopen за место _wfopen_s. В принципе большой разницы нет, так что при желании можете и заменить их. Делается это быстро
При использовании структуры FILE, читать напрямую в std::string не получится, поэтому я ее и удалил
Будут вопросы, задавай. Я рассказал здесь все в краткости
Помог, скажи спасибо
Этот пользователь сказал cпасибо за это полезное сообщение:
Вот что еще я хотел сказать. Ошибка вызвана тем, что ты забыл разыменовать std::string в функции std::getline(f,str); так как там нужно std::string, а ты используешь std::string*. Либо, как сделал это я, использовать класс std::string, за место std::string*.
В проекте включен unicode. Мне не принципиально, в какой кодировке делать, но всё-таки хотелось бы запустить в юникоде. Если причина только в этом, поменяю.
Второй вариант через fgets работает, но меня не устраивает заданная длина строки для чтения. длина может быть сильно разной (от 10 до 5000 символов). Можно сделать динамически?
Первый вариант не заработал. Я немного изменил код, добавив чтение в вектор (может и зря, но кажется мне так будет удобнее). Компилятор выдает ошибку:
Ошибка 1 error C2784: std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &): не удалось вывести аргумент шаблон для "std::basic_istream<_Elem,_Traits> &" из "std::wfstream"
Об этом надо сразу говорить. Я ведь не знал, что у вас включен юникод. По вашу кода я думал, что он не включен, т.к. вы используете std::string. std::string хранит только char. Для wchar_t нужно использовать std::wstring. А можно и по-другому: написать код, который будет работать и с юникодом, и без юникода (std::basic_string<TCHAR>).
Первая строка "#define _UNICODE" - это явное указание компилятору, что мы используем юникод. Вам это делать не надо, студия сама передает этот параметр компилятору. Я указал только для явности.
Т.к. у меня компилятор g++, поэтому функция имеет такой вид: "int PCList(const char *FileName, lines &ListBuf)", а именно "const char *". Стандартно библиотека не предоставляет открывать файловый поток через юникодовское имя. В студии, судя по msdn, предоставляет. Так что в студии можете заменить на "int PCList(const wchar_t *FileName, lines &ListBuf)". Завтра я защищаю отчет по практике, поэтому на работе меня не будет, но после завтра я буду на работе, а там стоит студия. Вот на работе и испробую код с такой функцией: "int PCList(const wchar_t *FileName, lines &ListBuf)" и выложу сюда.
Замечание по вашему коду: Если вы ничего не возвращаете, то зачем вы делаете ее функцией? Не лучше ли сделать ее процедурой?
Замечание по вашему коду: если вы ничего не меняете в переменной, то лучше делать ее константой. У вас переменная "wchar_t* FileName" не изменяется, поэтому ее НУЖНО объявлять так "const wchar_t* FileName".
Замечание по вашему коду: std::vector<std::string> - почему вы объявили ее так? а не лучше это вынести в еще один тип, так легче будет читать. Пример см. в моем коде тип "lines".
Использовал "using namespace std" чтобы меньше писать и код был менее громоздким. Ну здесь, это кому как нравится.
Не понял смысла "std::vector<std::string> ListBuf". Может быть вы имели в виду "std::vector<std::string> &ListBuf". То есть вы забыли указать, что мы берем адрес переменной, а не копируем всё в эту переменную. Я прав? Если что, это тема: "использование переменных, ссылок и адресов".
Не понял смысла "while (!std::getline(file_in, str))". Может быть вы имели в виду "while (!std::getline(file_in, str).eof())"? Функция "std::getline(file_in, str)" возвращает класс basic_istream. Но использовать "while (!std::getline(file_in, str).eof())" тоже плохо, иначе он не прочтет последнюю строку. Поэтому, чтобы прочитать все из файла, нужно использовать так, как я сделал это в примере.
Я подключил "algorithm", лишь только для вывода текста, чтобы проверить корректность использования юникода. Проверка прошла успешно. Можете ее и убрать, вместе с "printList" и "for_each".
Помог, скажи спасибо
Этот пользователь сказал cпасибо за это полезное сообщение:
Полностью код ещё не проверял, не было времени и возможности (выключают электричество на 2 часа в день). Постараюсь проверить в ближайшее время и сообщу результат.
Цитата:
Сообщение от L.E.O.
А можно и по-другому: написать код, который будет работать и с юникодом, и без юникода (std::basic_string<TCHAR>).
Немного о проекте. Это консольная утилита для копирования файлов из локальной сети (логи одной программы) в указанную папку и дальнейшего анализа. Все файлы имеют одинаковое имя и расположены в одинаковых каталогах. Список компьютеров в локальной сети, которые надо обходить, хранится в текстовом файле в каталоге программы (назовем его ip_list.txt). Программе в качестве параметра запуска будет передаваться путь до файла ip_list.txt. Также в качестве параметра запуска будет указываться результирующий каталог, в который будут копироваться логи из сети. Далее моя программа будет по-очереди обходить файлы в этом каталоге, анализировать их и результат работы выводить в другой текстовый файл. Все текстовые файлы на данный момент сделаны в кодировке cp1251. Мне казалось, что если моя программа будет скомпилирована в юникоде, то она будет универсальной, т.к. cp1251, по-сути, является подмножеством юникода. Или я сейчас чушь сморозил?
Цитата:
Сообщение от L.E.O.
Замечание по вашему коду: если вы ничего не меняете в переменной, то лучше делать ее константой. У вас переменная "wchar_t* FileName" не изменяется, поэтому ее НУЖНО объявлять так "const wchar_t* FileName".
Я планирую передавать имя файла для анализа через параметры запуска консольного приложения. Поэтому глобально (в рамках проекта) переменная FileName будет разной, но внутри функции int PCList(const char *FileName, lines &ListBuf) меняться не будет. Можно её в таком случае объявлять константной переменной?
Цитата:
Сообщение от L.E.O.
Замечание по вашему коду: Если вы ничего не возвращаете, то зачем вы делаете ее функцией? Не лучше ли сделать ее процедурой?
Возможно. Проект в самом начале, поэтому ещё не определился, как лучше. Может быть сделаю процедурой, а может буду возвращать значение typedef vector<su_string> lines;
Цитата:
Сообщение от L.E.O.
о есть вы забыли указать, что мы берем адрес переменной, а не копируем всё в эту переменную. Я прав?
Правы.
Цитата:
Сообщение от L.E.O.
Не понял смысла "while (!std::getline(file_in, str))".
Да, это моя невнимательность.
Добавлено через 13 минут L.E.O.,
Ещё вот что хотел спросить.
Не смог найти внятной документации по этой функции. Особенно интересно значение параметра ios_base::in. Почитав примеры программ на форумах, нашел, что параметр может быть также ios::in | ios::out | ios::trunc. Догадываюсь, что это означает чтение из потока, запись в поток и очистка потока перед записью в него, но уверенности нет.
написать код, который будет работать и с юникодом, и без юникода (std::basic_string<TCHAR>
Я имел в виду что код можно компилить и с настройками и с юникодом и с multibyte по умолчанию.
Цитата:
Сообщение от virtuOS
Мне казалось, что если моя программа будет скомпилирована в юникоде, то она будет универсальной
По идеи да.
Цитата:
Сообщение от virtuOS
cp1251, по-сути, является подмножеством юникода. Или я сейчас чушь сморозил?
Да, сморозил. cp1251 это ansi. unicode это UTF-7, UTF-8, UTF-16, UTF-32. UTF расшифровывается как uniocode text format.
Цитата:
Сообщение от virtuOS
Я планирую передавать имя файла для анализа через параметры запуска консольного приложения. Поэтому глобально (в рамках проекта) переменная FileName будет разной, но внутри функции int PCList(const char *FileName, lines &ListBuf) меняться не будет. Можно её в таком случае объявлять константной переменной?
Не можно, а нужно.
Цитата:
Сообщение от virtuOS
Не смог найти внятной документации по этой функции. Особенно интересно значение параметра ios_base::in. Почитав примеры программ на форумах, нашел, что параметр может быть также ios::in | ios::out | ios::trunc. Догадываюсь, что это означает чтение из потока, запись в поток и очистка потока перед записью в него, но уверенности нет.
Все верно. Можешь про параметры прочитать [Ссылки могут видеть только зарегистрированные пользователи. ]
Теперь проблемы с преобразованием типов данных.
Как передать в функцию CopyFileW(sPath, dPath, FALSE) строки из вектора, имеющие тип su_string? Как преобразовать wchar_t в TCHAR? У меня не получилось ни явное указание типа компилятору, ни через MultiByteToWideChar.
Всем привет. Долго не отвечал из-за написания и защиты отчета по практике.
Цитата:
Сообщение от virtuOS
Как передать в функцию CopyFileW(sPath, dPath, FALSE) строки из вектора, имеющие тип su_string?
su_string - это класс stl строки. У него есть метод c_str() возвращающий "const _TChar *", где _TChar - тип переданный в шаблон класса при его объявлении. В вашем случае будет так: CopyFileW(sPath.c_str(), dPath.c_str(), FALSE)
sPath.c_str() - вернет const wchar_t *, при настройках с UNICODE; и const char *, при настройках MultiByte.
Цитата:
Сообщение от virtuOS
Как преобразовать wchar_t в TCHAR?
Вы не понимаете что такое TCHAR. TCHAR это либо char, либо wchar_t. Здесь все зависит от параметров компиляции. В Студии эти параметры передаются автоматически, посредством настроек. Если в настройках включен параметр UNICODE, тогда TCHAR - это wchar_t, иначе это char.
Этот тип был создан только для быстрого перехода с UNICODE на ANSI и обратно.
PS:
Я быстро накинул код вашей задачи, только с поправкой. Задача стала такой:
Консольная утилита для копирования логов из одной папки в указанную папку. Все файлы имеют одинаковое имя (log.txt). Список каталогов, которые надо обходить, хранится в текстовом файле ip_list.txt. Программе в качестве параметра запуска будет передаваться 2 значения: путь до файла ip_list.txt; результирующий каталог, в который будут копироваться логи. Далее программа по-очереди обходить файлы в этих каталогах, и копирует их в другой текстовый файл.
Параметры передаются по стандартным правилам, а именно: если имя содержит пробел, то нужно ставить имя файла и пути в кавычки; путь лучше заканчивать без слеша. Если со слешом, то в таком виде (\\") разумеется без скобок.
Помог, скажи спасибо
Последний раз редактировалось L.E.O.; 26.04.2011 в 20:25..
Этот пользователь сказал cпасибо за это полезное сообщение:
Долго не отвечал из-за написания и защиты отчета по практике.
Надеюсь, защита прошла успешно.
Спасибо большое за код и потраченное время. Что-то безусловно возьму из вашего примера, но писать скорее всего буду самостоятельно. Только так придет понимание каждой строчки программы, а быть "копи-пастером" я не хочу. Хотя и говорят, что учиться лучше на чужих ошибках, но к программированию это скорее всего не относится. Только с опытом придет результат. Но в любом случае спасибо, думаю, ваш пример позволит избежать многих ошибок.