Trying to print a map in CPP with LIBCACA - c++

I'm trying to display a simple map using the caca_put_str() / caca_printf() function except that it doesn't interpret the '\n' correctly. Any tips to share to fix this? The documentation is quite empty btw...
Thanks in advance !
Here is the code :
#include <string>
#include <caca.h>
#include <iostream>
#include <fstream>
caca_canvas_t *cv;
static std::string readFile(const std::string &file)
{
std::ifstream buffer(file);
std::string str;
if (buffer.is_open())
{
std::getline(buffer, str, '\0');
buffer.close();
return (str);
}
return (NULL);
}
int main(void)
{
std::string map = readFile("arcade.txt");
caca_display_t *dp;
caca_event_t event;
int width = 1080;
int height = 980;
cv = caca_create_canvas(width, height);
dp = caca_create_display(cv);
if (!dp)
std::exit(1);
caca_set_display_title(dp, "Windows");
while (true)
{
caca_refresh_display(dp);
caca_put_str(cv, 0, 0, map.c_str();
}
caca_free_canvas(cv);
caca_free_display(dp);
}
I'm trying to print this :
############################
#............##............#
#.####.#####.##.#####.####.#
#.####.#####.##.#####.####.#
#..........................#
#.####.##.########.##.####.#
#......##....##....##......#
######.#####.##.#####.######
#....#.##..........##.#....#
#....#.##.###--###.##.#....#
######.##.#......#.##.######
..........#......#..........
######.##.#......#.##.######
#....#.##.########.##.#....#
#....#.##..........##.#....#
######.##.########M##.######
#............##............#
#.####.#####.##.#####.####.#
#...##................##...#
###.##.##.########.##.##.###
#......##....##....##......#
#.##########.##.##########.#
But it is displayed on a single line.

Related

Tried to split wchar or another function to get the file name of running application

I searched here a lot and did try several examples but still can't solve my little problem.
I need to extract the file name 'test.exe' out of the path. Has someone an idea which might work? Other option is to get the file name by another function?
Thanks in advance!
WCHAR fileName[255];
GetModuleFileName(NULL, fileName, 255); // fileName = \TestFolder\test.exe
Look at PathFindFileName():
#include <windows.h>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
WCHAR fullPath[MAX_PATH];
GetModuleFileName(NULL, fullPath, MAX_PATH);
LPWSTR fileName = PathFindFileName(fullPath);
Using WinApi
#include <iostream>
#include <string>
#include <windows.h>
std::string GetExecutableName()
{
std::string path = std::string(MAX_PATH, 0);
if( !GetModuleFileNameA(nullptr, &path[0], MAX_PATH ) )
{
throw std::runtime_error(u8"Error at get executable name.");
}
size_t pos=path.find_last_of('/');
if(pos == std::string::npos)
{
pos = path.find_last_of('\\');
}
return path.substr(pos+1);
}
int main()
{
std::cout<< GetExecutableName() << std::endl;
return 0;
}
Using main args
First - arg[0] contains full filename of executable.
#include <iostream>
#include <string>
std::string GetExecutableName(const std::string& exe)
{
size_t pos=exe.find_last_of('/');
if(pos == std::string::npos)
{
pos =exe.find_last_of('\\');
}
return exe.substr(pos+1);
}
int main(int argc,char ** args) {
std::cout << GetExecutableName(args[0])<< std::endl;
}

bsoncxx - is there a way to iterate through documents in .bson dump file?

Similarly to how we construct bsoncxx::document::view objects from a buffer with a single binary document, is there a way to extract single documents from a collection in a .bson dump in this framework without having to load them into a DB?
i.e. what works for single document objects
uint8 *buffer; // single bson document
size_t length; // size of buffer
bsoncxx::document::view view(buffer, length);
for (auto elem : view) {
doSomethingWithElem()
}
I'd like to be able to construct a cursor for the whole dump, but without loading it into a collection. Is something like this possible?
Found the solution and it was pretty simple in the end - I utilized the libbson library.
An example of what I used below:
#include <bson.h>
// and other includes
void read_bson() {
bson_reader_t *reader;
const bson_t *doc;
bson_error_t error;
bool eof;
char *path;
reader = bson_reader_new_from_file(path, &error);
if (reader)
{
while ((doc = bson_reader_read(reader, &eof)))
{
const uint8_t *buffer = bson_get_data(doc);
auto view = bsoncxx::document::view(buffer, doc->len);
}
}
}
If you are using mongo-cxx-driver, here is a example for reading bson file dumped by mongodump tool.
#include <iostream>
#include <vector>
#include <fstream>
#include <mongocxx/client.hpp>
#include <mongocxx/uri.hpp>
#include <bsoncxx/json.hpp>
#include <bsoncxx/builder/stream/document.hpp>
#include <sstream>
void parse_one_doc(const char *data, const size_t &length) {
// TODO fill your code
bsoncxx::document::view view((std::uint8_t *) data, length);
std::cout << bsoncxx::to_json(view) << std::endl;
}
int unpack_size(const char *data, size_t position) {
return *(int *) (data + position);
}
bool parse_mongo_dumper(const std::string &data) {
size_t position = 0u, end = data.length() - 1u, data_len = data.size();
size_t obj_size, obj_end;
const char *dc = data.c_str();
while (position < end) {
obj_size = unpack_size(dc, position);
if (position + obj_size > data_len) {
return false;
}
obj_end = position + obj_size;
if (*(dc + obj_end - 1) != '\0') {
return false;
}
parse_one_doc(dc + position, obj_size);
position = obj_end;
}
return true;
}
int main() {
std::string f = "/path/to/data.bson";
// read all data into string
std::ifstream t(f);
std::stringstream buffer;
buffer << t.rdbuf();
std::string s = buffer.str();
// parse bson
parse_mongo_dumper(s);
return 0;
}

WritePrivateProfileString works in main but not in function

I am trying to use WritePrivateProfileString and GetPrivateProfileInt for a .ini parser.
When I put the code below into main(), or into a class constructor, it works for writing and reading.
But, when I make functions for writing and reading, and call the functions in main(), nothing happens, although the functions are run as they will cout something if I ask them to.
Here is the test program I wrote to demonstrate this:
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <string>
#define CStringify(x) std::to_string(x).c_str()
int testvar = 12;
int returntestvar = 0;
std::fstream config;
std::string configstring = ".//config.ini";
int main()
{
WriteINI();
ReadINI();
std::cout << returntestvar << std::endl;
getchar();
}
void WriteINI()
{
config.open("config.ini", std::ios::app);
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void ReadINI()
{
config.open("config.ini", std::ios::app);
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The above code creates and then edits an .ini file, as it is expected to.
However, if I move the code into a class, it will no longer work.
main.cpp
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <string>
#include "INIClassTest.h"
extern INIParser* Parse;
int main()
{
Parse->WriteINI();
Parse->ReadINI();
std::cout << Parse->returntestvar << std::endl;
getchar();
}
INIClassTest.h
#pragma once
#include <fstream>
#include <string>
#include <Windows.h>
#define CStringify(x) std::to_string(x).c_str()
class INIParser
{
public:
INIParser();
void WriteINI();
void ReadINI();
int testvar;
int returntestvar;
std::fstream config;
std::string configstring;
};
extern INIParser* Parse;
INIClassTest.cpp
#include "INIClassTest.h"
#include <iostream>
INIParser* Parse = new INIParser();
INIParser::INIParser()
{
returntestvar = 0;
testvar = 18;
std::string configstring = ".//config.ini";
}
void INIParser::WriteINI()
{
config.open("config.ini", std::ios::app);
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void INIParser::ReadINI()
{
config.open("config.ini", std::ios::app);
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The above code creates an .ini file, but it doesn't edit it or return anything.
You should NOT be using an fstream at all to create/open the INI file manually. WritePrivateProfileString() and GetPrivateProfileInt() handle that for you.
Also, if you read their documentation, you would see that you SHOULD NOT use a relative path for the INI file, or else the file will be relative to the Windows installation folder, not your app folder. So, you probably ARE reading/writing the INI file, just not where you are expecting from/to. If you want your INI file to be relative to your app's folder, you need to retrieve the path of your app's folder 1 and append the INI filename to it.
1: that is really not a good idea in general, though. Depending on where you install your app, the user might not have write access to that folder. You should instead use SHGetFolderPath() or SHGetKnownFolderPath() to get the user's local %AppData% folder, then create your own subfolder inside of it, and then create your INI file inside of that subfolder.
Try this instead:
#include <Windows.h>
#include <iostream>
#include <string>
#define CStringify(x) std::to_string(x).c_str()
std::string GetAppFolder();
std::string GetINIPath();
void WriteINI();
void ReadINI();
int testvar = 12;
int returntestvar = 0;
std::string configstring = GetINIPath();
int main()
{
WriteINI();
ReadINI();
std::cout << returntestvar << std::endl;
std::cin.get();
return 0;
}
std::string GetAppFolder()
{
char szFileName[MAX_PATH];
DWORD len = GetModuleFileName(NULL, szFileName, MAX_PATH);
std::string result(szFileName, len);
std::string::size_type pos = result.find_last_of("\\/");
result.resize(pos+1);
return result;
}
std::string GetINIPath()
{
return GetAppFolder() + "config.ini";
}
void WriteINI()
{
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void ReadINI()
{
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The main reason your INIParser class fails is because your constructor is storing the INI file path in a local variable named configstring, instead of in the class's member also named configstring. Thus, the class member is blank when WriteINI() and ReadINI() are called.
Try this instead:
main.cpp
#include <iostream>
#include "INIClassTest.h"
int main()
{
Parse.WriteINI();
Parse.ReadINI();
std::cout << Parse.returntestvar << std::endl;
std::cin.get();
return 0;
}
INIClassTest.h
#pragma once
#include <string>
class INIParser
{
public:
INIParser();
void WriteINI();
void ReadINI();
int testvar;
int returntestvar;
std::string configstring;
};
extern INIParser Parse;
INIClassTest.cpp
#include <Windows.h>
#include "INIClassTest.h"
#include <string>
#define CStringify(x) std::to_string(x).c_str()
INIParser Parse;
static std::string GetAppFolder()
{
char szFileName[MAX_PATH];
DWORD len = GetModuleFileName(NULL, szFileName, MAX_PATH);
std::string result(szFileName, len);
std::string::size_type pos = result.find_last_of("\\/");
result.resize(pos+1);
return result;
}
static std::string GetINIPath()
{
return GetAppFolder() + "config.ini";
}
INIParser::INIParser()
{
returntestvar = 0;
testvar = 18;
configstring = GetINIPath();
}
void INIParser::WriteINI()
{
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void INIParser::ReadINI()
{
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}

howto: Read input and store it in another file

I want to make a program that reads the highest value from one file and stores it in another. I've read about ifstream and ofstream but how do I let the ofstream store the highest value from the instream in another file? Here is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
} csvWhitespace;
int main() {
string line;
ifstream myfile ("C:/Users/Username/Desktop/log.csv");
ofstream myfile2 ("C:/Users/Username/Desktop/log2.csv");
return 0;
}
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), &csvWhitespace});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}
Thanks in advance :)
You could just copy from the one file in the other, without having to worry about the format, by treating them in binary mode. Here is an example:
#include <stdio.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE *ifp, *ofp;
char buf[bufSize];
if (argc != 3)
{
fprintf(stderr,
"Usage: %s <soure-file> <target-file>\n", argv[0]);
return 1;
}
if ((ifp = fopen(argv[1], "rb")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
if ((ofp = fopen(argv[2], "wb")) == NULL)
{ /* Open target file. */
perror("fopen target-file");
return 1;
}
while (fgets(buf, sizeof(buf), ifp) != NULL)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
/* Write characters read to target file. */
fwrite(buf, sizeof(char), strlen(buf), ofp);
}
fclose(ifp);
fclose(ofp);
return 0;
}
which was given as an example in IP, source. You just need to specify the cmd arguments as the desired files.
You can do it like this. Live example using cin and cout rather than files.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
};
int main() {
string line;
ifstream myfile("log.csv");
ofstream myfile2("log2.csv");
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), new CsvWhitespace{}});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}

