SamForum.org  
SamLab.ws
Заблокированные пользователи

Вернуться   SamForum.org > Программирование > С
Важная информация

Ответ
 
Опции темы Опции просмотра
Чтение строк из файла
Старый Добавлено: 15.04.2011, 13:40
  (#1)
virtuOS
Модератор
Модератор
 
Аватар для virtuOS

По умолчанию Чтение строк из файла

Есть текстовый файл с набором строк. надо эти строки прочитать для дальнейшего разбора и анализа. Пишу примерно так (лишнее убрал):
Код:
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <fstream>

int _tmain(int argc, _TCHAR* argv[])
{
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;
}
В результате ошибки:
  • error C2079: "f" использует неопределенный class "std::basic_ifstream<_Elem,_Traits>"
  • IntelliSense: отсутствуют экземпляры перегруженная функция "std::getline", соответствующие списку аргументов
Насколько я понял, прописал лишний include? в результате Visual Studio не может понять, какую функцию использовать.


Или, может, есть другой способ читать из файла строки? Писать в цикле проверку каждого символа и сравнивать с символом конца строки не хочется.


PS.
Первоначально планировал файл открывать другим способом:
Код:
errno_t err;
FILE *file;
err = _wfopen_s(&file, FileName, L"r");
но как потом читать сразу строки из файла *file также не понял.


"Умом Россию не понять, аршином общим не измерить: у ней особенная стать - в Россию можно только верить."©
Волхвы не боятся могучих владык, а княжеский дар им не нужен; правдив и свободен их вещий язык и с волей небесною дружен. Грядущие годы таятся во мгле; но вижу твой жребий на светлом челе. ©

Последний раз редактировалось virtuOS; 15.04.2011 в 14:40..
virtuOS вне форума Отправить личное сообщение для virtuOS
Вверх
Ответить с цитированием
Старый Добавлено: 15.04.2011, 18:18
  (#2)
L.E.O.
Пользователь
Пользователь
 
Аватар для L.E.O.

По умолчанию

Цитата:
Сообщение от virtuOS Посмотреть сообщение
Насколько я понял, прописал лишний 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;
}
Замечания:
  1. Как я сказал раннее, все было откомпилировано под g++, поэтому в инклудах отсутствует "windows", но на работу программы это не скажется в этих моментах.
  2. Использовал _wfopen за место _wfopen_s. В принципе большой разницы нет, так что при желании можете и заменить их. Делается это быстро
  3. При использовании структуры FILE, читать напрямую в std::string не получится, поэтому я ее и удалил
  4. Будут вопросы, задавай. Я рассказал здесь все в краткости


Помог, скажи спасибо
L.E.O. вне форума Отправить личное сообщение для L.E.O.
Вверх
Ответить с цитированием
Этот пользователь сказал cпасибо за это полезное сообщение:
virtuOS (18.04.2011)
Старый Добавлено: 18.04.2011, 15:06
  (#3)
L.E.O.
Пользователь
Пользователь
 
Аватар для L.E.O.

По умолчанию

Вот что еще я хотел сказать. Ошибка вызвана тем, что ты забыл разыменовать std::string в функции std::getline(f,str); так как там нужно std::string, а ты используешь std::string*. Либо, как сделал это я, использовать класс std::string, за место std::string*.

С Уважением, L.E.O.


Помог, скажи спасибо
L.E.O. вне форума Отправить личное сообщение для L.E.O.
Вверх
Ответить с цитированием
Старый Добавлено: 18.04.2011, 19:05
  (#4)
virtuOS
Модератор
Модератор
 
Аватар для virtuOS

По умолчанию

В проекте включен unicode. Мне не принципиально, в какой кодировке делать, но всё-таки хотелось бы запустить в юникоде. Если причина только в этом, поменяю.

Второй вариант через fgets работает, но меня не устраивает заданная длина строки для чтения. длина может быть сильно разной (от 10 до 5000 символов). Можно сделать динамически?

Первый вариант не заработал. Я немного изменил код, добавив чтение в вектор (может и зря, но кажется мне так будет удобнее). Компилятор выдает ошибку:
Код:
#include "stdafx.h"

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
//#include <iostream>
#include <string>
//#include <fstream>
//#include <conio.h>
#include <vector>

int PCList (wchar_t* FileName, std::vector<std::string> ListBuf)
{std::wfstream file_in(FileName,std::ios_base::in);
std::string str;
	std::vector<std::string> file_buf;

	while (!std::getline(file_in, str))
	{
		ListBuf.push_back(str);
	}
	file_in.close();
   return 0;
}
Ошибка 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"

Ошибка 3 error C2782: std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &): в шаблон параметр "_Elem" неоднозначен

Ошибка 4 error C2780: std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem): требует аргументов: 3, имеется: 2


PS. Может, всё-таки отказаться от юникода?


"Умом Россию не понять, аршином общим не измерить: у ней особенная стать - в Россию можно только верить."©
Волхвы не боятся могучих владык, а княжеский дар им не нужен; правдив и свободен их вещий язык и с волей небесною дружен. Грядущие годы таятся во мгле; но вижу твой жребий на светлом челе. ©
virtuOS вне форума Отправить личное сообщение для virtuOS
Вверх
Ответить с цитированием
Старый Добавлено: 18.04.2011, 20:54
  (#5)
L.E.O.
Пользователь
Пользователь
 
Аватар для L.E.O.

По умолчанию

Цитата:
Сообщение от virtuOS Посмотреть сообщение
В проекте включен unicode

Об этом надо сразу говорить. Я ведь не знал, что у вас включен юникод. По вашу кода я думал, что он не включен, т.к. вы используете std::string. std::string хранит только char. Для wchar_t нужно использовать std::wstring. А можно и по-другому: написать код, который будет работать и с юникодом, и без юникода (std::basic_string<TCHAR>).
Код:
Код:
#define _UNICODE

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <fstream>
//#include <conio.h>
#include <vector>
#include <algorithm>

using namespace std;

#ifdef _UNICODE
typedef wfstream su_fstream; // support unicode file stream
#else
typedef fstream su_fstream; // support unicode file stream
#endif

typedef basic_string<TCHAR> su_string; // support unicode string
typedef vector<su_string> lines;

int PCList(const char *FileName, lines &ListBuf)
{
    su_fstream file_in(FileName, ios_base::in);
    su_string str;

    while (!file_in.eof())
    {
        getline(file_in, str);
        ListBuf.push_back(str);
    }
    file_in.close();
    return 0;
}

void printList(const su_string &StringBuf)
{
    wcout << StringBuf << endl;
}

int main()
{
    lines ListBuf;
    PCList("1.txt", ListBuf);
    for_each(ListBuf.begin(), ListBuf.end(), printList);
    return 0;
}

Примечания по коду (обязательно прочитать):
  1. Первая строка "#define _UNICODE" - это явное указание компилятору, что мы используем юникод. Вам это делать не надо, студия сама передает этот параметр компилятору. Я указал только для явности.
  2. Т.к. у меня компилятор 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)" и выложу сюда.
  3. Замечание по вашему коду: Если вы ничего не возвращаете, то зачем вы делаете ее функцией? Не лучше ли сделать ее процедурой?
  4. Замечание по вашему коду: если вы ничего не меняете в переменной, то лучше делать ее константой. У вас переменная "wchar_t* FileName" не изменяется, поэтому ее НУЖНО объявлять так "const wchar_t* FileName".
  5. Замечание по вашему коду: std::vector<std::string> - почему вы объявили ее так? а не лучше это вынести в еще один тип, так легче будет читать. Пример см. в моем коде тип "lines".
  6. Использовал "using namespace std" чтобы меньше писать и код был менее громоздким. Ну здесь, это кому как нравится.
  7. Не понял смысла "std::vector<std::string> ListBuf". Может быть вы имели в виду "std::vector<std::string> &ListBuf". То есть вы забыли указать, что мы берем адрес переменной, а не копируем всё в эту переменную. Я прав? Если что, это тема: "использование переменных, ссылок и адресов".
  8. Не понял смысла "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())" тоже плохо, иначе он не прочтет последнюю строку. Поэтому, чтобы прочитать все из файла, нужно использовать так, как я сделал это в примере.
  9. Я подключил "algorithm", лишь только для вывода текста, чтобы проверить корректность использования юникода. Проверка прошла успешно. Можете ее и убрать, вместе с "printList" и "for_each".


Помог, скажи спасибо
L.E.O. вне форума Отправить личное сообщение для L.E.O.
Вверх
Ответить с цитированием
Этот пользователь сказал cпасибо за это полезное сообщение:
virtuOS (19.04.2011)
Старый Добавлено: 19.04.2011, 11:28
  (#6)
virtuOS
Модератор
Модератор
 
Аватар для virtuOS

По умолчанию

Полностью код ещё не проверял, не было времени и возможности (выключают электричество на 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.,
Ещё вот что хотел спросить.

Код:
typedef wfstream su_fstream;
su_fstream file_in(FileName, ios_base::in);
Не смог найти внятной документации по этой функции. Особенно интересно значение параметра ios_base::in. Почитав примеры программ на форумах, нашел, что параметр может быть также ios::in | ios::out | ios::trunc. Догадываюсь, что это означает чтение из потока, запись в поток и очистка потока перед записью в него, но уверенности нет.


"Умом Россию не понять, аршином общим не измерить: у ней особенная стать - в Россию можно только верить."©
Волхвы не боятся могучих владык, а княжеский дар им не нужен; правдив и свободен их вещий язык и с волей небесною дружен. Грядущие годы таятся во мгле; но вижу твой жребий на светлом челе. ©

Последний раз редактировалось virtuOS; 19.04.2011 в 11:44..
virtuOS вне форума Отправить личное сообщение для virtuOS
Вверх
Ответить с цитированием
Старый Добавлено: 20.04.2011, 11:38
  (#7)
L.E.O.
Пользователь
Пользователь
 
Аватар для L.E.O.

По умолчанию

Цитата:
Сообщение от L.E.O. Посмотреть сообщение
написать код, который будет работать и с юникодом, и без юникода (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. Догадываюсь, что это означает чтение из потока, запись в поток и очистка потока перед записью в него, но уверенности нет.

Все верно. Можешь про параметры прочитать [Ссылки могут видеть только зарегистрированные пользователи. ]

Код под Visio Studio:

Код:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <fstream>
//#include <conio.h>
#include <vector>
#include <algorithm>

using namespace std;

#ifdef _UNICODE
typedef wfstream su_fstream; // support unicode file stream
#define out wcout
#else
typedef fstream su_fstream; // support unicode file stream
#define out cout
#endif

typedef basic_string<TCHAR> su_string; // support unicode string
typedef vector<su_string> lines;

int PCList(const TCHAR *FileName, lines &ListBuf)
{
    su_fstream file_in(FileName, ios_base::in);
    su_string str;

    while (!file_in.eof())
    {
        getline(file_in, str);
        ListBuf.push_back(str);
    }
    file_in.close();
    return 0;
}

void printList(const su_string &StringBuf)
{
    out << StringBuf << endl;
}

int main()
{
    lines ListBuf;
    PCList(_T("1.txt"), ListBuf);
    for_each(ListBuf.begin(), ListBuf.end(), printList);
    return 0;
}


Помог, скажи спасибо
L.E.O. вне форума Отправить личное сообщение для L.E.O.
Вверх
Ответить с цитированием
Этот пользователь сказал cпасибо за это полезное сообщение:
virtuOS (22.04.2011)
Старый Добавлено: 22.04.2011, 15:45
  (#8)
virtuOS
Модератор
Модератор
 
Аватар для virtuOS

По умолчанию

И снова здравствуйте ))).

Теперь проблемы с преобразованием типов данных.
Как передать в функцию CopyFileW(sPath, dPath, FALSE) строки из вектора, имеющие тип su_string? Как преобразовать wchar_t в TCHAR? У меня не получилось ни явное указание типа компилятору, ни через MultiByteToWideChar.


"Умом Россию не понять, аршином общим не измерить: у ней особенная стать - в Россию можно только верить."©
Волхвы не боятся могучих владык, а княжеский дар им не нужен; правдив и свободен их вещий язык и с волей небесною дружен. Грядущие годы таятся во мгле; но вижу твой жребий на светлом челе. ©
virtuOS вне форума Отправить личное сообщение для virtuOS
Вверх
Ответить с цитированием
Старый Добавлено: 22.04.2011, 20:32
  (#9)
Exodus
Заблокирован
Заблокирован
 
Аватар для Exodus

По умолчанию

Код:
char str[256];
wchar_t wstr[256];
mbstowcs(wstr,str,strlen(str));
вроде...
Exodus вне форума
Вверх
Ответить с цитированием
Старый Добавлено: 25.04.2011, 15:40
  (#10)
virtuOS
Модератор
Модератор
 
Аватар для virtuOS

По умолчанию

Цитата:
Сообщение от Exodus Посмотреть сообщение
вроде...

Вроде и без преобразований должно работать, но не работает.
Не работает даже так:
Код:
typedef std::basic_string<wchar_t> su_string;
su_string s, s1;
CopyFileW(s,s1,FALSE);
Код:
Ошибка	1	error C2664: CopyFileW: невозможно преобразовать параметр 1 из "su_string" в "LPCWSTR"


"Умом Россию не понять, аршином общим не измерить: у ней особенная стать - в Россию можно только верить."©
Волхвы не боятся могучих владык, а княжеский дар им не нужен; правдив и свободен их вещий язык и с волей небесною дружен. Грядущие годы таятся во мгле; но вижу твой жребий на светлом челе. ©
virtuOS вне форума Отправить личное сообщение для virtuOS
Вверх
Ответить с цитированием
Старый Добавлено: 25.04.2011, 16:50
  (#11)
Exodus
Заблокирован
Заблокирован
 
Аватар для Exodus

По умолчанию

Цитата:
Сообщение от virtuOS Посмотреть сообщение
Вроде и без преобразований должно работать, но не работает.

это тоже преобразование...

Цитата:
Сообщение от virtuOS Посмотреть сообщение
typedef std::basic_string<wchar_t> su_string;
su_string s, s1;

Exodus вне форума
Вверх
Ответить с цитированием
Старый Добавлено: 26.04.2011, 13:55
  (#12)
L.E.O.
Пользователь
Пользователь
 
Аватар для L.E.O.

По умолчанию

Всем привет. Долго не отвечал из-за написания и защиты отчета по практике.
Цитата:
Сообщение от 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; результирующий каталог, в который будут копироваться логи. Далее программа по-очереди обходить файлы в этих каталогах, и копирует их в другой текстовый файл.

Если хотите, можете использовать часть кода.
Код чисто под Visio Studio:

Код:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <windows.h>
#include <string>
#include <fstream>
//#include <conio.h>
#include <vector>
#include <algorithm>

using namespace std;

#ifdef _UNICODE
typedef wfstream su_fstream; // support unicode file stream
#define standart_out wcout
#else // _UNICODE
typedef fstream su_fstream; // support unicode file stream
#define standart_out cout
#endif // _UNICODE

typedef basic_ostream<TCHAR> su_ostream; // support out stream
typedef basic_string<TCHAR> su_string; // support unicode string
typedef vector<su_string> lines;

template <typename _CharT>
struct printList
{
    unsigned int index;
    basic_ostream<_CharT> &out;

    printList(basic_ostream<_CharT> &__basic_out) : index(1), out(__basic_out) {}

    void operator()(const su_string &StringBuf) { out << index << _CharT(')') << _CharT(' ') << StringBuf << endl; ++index; }
};

template <typename _CharT>
inline void correctingPathDir(basic_string<_CharT> &dir)
{
    if (!dir.empty() && *(dir.end() - 1) != _CharT('\\'))
    {
        dir += _CharT('\\');
    }
}

class LogCopy
{
private:
    unsigned int index;

    lines listLogFiles;
    lines listErrorFiles;

    su_string srcFileName;
    su_string destPath;

    void PCList()
    {
        su_fstream file_in(srcFileName.c_str(), ios_base::in);
        su_string str;

        if (!file_in.is_open())
        {
            // error
            return;
        }

        while (!file_in.eof())
        {
            getline(file_in, str);
            if (!str.empty())
            {
                listLogFiles.push_back(str);
            }
        }
        file_in.close();
    }

    void scanPCList(const TCHAR *fileName)
    {
        correctingPathDir(destPath);
        correctingPathDir(srcFileName);

        srcFileName += fileName;

        PCList();
    }

public:
    LogCopy(int argc, TCHAR **argv) :
        index(1)
    {
        if (2 <= argc)
        {
            srcFileName = argv[1];
        }

        if (3 <= argc)
        {
            destPath = argv[2];
        }

        scanPCList(_T("ip_list.txt"));
    }

    LogCopy(const TCHAR *SrcPath, const TCHAR *DestPath) :
        index(1)
    {
        srcFileName = SrcPath;
        destPath = DestPath;
        scanPCList(_T("ip_list.txt"));
    }

    bool operator ()(const su_string &PathName)
    {
        // tranform to new file name
        static TCHAR NewFileName[32767];
        _stprintf(NewFileName, _T("log_%d.txt"), index);
        ++index;

        su_string FullNameSrc = PathName;
        FullNameSrc += (!PathName.empty() && *(PathName.end() - 1) != _T('\\')) ? _T("\\log.txt") : _T("log.txt");
        su_string FullNameDst = destPath + NewFileName;

        BOOL bCoping = CopyFile(FullNameSrc.c_str(), FullNameDst.c_str(), FALSE);
        if (!bCoping)
        {
            listErrorFiles.push_back(FullNameSrc);
        }
        return bCoping;
    }

    void CopyFilesFull()
    {
        listErrorFiles.clear();
        for (lines::const_iterator i = listLogFiles.begin(); i != listLogFiles.end(); ++i)
        {
            (*this)(*i);
        }
    }

    bool CopyFilesToFirstError()
    {
        listErrorFiles.clear();
        for (lines::const_iterator i = listLogFiles.begin(); i != listLogFiles.end(); ++i)
        {
            if ((*this)(*i))
            {
                return false;
            }
        }
        return true;
    }

    inline size_t countErrorFiles() const { return listErrorFiles.size(); }
    inline size_t countLogFiles() const { return listLogFiles.size(); }

    lines ErrorFiles() const { return listErrorFiles; }
    lines LogFiles() const { return listLogFiles; }

    template <typename _CharT2>
    friend basic_ostream<_CharT2>& operator <<(basic_ostream<_CharT2> &cout, const LogCopy &logCopy);
};

template <typename _CharT>
inline basic_ostream<_CharT>& operator <<(basic_ostream<_CharT> &cout, const LogCopy &logCopy)
{
    for_each(logCopy.listErrorFiles.begin(), logCopy.listErrorFiles.end(), printList<_CharT>(cout));
    return cout;
}

int _tmain(int argc, _TCHAR **argv)
{
    LogCopy logCopy = LogCopy(argc, argv);
    logCopy.CopyFilesFull();
    if (logCopy.countErrorFiles())
    {
        standart_out << _T("List file name with error in copy:") << endl << logCopy;
    }

    return 0;
}


Код под любой компилятор:

Код:
#ifndef _MSC_VER // not for Microsoft visual studio

#define _UNICODE
#ifndef _UNICODE

#ifdef UNICODE
#undef UNICODE
#endif // UNICODE
#else // _UNICODE
#ifndef UNICODE
#define UNICODE
#endif // UNICODE
#endif // _UNICODE

#endif // _MSC_VER

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <windows.h>
#include <string>
#include <fstream>
//#include <conio.h>
#include <vector>
#include <algorithm>

using namespace std;

#ifdef _UNICODE
typedef wfstream su_fstream; // support unicode file stream
#define standart_out wcout
#else // _UNICODE
typedef fstream su_fstream; // support unicode file stream
#define standart_out cout
#endif // _UNICODE

#ifdef _MSC_VER // Microsoft visual studio
typedef TCHAR fchar; // file char
// sut - support unicode _TEXT(x)
#define sut(x) _T(x)
#else // _MSC_VER
typedef char fchar; // file char
// sut - support unicode _TEXT(x)
#define sut(x) x
#endif // _MSC_VER

typedef basic_ostream<TCHAR> su_ostream; // support out stream
typedef basic_string<TCHAR> su_string; // support unicode string
typedef vector<su_string> lines;

template <typename _CharT>
struct printList
{
    unsigned int index;
    basic_ostream<_CharT> &out;

    printList(basic_ostream<_CharT> &__basic_out) : index(1), out(__basic_out) {}

    void operator()(const su_string &StringBuf) { out << index << _CharT(')') << _CharT(' ') << StringBuf << endl; ++index; }
};

template <typename _CharT>
inline void correctingPathDir(basic_string<_CharT> &dir)
{
    if (!dir.empty() && *(dir.end() - 1) != _CharT('\\'))
    {
        dir += _CharT('\\');
    }
}

class LogCopy
{
private:
    unsigned int index;

    lines listLogFiles;
    lines listErrorFiles;

#ifdef _MSC_VER
    su_string srcFileName;
#else // _MSC_VER
    string srcFileName;
#endif // _MSC_VER

    su_string destPath;

    void PCList()
    {
        su_fstream file_in(srcFileName.c_str(), ios_base::in);
        su_string str;

        if (!file_in.is_open())
        {
            // error
            return;
        }

        while (!file_in.eof())
        {
            getline(file_in, str);
            if (!str.empty())
            {
                listLogFiles.push_back(str);
            }
        }
        file_in.close();
    }

    void scanPCList(const fchar *fileName)
    {
        correctingPathDir(destPath);
        correctingPathDir(srcFileName);

        srcFileName += fileName;

        PCList();
    }

public:
    LogCopy(int argc, fchar **argv) :
        index(1)
    {
        if (2 <= argc)
        {
            srcFileName = argv[1];
        }

        if (3 <= argc)
        {
#if defined(_MSC_VER) || !defined(_UNICODE)
            destPath = argv[2];
#else
            static TCHAR NewFileName[32767];
            mbstowcs(NewFileName, argv[2], strlen(argv[2]));
            destPath = NewFileName;
#endif
        }

        scanPCList(sut("ip_list.txt"));
    }

    LogCopy(const fchar *SrcPath, const TCHAR *DestPath) :
        index(1)
    {
        srcFileName = SrcPath;
        destPath = DestPath;
        scanPCList(sut("ip_list.txt"));
    }

    bool operator ()(const su_string &PathName)
    {
        // tranform to new file name
        static TCHAR NewFileName[32767];
        _stprintf(NewFileName, _T("log_%d.txt"), index);
        ++index;

        su_string FullNameSrc = PathName;
        FullNameSrc += (!PathName.empty() && *(PathName.end() - 1) != _T('\\')) ? _T("\\log.txt") : _T("log.txt");
        su_string FullNameDst = destPath + NewFileName;

        BOOL bCoping = CopyFile(FullNameSrc.c_str(), FullNameDst.c_str(), FALSE);
        if (!bCoping)
        {
            listErrorFiles.push_back(FullNameSrc);
        }
        return bCoping;
    }

    void CopyFilesFull()
    {
        listErrorFiles.clear();
        for (lines::const_iterator i = listLogFiles.begin(); i != listLogFiles.end(); ++i)
        {
            (*this)(*i);
        }
    }

    bool CopyFilesToFirstError()
    {
        listErrorFiles.clear();
        for (lines::const_iterator i = listLogFiles.begin(); i != listLogFiles.end(); ++i)
        {
            if ((*this)(*i))
            {
                return false;
            }
        }
        return true;
    }

    inline size_t countErrorFiles() const { return listErrorFiles.size(); }
    inline size_t countLogFiles() const { return listLogFiles.size(); }

    lines ErrorFiles() const { return listErrorFiles; }
    lines LogFiles() const { return listLogFiles; }

    template <typename _CharT2>
    friend basic_ostream<_CharT2>& operator <<(basic_ostream<_CharT2> &cout, const LogCopy &logCopy);
};

template <typename _CharT>
inline basic_ostream<_CharT>& operator <<(basic_ostream<_CharT> &cout, const LogCopy &logCopy)
{
    for_each(logCopy.listErrorFiles.begin(), logCopy.listErrorFiles.end(), printList<_CharT>(cout));
    return cout;
}

int main(int argc, char **argv)
{
    LogCopy logCopy = LogCopy(argc, argv);
    logCopy.CopyFilesFull();
    if (logCopy.countErrorFiles())
    {
        standart_out << _T("List file name with error in copy:") << endl << logCopy;
    }

    return 0;
}


Параметры передаются по стандартным правилам, а именно: если имя содержит пробел, то нужно ставить имя файла и пути в кавычки; путь лучше заканчивать без слеша. Если со слешом, то в таком виде (\\") разумеется без скобок.


Помог, скажи спасибо

Последний раз редактировалось L.E.O.; 26.04.2011 в 20:25..
L.E.O. вне форума Отправить личное сообщение для L.E.O.
Вверх
Ответить с цитированием
Этот пользователь сказал cпасибо за это полезное сообщение:
virtuOS (26.04.2011)
Старый Добавлено: 26.04.2011, 15:10
  (#13)
virtuOS
Модератор
Модератор
 
Аватар для virtuOS

По умолчанию

L.E.O.,
Цитата:
Сообщение от L.E.O. Посмотреть сообщение
Долго не отвечал из-за написания и защиты отчета по практике.

Надеюсь, защита прошла успешно.

Спасибо большое за код и потраченное время. Что-то безусловно возьму из вашего примера, но писать скорее всего буду самостоятельно. Только так придет понимание каждой строчки программы, а быть "копи-пастером" я не хочу. Хотя и говорят, что учиться лучше на чужих ошибках, но к программированию это скорее всего не относится. Только с опытом придет результат. Но в любом случае спасибо, думаю, ваш пример позволит избежать многих ошибок.


"Умом Россию не понять, аршином общим не измерить: у ней особенная стать - в Россию можно только верить."©
Волхвы не боятся могучих владык, а княжеский дар им не нужен; правдив и свободен их вещий язык и с волей небесною дружен. Грядущие годы таятся во мгле; но вижу твой жребий на светлом челе. ©
virtuOS вне форума Отправить личное сообщение для virtuOS
Вверх
Ответить с цитированием
Старый Добавлено: 07.06.2011, 11:27
  (#14)
ekzekuciya
Наблюдающий
Пользователь
 
Аватар для ekzekuciya

По умолчанию

std::getline(f, str);

str это не std::string, а чаровский массив или указатель на массив
ekzekuciya вне форума Отправить личное сообщение для ekzekuciya
Вверх
Ответить с цитированием
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.10
Copyright ©2000 - 2019, vBulletin Solutions, Inc. Перевод: zCarot

Время генерации страницы 0.16308 секунды с 19 запросами