How to read only certain range of symbols from std::basic_ostream (e.g. std::cin) - std

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
int main () {
std::vector<std::string> words{};
std::string word;
char letter;
while (std::cin.get(letter) && letter != '\n') {
if ('a' <= std::tolower(letter) && std::tolower(letter) <= 'z') {
word.push_back(letter);
} else if (!word.empty()) {
words.push_back(word);
word.clear();
}
}
words.push_back(word);
std::ostream_iterator<std::string> out(std::cout, " ");
std::copy(words.begin(), words.end(), out);
return 0;
}
Is there some way to read data from the stream, while ignoring certain characters (or vice versa, reading only certain ones)? I know how to do it "manually" (example above), but I want to use all the functionality of the C++ standard library. Maybe there are some special stream manipulators?

Related

how to find characters in a string and then remove them if they match a particular character?

/* I have to find character and remove them, based on the character it has to go inside the if/else if condition. I am facing difficulty in getting inside the else if condition */
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <string>
using namespace std;
int main() {
int fut = 0, spd =0;
std::string symbol = "PGSh/d TWOGK h/d"; //it will contain either 'h/d' or '/'
std::string str = "h/d";
std::string str1 = "/";
if(symbol.find(str)) //if it finds "h/d" then it belongs to future
{
++fut; //even one count is enough
boost::erase_all(symbol, "h/d");
std::cout<<"Future Instrument "<<std::endl;
}
else if(symbol.find(str1)) //if it finds "/" then it belongs to spread
{
++spd; //even one count is enough
boost::erase_all(symbol, "//");
std::cout<<"Spread Instrument "<<std::endl;
}
boost::erase_all(symbol, " ");
boost::to_upper(symbol);
std::cout<<symbol<<std::endl;
return 0;
}

gcc using unlink and readdir, 7 days old files needs to be deleted