istream object don't read any char

Why istream object after calling readsome() method don't give any chars in buffer? Is there any error in class construction?
StreamBuffer.h
#ifndef StreamBuffer_h
#define StreamBuffer_h
#include <string>
#include <fstream>
#include <iostream>
#include <iterator>
enum StreamBufferState
{
STREAMBUFFER_OK = 0,
STREAMBUFFER_EOF = 1
};
class StreamBuffer
{
std::fstream file;
std::istream istrm;
int maxBufferSize;
std::string buffer;
public:
StreamBuffer(int maxBuffSize, const std::string& filename);
~StreamBuffer();
void SetMaxBufferSize(unsigned int maxBuffSize);
StreamBufferState FullBufferWithData();
std::string GetDataBuffer();
};
#endif
StreamBuffer.cpp
#include "StreamBuffer.h"
using namespace std;
StreamBuffer::StreamBuffer(int maxBuffSize, const std::string& filename) : istrm( !filename.empty() ? file.rdbuf() : cin.rdbuf() )
{
SetMaxBufferSize(maxBuffSize);
if(!filename.empty())
{
file.open(filename.c_str(),ios::in | ios::binary);
}
else
{
std::cin>>noskipws;
}
}
StreamBuffer::~StreamBuffer()
{
file.close();
}
void StreamBuffer::SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
StreamBufferState StreamBuffer::FullBufferWithData()
{
istrm.readsome((char*)&buffer[0],maxBufferSize);
if(istrm.eof())
return STREAMBUFFER_EOF;
return STREAMBUFFER_OK;
}
std::string StreamBuffer::GetDataBuffer()
{
string buf = buffer;
return buf;
}
File is opened, but readsome() don't read buffer.
You have undefined behavior in your code, as you try read into an empty string. You need to set the size of buffer.
An unrelated logical error: In the FullBufferWithData function you will return "OK" even if there is an error reading the file.