Господа, настало время спрашивать у вас про С++
Проблема такова:
я прочитал книжку, и мне надо за 3 дня перерписать мой красивенький проект с C# на с++ —
потому что он срочно понадобился коллегам, а у них на с++ все
я полдня пробую записать строчку в файл.
Вот мой код:
ну что я могу сказать?
не пишет, сука, и ошибок не выдает.
Заодно, не научите ли вы меня складывать строки более человеческим способом, чем strcat()?
Вообще, мне очень нравится библиотека boost, и строки там почти нормальные,
но почему то оператор сложения не работает.
SLH>ну что я могу сказать? SLH>не пишет, сука, и ошибок не выдает.
Символ '\T' — это табуляция.
Пиши путь с нормальной косой — и будет тебе счастье. SLH>Заодно, не научите ли вы меня складывать строки более человеческим способом, чем strcat()? SLH>Вообще, мне очень нравится библиотека boost, и строки там почти нормальные, SLH>но почему то оператор сложения не работает.
Оператор сложения работает для строк из STL. Тип std::string.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Большое спасибо всем за ответы!
Даже не ожидал такой положительной реакции!
Пока все заработало.
я за это время просмотрел документацию по boost::filesystem,
но там люди такими вещами как запись строки в файл не заморачиваются
то есть готового примера там нет.
будем искать!
Здравствуйте, SteeLHeaD, Вы писали:
SLH>я за это время просмотрел документацию по boost::filesystem, SLH>но там люди такими вещами как запись строки в файл не заморачиваются
Файлсистем — это работа с файловой системой — создание\удаление\итерация и т.д.
SLH>то есть готового примера там нет. SLH>будем искать!
const char* logFile="c:\\Temp\\Logs\\mainlog.log";
time_t rawtime;
time ( &rawtime );
struct tm* timeinfo;
timeinfo = localtime ( &rawtime );
char* format = "%I:%M:%S";
char buffer[50];
strftime(buffer, 50, format, timeinfo);
//string rez = strcat(strcat(strcat( buffer, ": "), str), "\r\n");
// этот код не нужен, см ниже
// но конкатенировать строки как-то так
// std::string(buffer) + ": " + str + "\r\n"
// чтобы работал "+" один из аргументов должен быть std::string
// str + ":" // ок
// ":" + str // ок
// buffer + ":" // не ок (складываются указатели)
ofstream myfile;
myfile.open( logFile, ios_base::out | ios::app );
myfile << buffer << ": " << str << "\r\n";
// myfile.flush(); // вызовется из close()
// myfile.close(); // при выходе за области видимости close вызовется из деструктора
ЗЫ файл хорошо бы где-нить сохранять, а не переоткрывать при каждом вызове logger::WriteLog
Здравствуйте, enji, Вы писали:
E>и насчет работы с датой\временем возможно стоит посмотреть на boost::date_time. Возможно покажется проще, чем сишные функции
Здравствуйте, LaptevVV, Вы писали:
LVV>Оператор сложения работает для строк из STL. Тип std::string.
это называется "стандартная библиотека", а не "STL".
в STL строк никогда не было.
Здравствуйте, Mr.Delphist, Вы писали:
MD>Здравствуйте, Mihas, Вы писали:
M>>SteeLHeaD, оно ж и в шарпе также. Куда смотрел?
MD>В шарпе можно написать @ перед строкой, и тогда никакого экранирования...
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, LaptevVV, Вы писали:
LVV>>Оператор сложения работает для строк из STL. Тип std::string. A>это называется "стандартная библиотека", а не "STL". A>в STL строк никогда не было.
Почему?
Standart Template Library — это стандартная библиотека С++.
Джоссатис написал... Член комитета как раз по этому вопросу...
Глава 11 его книжки.
Или вы различаете термины Standart Template Library и стандартная библиотека.
Я предпочитаю не различать.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>>>Оператор сложения работает для строк из STL. Тип std::string. A>>это называется "стандартная библиотека", а не "STL". A>>в STL строк никогда не было. LVV>Почему? LVV>Standart Template Library — это стандартная библиотека С++.
никакой STL в действующем стандарте нет.
есть Strings library и куча других либ. все они вместе называются standart library
LVV>Джоссатис написал... Член комитета как раз по этому вопросу... LVV>Глава 11 его книжки.
какой книжки, какое издание?
LVV>Или вы различаете термины Standart Template Library и стандартная библиотека.
да. STL была разработана Степановым для ранних версий С++, в ней никаких строк не было.
потом, в С++98 из нее сделали Algorithms library, часть Numerics library и т.п.
LVV>Я предпочитаю не различать.
я предпочитаю использовать корректные термины.
Здравствуйте, SteeLHeaD, Вы писали:
SLH>Большое спасибо всем за ответы! SLH>Даже не ожидал такой положительной реакции! SLH>Пока все заработало. SLH>я за это время просмотрел документацию по boost::filesystem, SLH>но там люди такими вещами как запись строки в файл не заморачиваются SLH>то есть готового примера там нет. SLH>будем искать!
Элементарные примеры в моей книжке написаны. И здесь на форуме я постил — поищи.
По традиции в Windows разделителем является символ обратной косой черты (\). В программе на С++ этот символ необходимо писать дважды (\\), так он является специальным символом. Однако допускается использовать и обычную косую черту (/). Разделитель должен отделять диск от имени каталога. Примеры имен:
"question.txt"
"c:\\test\\question.doc"
"a:/number.bin"
И далее:
Пример обработки текстовых файлов
В качестве примера обработки текстовых файлов напишем программу, которая реализует наиболее часто используемую функцию препроцессора — подключение файлов с помощью оператора #include. Ограничим синтаксис оператора:
оператор начинается с первой позиции строки;
подключаемый файл всегда задается в формате «имя_файла»;
имя файла отделяется от оператора #include только одним пробелом.
Таким образом, непосредственно имя файла начинается в операторе всегда с 11-й позиции и продолжается до символа-кавычки. Подключаемый файл тоже может содержать операторы #include. Ограничение вложенности, очевидно, задается глобальной константой FOPEN_MAX, определяющей максимальное количество одновременно открытых файлов и определенной в заголовке <stdio.h>.
Итак, в результате получаем:
#include "имя_файла"
При подключении этот оператор записывается в результирующий файл как комментарий:
//----------#include имя_файла----------
После этой строки в результирующий файл записывается содержимое указанного файла. Если подключаемый файл не был открыт, то в результирующий файл записывается строка-комментарий:
//----------#include имя_файла -- Error! -- File not open!
Подключаемые файлы могут, вообще говоря, располагаться в различных каталогах, но мы для проверки работы программы соберем их все в нашем каталоге TextFiles. Файл, который надо обрабатывать первым, задается в командной строке. Если имя задано неверно, то программа завершает работу. Результирующий файл с именем result.files размещается в том же каталоге TextFiles. Текст программы представлен в листинге 14.5.
Листинг 14.5. Обработка оператора #include
string NameFiles(const char *namefile)
{ string path = "c:/textfiles/";
return path+namefile;
}
bool isInclude(const string line)
{ if (line.substr(0,8) == "#include") return true;
else return false;
}
void includeFile(const char *namefile, ofstream &result)
{ static int countfiles = 0;
++countfiles;
if (countfiles > FOPEN_MAX) // файлов больше положенного?
{ cerr << "Too mani files is opened!" << endl;
abort();
}
string line; // читаемая строкаconst string tenminus = "----------";
const string include = "#include ";
string comment;
string name = NameFiles(namefile); // полное имя файла
ifstream in; // очередной входной файл
in.open(name.c_str()); // открылиif(in.is_open()) // если открылся
{ getline(in, line);
while(!in.eof())
{ if (isInclude(line)) // если #include
{ char file[FILENAME_MAX];
int i = 0; // извлекаем имя файла из #includewhile(line[i+10]!='"') { file[i]=line[i+10]; i++; }
file[i] = 0; // завершающий ноль
comment = "//"+tenminus+include+file+tenminus;
result << comment << endl;
includeFile(file, result); // пошли внутрь
result <<"//-end------------------------------\n";
}
else result << line << endl;
getline(in, line);
}
in.close();
}
else// формируем ошибочный комментарий
{ const string Error = "Error! -- File not open!";
comment = "//"+tenminus+include+namefile+" -- "+Error+'\n';
result << comment;
}
}
int main(int argc, char *argv[])
{ ofstream result ("c:/textfiles/result.files");
if(!result.is_open()) // ошибка при открытии
{ cerr << "Error result file!" << endl;
return 1;
}
includeFile(argv[1], result);
result.close();
return 0;
}
Главная программа просто открывает результирующий файл и вызывает рекурсивную функцию обработки, передавая ей в качестве параметра имя файла из командной строки и поток-результат. Ошибки практически не обрабатываются, чтобы не отвлекаться от основной задачи — обработки файлов.
Основную работу выполняет рекурсивная функция includeFile(), аргументом которой является имя обрабатываемого файла и поток-результат. Функция в начале считает количество открытых файлов — можно запрограммировать здесь более серьезную обработку ошибки (например, генерировать исключение). Если все в порядке, то формируется полное имя файла — работает вспомогательная функция NameFiles(). Далее файл открывается, и в цикле читаются строки файла. Если прочитана обычная строка, то она просто выводится в результирующий файл. Если же строка содержит оператор #include (что определяет простая функция-предикат isInclude()), то формируется и выводится строка-комментарий о включаемом файле, и выполняется рекурсивный вызов. По окончании файла выводится дополнительная строка минусов со словом «end». Таким образом, включенный файл оказывается обрамленным двумя строками-комментариями. Если же при открытии файла возникли проблемы, то формируется строка-комментарий с ошибкой, и функция завершает обработку текущего файла.
Создадим в каталоге TextFiles три небольших текстовых файла a.txt, b.txt и d.txt:
файл a.txt:
Файл a.txt подключает файл b.txt, который, в свою очередь, подключает файл d.txt и ошибочный файл dd.txt. Результат работы нашей программы получается следующий:
Как видим, вложенные файлы обрабатываются совершенно правильно.
Собственно, если бы не нужно было формировать комментарий вокруг вложенного файла, функция includeFile() была бы значительно короче (листинг 14.6).
Листинг 14.6. Функиця includeFile()
void includeFile(const char *namefile, ofstream &result)
{ static int countfiles = 0;
++countfiles; // проверяем countfiles > FOPEN_MAX
if (countfiles > FOPEN_MAX)
{ cerr << "Too mani files is opened!" << endl; abort(); }
string line;
string name = NameFiles(namefile);
ifstream in;
in.open(name.c_str());
if(in.is_open())
{ getline(in, line);
while(!in.eof())
{ if (isInclude(line)) includeFile(file, result);
else result << line << endl;
getline(in, line);
}
in.close();
}
else result << "Error! -- File not open!" << endl;
}
Этот вариант функции вполне можно использовать в «настоящем» препроцессоре.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, Mr.Delphist, Вы писали:
MD>>Здравствуйте, Mihas, Вы писали:
M>>>SteeLHeaD, оно ж и в шарпе также. Куда смотрел?
MD>>В шарпе можно написать @ перед строкой, и тогда никакого экранирования...
A>а в С++ можно написать R"(...)", ну и что?
А вот с этого места — можно поподробнее? T-макрос знаю, а вот R — никогда не встречался.
Здравствуйте, Mr.Delphist, Вы писали:
A>>а в С++ можно написать R"(...)", ну и что?
MD>А вот с этого места — можно поподробнее? T-макрос знаю, а вот R — никогда не встречался.