How can we write WCHAR and CHAR to a wofstream at the same time?like this:
wofstream << L"汉字" << "汉字"
Here is something for testing. I can only "wofstream<<WCHAR" or only "wofstream<<CHAR", but can't "wofstream<<WCHAR<<CHAR" both at the same time.
#include <iostream>
#include <fstream>
#include <locale>
int main() {
std::wofstream wof2;
wof2.open(L"2.txt", std::wofstream::app);
wof2 << "\nCHAR 汉";
wof2.flush();
wof2 << L"\nWCHAR 汉";
wof2.close();
const char * tmp = setlocale(LC_ALL, "");
std::cout << tmp << std::endl;
std::locale::global(std::locale(""));
wof2.open(L"2.txt", std::wofstream::app);
wof2.imbue(std::locale());
wof2 << L"\nWCHAR after imbue";
wof2.flush();
wof2 << L"\nWCHAR 汉";
wof2.flush();
wof2 << "\nCHAR汉";
wof2.flush();
return 0;
}
We can see that at the console
Chinese (Simplified)_China.936
But In the 2.txt, I see that
CHAR 汉
WCHAR
WCHAR after imbue
WCHAR 汉
CHAR
Related
I'm trying to make my own programming language and compiler for it. While creating lexical analyzer i have troubles with this function. Also i included stdlib.h and stdio.h. Platform what i use is m1 mac and vscode with gcc
There is code:
#define _CRT_SECURE_NO_WARNINGS
#include "Log.h"
namespace Log
{
LOG getlog(wchar_t logfile[])
{
try
{
LOG struc;
struc.stream = new (std::nothrow) std::ofstream;
if (!struc.stream)
throw ERROR_THROW(112);
struc.stream->open(logfile);
if (!(*(struc.stream)).is_open())
throw ERROR_THROW(112);
wcscpy(struc.logfile, logfile);
return struc;
}
catch (Error::ERROR e)
{
Error::ErrorDisplay(e);
}
}
void WriteLine(LOG log, char *c, ...)
{
for (char **c_ptr = &c; **c_ptr; c_ptr++)
{
*log.stream << *c_ptr;
}
}
void WriteLine(LOG log, wchar_t *c, ...)
{
unsigned lineLength = 0;
char *line = nullptr;
unsigned int n = 0;
for (wchar_t **c_ptr = &c; **c_ptr; c_ptr++)
{
lineLength = wcslen(*c_ptr);
line = new char[lineLength + 1];
wcstombs_s(&n, line, lineLength + 1u, *c_ptr, lineLength + 1u);
*log.stream << line;
delete[] line;
}
}
void WriteLog(LOG log)
{
std::string line = "----Протокол------ ";
time_t result = time(NULL);
char str[26];
ctime_s(str, sizeof str, &result);
for (int i = 0; i < 26; i++)
line += str[i];
*log.stream << line;
}
void WriteParm(LOG log, Parm::PARM parm)
{
char in_text[PARM_MAX_SIZE];
char out_text[PARM_MAX_SIZE];
char log_text[PARM_MAX_SIZE];
wcstombs(in_text, parm.in, PARM_MAX_SIZE);
wcstombs(out_text, parm.out, PARM_MAX_SIZE);
wcstombs(log_text, parm.log, PARM_MAX_SIZE);
*log.stream << "---- Параметры ---- \n-in: " << in_text
<< "\n-out: " << out_text
<< "\n-log: " << log_text;
}
void WriteIn(LOG log, In::IN in)
{
*log.stream << "\n----Исходные данные------\nКол-во символов: " << (in.size < 0 ? 0 : in.size) << std::endl
<< "Проигнорировано: " << (in.ignor < 0 ? 0 : in.ignor) << std::endl
<< "Кол-во строк: " << (in.lines < 0 ? 0 : in.lines) << std::endl;
}
void WriteError(LOG log, Error::ERROR error)
{
*log.stream << "Ошибка " << error.id << ": " << error.message << ", Строка " << error.inext.line << ", Позиция " << error.inext.col << std::endl;
}
void Close(LOG log)
{
(*log.stream).close();
delete log.stream;
}
}
And header file:
#pragma once
#include <fstream>
#include <iostream>
#include <cwchar>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include "In.h"
#include "Parm.h"
#include "Error.h"
namespace Log
{
struct LOG
{
wchar_t logfile[PARM_MAX_SIZE];
std::ofstream *stream;
};
static const LOG INITLOG{L"", NULL};
LOG getlog(wchar_t logfile[]);
void WriteLine(LOG log, char *c, ...);
void WriteLine(LOG log, wchar_t *c, ...);
void WriteLog(LOG log);
void WriteParm(LOG log, Parm::PARM parm);
void WriteIn(LOG log, In::IN in);
void WriteError(LOG log, Error::ERROR error);
void Close(LOG log);
}
I tried to change include path and change versions of c++, std and compilers
I am trying to create a program which copy itself while it is running to new location without keeping the orignal file location . once it is copied I got the file without extension , but how can I overcome this ?
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szFilepath[MAX_PATH];
TCHAR szFilename[MAX_PATH];
TCHAR szDestpath[MAX_PATH];
/* Get the current executable's full path */
GetModuleFileName(NULL, szFilepath, MAX_PATH);
std::wcout << "filepath: " << szFilepath << std::endl;
/* Extract just the name */
GetFileTitle(szFilepath, szFilename, MAX_PATH);
std::wcout << "filename: " << szFilename << std::endl;
//Set the destination folder path
_tcscpy(szDestpath, L"D:\\");
//Set the destination file path
_tcscat(szDestpath, szFilename);
std::wcout << "dest path: " << szDestpath << std::endl;
// copys the file of your '.exe'
if (!CopyFile(szFilepath, szDestpath, FALSE)) {
std::cout << "couldnt copy the file";
}
else {
std::cout << "copied";
}
return 0;
}
Per the documentation for GetFileTitle():
GetFileTitle returns the string that the system would use to display the file name to the user. The display name includes an extension only if that is the user's preference for displaying file names. This means that the returned string may not accurately identify the file if it is used in calls to file system functions.
You should be using a more suitable function to get the actual filename, such as PathFindFileName():
#include <windows.h>
#include <shlwapi.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR szFilepath[MAX_PATH];
LPWSTR lpszFilename;
WCHAR szDestpath[MAX_PATH];
/* Get the current executable's full path */
GetModuleFileNameW(NULL, szFilepath, MAX_PATH);
std::wcout << L"filepath: " << szFilepath << std::endl;
/* Extract just the name */
lpszFilename = PathFindFileNameW(szFilepath);
std::wcout << L"filename: " << lpszFilename << std::endl;
/* Set the destination folder path and file name */
PathCombineW(szDestpath, L"D:\\", lpszFilename);
std::wcout << L"dest path: " << szDestpath << std::endl;
// copys the file of your '.exe'
if (!CopyFileW(szFilepath, szDestpath, FALSE)) {
std::wcout << L"couldnt copy the file";
}
else {
std::wcout << L"copied";
}
return 0;
}
Or, you could simply parse the filename yourself using normal C++ string operations, eg:
#include <windows.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR szFilepath[MAX_PATH];
std::wstring wFilepath;
std::wstring wFilename;
std::wstring wDestpath;
/* Get the current executable's full path */
wFilepath = std::wstring(szFilepath, GetModuleFileNameW(NULL, szFilepath, MAX_PATH));
std::wcout << L"filepath: " << wFilepath << std::endl;
/* Extract just the name */
wFilename = wFilepath.substr(wFilepath.find_last_of(L"\\/")+1);
std::wcout << L"filename: " << wFilename << std::endl;
/* Set the destination folder path and file name */
wDestpath = L"D:\\" + wFilename;
std::wcout << L"dest path: " << wDestpath << std::endl;
// copys the file of your '.exe'
if (!CopyFileW(wFilepath.c_str(), wDestpath.c_str(), FALSE)) {
std::wcout << L"couldnt copy the file";
}
else {
std::wcout << L"copied";
}
return 0;
}
I passed a structure pointer to a function. What I need is to get the string "connection refused"(return from ssh_get_error()) in the main function.
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
using namespace std;
typedef struct rtns {
bool state;
char* desc;
} rtns;
int connect_host(rtns *con_host) {
const char* desc;
char desc2[1000];
ssh_session my_ssh_session;
int rc;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK) {
(*con_host).state = false;
desc = ssh_get_error(my_ssh_session);
strcpy(desc2, ssh_get_error(my_ssh_session));
(*con_host).desc = strdup(desc2);
cout << "from connect_host function->" <<con_host->desc << "\n";
} else {
(*con_host).state = true;
}
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
int main() {
rtns con_host;
rtns *p = (rtns*) malloc(sizeof(struct rtns));
p = (rtns*) malloc(20);
connect_host(&con_host);
cout << "from main function->" << *(con_host.desc) << "\n\n";
}
Output-
from connect_host function->Connection refused
from main function->C
The problem is that i am only getting one character "C" in the main function. I have some idea that I am doing memory allocation wrong but i have no idea how to do it correctly. I also tried to shift the malloc allocation in con_host function but it didn't work either.
Think about what you are printing. You pass to the stream a char, not a char *:
cout << "from main function->" << *(con_host.desc) << "\n\n";
// *(con_host.desc) = *(char *) = char
// Above is a simplification but you get the point.
So long as con_host.desc is a null terminated c string you can print it like this:
cout << "from main function->" << con_host.desc << "\n\n";
Here is a live example.
It's not memory allocation error. It's caused by the output statement. Change to
cout << "from main function->" << con_host.desc << "\n\n";
I made this dll file that tries to check if a file exists. But even if I manually create the file, my dll still can't find it.
My dll retrieves the process id of the running program and looks for a file that is named after the pid.
Can anyone please tell me what I'm missing :(
Code:
#include <Windows.h>
#include <winbase.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int clientpid = GetCurrentProcessId();
ifstream clientfile;
string clientpids, clientfilepath;
VOID LoadDLL() {
AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "Debug Start" << std::endl;
std::ostringstream ostr;
ostr << clientpid;
clientpids = ostr.str();
ostr.str("");
TCHAR tempcvar[MAX_PATH];
GetSystemDirectory(tempcvar, MAX_PATH);
ostr << tempcvar << "\\" << clientpids << ".nfo" << std::endl;
clientfilepath = ostr.str();
//clientfile.c_str()
ostr.str("");
std::cout << "Start search for: " << clientfilepath << std::endl;
FOREVER {
clientfile.open(clientfilepath,ios::in);
if(clientfile.good()) {
std::cout << "Exists!" << std::endl;
}
Sleep(10);
};
}
Supposing you are working with UNICODE
I think the problems goes in the following line:
ostr << tempcvar << "\\" << clientpids << ".nfo" << std::endl; The tempcvar is a tchar, and maybe you are working with unicode, so it means tempcvar is a widechar.
The result that you get inserting tempcvar in ostr is not what you are expecting (You are mixing multibyte with widechar too). A solution to this problem is converting tempcvar into a multi byte string (const char* or char*...)
Look at this example based on your code (Look at the convertion between tchar to multibyte char)
VOID LoadDLL() {
AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "Debug Start" << std::endl;
std::ostringstream ostr;
ostr << clientpid;
clientpids = ostr.str();
ostr.str("");
TCHAR tempcvar[MAX_PATH];
GetSystemDirectory(tempcvar, MAX_PATH);
// Convertion between tchar in unicode (wide char) and multibyte
wchar_t * tempcvar_widechar = (wchar_t*)tempcvar;
char* to_convert;
int bytes_to_store = WideCharToMultiByte(CP_ACP,
0,
tempcvar_widechar,
-1,NULL,0,NULL,NULL);
to_convert = new char[bytes_to_store];
WideCharToMultiByte(CP_ACP,
0,
tempcvar_widechar,
-1,to_convert,bytes_to_store,NULL,NULL);
// Using char* to_convert that is the tempcvar converted to multibyte
ostr << to_convert << "\\" << clientpids << ".nfo" << std::endl;
clientfilepath = ostr.str();
//clientfile.c_str()
ostr.str("");
std::cout << "Start search for: " << clientfilepath << std::endl;
FOREVER {
clientfile.open(clientfilepath,ios::in);
if(clientfile.good()) {
std::cout << "Exists!" << std::endl;
}
Sleep(10);
};
}
You can search more about the wide string to multibyte string convertion if this example does not works to you.
Check if you are working with Unicode, if you are, maybe this is your problem.
If you are not working with unicode, the problem in your code can be opening the file.
Hope it helps!
I am trying a reasonably simple program to test binary input/output. I am basically writing a file with a header (string) and some data (doubles). The code is as follows:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
typedef std::ostream_iterator<double> oi_t;
typedef std::istream_iterator<double> ii_t;
std::ofstream ofs("data.bin", std::ios::in);
//-If file doesn't exist, create a new one now
if(!ofs) {
ofs.open("data.bin", std::ios::out|std::ios::binary|std::ios::app);
}
else {
ofs.close();
ofs.open("data.bin", std::ios::out|std::ios::binary|std::ios::app);
}
//-Write a header consisting of length of grid subdomain and its name
///*
const std::string grid = "Header";
unsigned int olen = grid.size();
ofs.write(reinterpret_cast<const char*>(&olen), sizeof(olen));
ofs.write(grid.c_str(), olen);
//*/
//-Now write the data
///*
std::vector<double> data_out;
//std::vector<std::pair<int, int> > cell_ids;
for(int i=0; i<100; ++i) {
data_out.push_back(5.0*double(i) + 100.0);
}
ofs << std::setprecision(4);
std::copy(data_out.begin(), data_out.end(), oi_t(ofs, " "));
//*/
ofs.close();
//-Now read the binary file; first header then data
std::ifstream ifs("data.bin", std::ios::binary);
///*
unsigned int ilen;
ifs.read(reinterpret_cast<char*>(&ilen), sizeof(ilen));
std::string header;
if(ilen > 0) {
char* buf = new char[ilen];
ifs.read(buf,ilen);
header.append(buf,ilen);
delete[] buf;
}
std::cout << "Read header: " << header << "\n";
//*/
///*
std::vector<double> data_in;
ii_t ii(ifs);
std::copy(ii, ii_t(), std::back_inserter(data_in));
std::cout << "Read data size: " << data_in.size() << "\n";
//*/
ifs.close();
//-Check the result
///*
for(int i=0; i < data_out.size(); ++i) {
std::cout << "Testing input/output element #" << i << " : "
<< data_out[i] << " " << data_in[i] << "\n";
}
std::cout << "Element sizes: " << data_out.size() << " " << data_in.size() <<
"\n";
//*/
return 0;
}
The problem is that when I try to write and read (and then print) both the header and the data it fails (I confirmed that it doesn't read the data then, but displays the header correctly). But when I comment out one of the write sections (header and/or data), it displays that part correctly indicating the read worked. I am sure I am not doing the read properly. Perhaps I am missing the usage of seekg somewhere.
The code runs fine for me. However you never check if the file is successfully opened for writing, so it could be silently failing on your system. After you open ofs you should add
if (!ofs) {
std::cout << "Could not open file for writing" << std::endl;
return 1;
}
And the same thing after you open ifs
if (!ifs) {
std::cout << "Could not open file for reading" << std::endl;
return 1;
}
Or something along those lines. Also I do not understand why you check if the file exists first since you do the same whether it exists or not.
This should work
#include <iostream>
using std::cout;
using std::cerr;
using std::cin;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cstdint>
int main() {
ifstream fin;
fin.open("input.dat", std::ios::binary | std::ios::in);
if (!fin) {
cerr << "Cannot open file " << "input.dat" << endl;
exit(1);
}
uint8_t input_byte;
while (fin >> input_byte) {
cout << "got byte " << input_byte << endl;
}
return 0;
}