Using this code fetched from google.
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct dirent *entry;
DIR *dp;
chdir("/mnt/shared");
dp = opendir(".");
while( (entry = readdir(dp)) != NULL ) {
if ( strcmp(entry->d_name, ".") &&strcmp(entry->d_name, "..") ){
unlink(entry->d_name);
}
}
}`
In this could it be possible to delete files older than 7 days from the current date?
In perl i tried as follows, but wondering this could be achived with your help?
my $now = time();
my $DATEAGE = 60*60*24*7;
for my $file (#file_list) {
my #stats = stat($file);
if ($now-$stats[9] > $DATEAGE) {
print "$file\n";}
Build the full string of the file and use several syscalls(2) (notably stat(2)) ; read Advanced Linux Programming
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct dirent *entry;
DIR *dp;
time_t weekago;
time(&weekago);
weekago -= 86400*7;
dp = opendir("/mnt/shared");
if (!dp) { perror("/mnt/shared"); exit(EXIT_FAILURE); };
while( (entry = readdir(dp)) != NULL ) {
if ( strcmp(entry->d_name, ".")
&& strcmp(entry->d_name, "..") ){
char buf[256];
if (snprintf(buf, sizeof(buf),
"/mnt/shared/%s", entry->d_name)
>=sizeof(buf))
{ fprintf(stderr, "too long path %s\n", buf);
exit(EXIT_FAILURE);
};
struct stat st;
if (stat(buf,&st)) {
perror(buf);
exit(EXIT_FAILURE);
};
if ((st.st_mode & S_IFMT) == S_IFREG // a plain file
&& (st.st_mtime < weekago))
{
if (remove(buf)) perror(buf);
}
}
}
My untested code above is imperfect (and not very well indented): it don't handle file paths wider than 255. But you could improve it, e.g. using asprintf(3) to build the path in heap (then you'll need to free it).
Practically speaking, use find(1). If you need to recurse in a file tree in C, use nftw(3)

Why won't this program work in release mode?

#include <iostream>
#include <fstream>
#include <stdlib.h> // includes the "atoi" function
#include <string>
using namespace std;
#include <sstream>;
int main()
{
std::fstream f;
f.open("file.in", std::fstream::in);
// read data
int count = 0;
std::string line = "";
getline( f, line, '\n' );
count = atoi( line.c_str() );
f.close();
f.open("file.in", std::fstream::out | std::fstream::trunc);
// write data
++count;
f << count << endl;
f.close();
return 0;
}
This works in debug mode in Visual Studio but when I run it as an application it doesn't work. I've initialized all variables so I'm not sure what else to check.
This line
f.open("file.in", std::fstream::in);
Make sure file.in is in \bin\release
I also advice your to use try/catch statements and print your errors

How to parse escaped string using `c_escape_ch_p` from boost::spirit?

I'm trying to use c_escape_ch_p (see here) from boost::spirit to parse an escaped C++ string. But I'm getting a compiler error. Here is my code:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/home/classic/utility/escape_char.hpp>
#include <boost/spirit/home/classic/utility/confix.hpp>
#include <iostream>
#include <string>
namespace client {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
bool parse(Iterator first, Iterator last) {
using qi::char_;
qi::rule< Iterator, std::string(), ascii::space_type > text;
using namespace boost::spirit::classic;
qi::rule<Iterator, std::string()> myword2 =
confix_p('"', *c_escape_ch_p, '"') ; // ERROR!
text = myword2;
bool r = qi::phrase_parse(first, last, text, ascii::space);
if (first != last)
return false;
return r;
}
}
int main () {
std::string s = "\"foo\"";
bool ok = client::parse(s.begin(), s.end());
std::cout << "OK? " << (ok ? "y" : "n") << std::endl;
return 0;
}
The compiler error is a failed static assert instantiated from the line with confix:
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
So, it says it's not a valid expression. How is it used correctly?
P.S.: I'm using Boost 1.45.
You are trying to combine classic (old, V1, ...) boost::spirit::classic and (new, V2) boost::spirit::qi.
This is not going to work. The newer stuff is a complete, and incompatible, rewrite. See the 'Porting from Spirit 1.8.x' notes in the documentation.
As for the question on how to parse escaped C/C++ strings using boost::spirit::qi, the following article will be helpful:
Parsing Escaped String Input Using Spirit.Qi

boost.log auto_flush files are not stored when app is crashed

Recently I started to play with boost.log, and bumped into an issue that if an unhanded exception is thrown no log messages are written to the log file. I am using rolling text files and auto-flash option is set on.
Here is the modified source from the samples:
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
#include <functional>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/log/common.hpp>
#include <boost/log/filters.hpp>
#include <boost/log/formatters.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/empty_deleter.hpp>
#include <boost/log/utility/record_ordering.hpp>
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace fmt = boost::log::formatters;
namespace keywords = boost::log::keywords;
using boost::shared_ptr;
using namespace boost::gregorian;
enum
{
LOG_RECORDS_TO_WRITE = 100,
LOG_RECORDS_TO_WRITE_BEFORE_EXCEPTION = 10,
THREAD_COUNT = 10
};
BOOST_LOG_DECLARE_GLOBAL_LOGGER(test_lg, src::logger_mt)
//! This function is executed in multiple threads
void thread_fun(boost::barrier& bar)
{
// Wait until all threads are created
bar.wait();
// Here we go. First, identify the thread.
BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::thread::id, boost::this_thread::get_id());
// Now, do some logging
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
{
BOOST_LOG(get_test_lg()) << "Log record " << i;
if(i > LOG_RECORDS_TO_WRITE_BEFORE_EXCEPTION)
{
BOOST_THROW_EXCEPTION(std::exception("unhandled exception"));
}
}
}
int main(int argc, char* argv[])
{
try
{
typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
shared_ptr< file_sink > sink(new file_sink(
keywords::file_name = L"%Y%m%d_%H%M%S_%5N.log", // file name pattern
keywords::rotation_size = 10 * 1024 * 1024, // rotation size, in characters
keywords::auto_flush = true // make each log record flushed to the file
));
// Set up where the rotated files will be stored
sink->locked_backend()->set_file_collector(sinks::file::make_collector(
keywords::target = "log" // where to store rotated files
));
// Upon restart, scan the target directory for files matching the file_name pattern
sink->locked_backend()->scan_for_files();
sink->locked_backend()->set_formatter(
fmt::format("%1%: [%2%] [%3%] - %4%")
% fmt::attr< unsigned int >("Line #")
% fmt::date_time< boost::posix_time::ptime >("TimeStamp")
% fmt::attr< boost::thread::id >("ThreadID")
% fmt::message()
);
// Add it to the core
logging::core::get()->add_sink(sink);
// Add some attributes too
shared_ptr< logging::attribute > attr(new attrs::local_clock);
logging::core::get()->add_global_attribute("TimeStamp", attr);
attr.reset(new attrs::counter< unsigned int >);
logging::core::get()->add_global_attribute("Line #", attr);
// Create logging threads
boost::barrier bar(THREAD_COUNT);
boost::thread_group threads;
for (unsigned int i = 0; i < THREAD_COUNT; ++i)
threads.create_thread(boost::bind(&thread_fun, boost::ref(bar)));
// Wait until all action ends
threads.join_all();
return 0;
}
catch (std::exception& e)
{
std::cout << "FAILURE: " << e.what() << std::endl;
return 1;
}
}
Source is compiled under Visual Studio 2008. boost.log compiled for boost 1.40.
Any help is highly appreciated.
Check to see if the log file is in the current working directory of the process, rather than the specified file collector target directory ("log" in your sample code). Additionally, you will probably want to specify a directory for the sink "file_name" pattern.
As "JQ" notes, don't expect to see any logging post-exception.

Resources