Visual C++ debug output displaying ???? for non Latin (Cyrillic) characters - visual-studio-2012

There is some Windows/VS setting that will let debug output in VS correctly output non Latin characters. We are interested in Cyrillic letters. What is that setting?

Too brief question. However, a solution based on this answer could help:
#include "stdafx.h"
#include <iostream>
#include <io.h>
#include <fcntl.h>
int wmain(int argc, wchar_t* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout
<< L"Unicode test -- Ελληνικά -- čeština -- русский язык -- Türkçesi"
<< std::endl;
for (int i = 1; i < argc; ++i)
{
std::wcout << L"param " << i << L": " << argv[i] << std::endl;
}
}
Verified using Visual Studio 2013:
==> ".\so36212399\Debug\so36212399.exe" qwertz ςερτυθ ěščřžý йцукен ğüşıöç
Unicode test -- Ελληνικά -- čeština -- русский язык -- Türkçesi
param 1: qwertz
param 2: ςερτυθ
param 3: ěščřžý
param 4: йцукен
param 5: ğüşıöç
==>

Related

C++ string concatenation in the Windows Subsystem for Linux (WSL) is deleting first string

I need help understanding what is wrong with my code or system. For some reason, when compiled and ran in WSL(Windows Subsystem for Linux), the following code generates a wrong result. When ran directly in the windows command terminal, it correctly generates the final output as HNDPNV and in WSL generates PNV. The airports file is simply a series of 50 lines, with 3 letters per line. g++ version is 7.5.0 in ubuntu 18.04 WSL and g++ windows version is 9.2.0.
compilation flags are: g++ -std=c++17 -Wall -Wextra -o test test.cpp
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
using namespace std;
int main() {
string airport_designations[50];
string air_companies_designations[20];
ifstream airports;
ifstream aircompanies;
string name = "apple";
string name2 = "orange";
airports.open("Airports.txt");
for (int i = 0; i < 50; i++){
getline(airports, airport_designations[i]);
cout << airport_designations[i] << endl;
}
airports.close();
aircompanies.open("Companies.txt");
for (int i = 0; i < 20; i++){
getline(aircompanies, air_companies_designations[i]);
cout << air_companies_designations[i] << endl;
}
aircompanies.close();
name = airport_designations[4];
cout << name << endl;
name += airport_designations[8];
cout << name << endl;
}
The line break on windows is \r\n,
On Linux \n.
To get a consistent conclusion, you need to replace all \r\ n in the Airports.txt file with \n.

calling std::system with parameter containing space in double quotes

I need to call a linux std::system call with parameter than contain string with spaces. In order to process it correctly using argc / argv I want to pass it with double quotes.
std::string cmdline = "myprogram -d \"I am a sting\"" ;
if I cout this string I get good results.
When I send it to std::system(cmdline)
and look at ps -ef I get
myprogram -d I am a string
How can I keep "I am a string" as a single parameter for myprogram ?
No problem:
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ cat test.cpp
#include <iostream>
#include <string>
#include <cstdlib>
int main()
{
std::string cmdline = "./see \"I am a string\"";
std::cout << cmdline << std::endl;
std::system(cmdline.c_str());
}
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ cat see.cpp
#include <iostream>
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
std::cout << argv[i] << std::endl;
}
}
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ g++ -std=c++11 test.cpp -o test
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ g++ -std=c++11 see.cpp -o see
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ ./test
./see "I am a string"
./see
I am a string
(tested in Cygwin)

Where are POSIX message queues located (Linux)?

man 7 mq_overview says that the POSIX "...message queues on the system can be viewed and manipulated using the commands usually used for files (e.g., ls(1) and rm(1))."
For example I was able to read using a mqd_t as a file descriptor as follows:
#include <iostream>
#include <fcntl.h>
#include <mqueue.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
std::cout << "Usage: mqgetinfo </mq_name>\n";
exit(1);
}
mqd_t mqd = mq_open(argv[1], O_RDONLY);
struct mq_attr attr;
mq_getattr(mqd, &attr);
std::cout << argv[1] << " attributes:"
<< "\nflag: " << attr.mq_flags
<< "\nMax # of msgs: " << attr.mq_maxmsg
<< "\nMax msg size: " << attr.mq_msgsize
<< "\nmsgs now in queue: " << attr.mq_curmsgs << '\n';
// Get the queue size in bytes, and any notification info:
char buf[1024];
int n = read(mqd, buf, 1023);
buf[n] = '\0';
std::cout << "\nFile /dev/mqueue" << argv[1] << ":\n"
<< buf << '\n';
mq_close(mqd);
}
Running this on msg queue /myq when it contains 5 msgs, 549 bytes gives:
$ g++ mqgetinfo.cc -o mqgetinfo -lrt
$ ./mqgetinfo /myq
/myq attributes:
flag: 0
Max # of msgs: 10
Max msg size: 8192
msgs now in queue: 5
File /dev/mqueue/myq:
QSIZE:549 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
$
Also:
$ !cat
cat /dev/mqueue/myq
QSIZE:549 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
So the file /dev/mqueue/myq has some info associated with the msg queue.
My question is: Where is the queue itself, i.e., where are the 549 bytes? I'm guessing they are in some list-type data structure internal to the kernel, but I don't see this mentioned in the man pages etc, and wondering how to find out about that..
Since the internal handling of message queues are implementation specific (not part of the standard, as it only specifies the programming interface and behaviour), I recommend you to have a look into the linux kernel source file ipc/mqueue.c and pay special attention to mqueue_create() and msg_insert() functions, as it's a good place to get started if you want to understand how message queues are implemented in the linux kernel.

Execute a command in another terminal via /dev/pts

I have a terminal that uses STDIN 3 (/proc/xxxx/fd/0 -> /dev/pts/3)
So if (in another terminal) I do:
echo 'do_something_command' > /dev/pts/3
The command is shown in my first (pts/3) terminal, but the command is not executed. And if (in this terminal pts/3) I'm in a program waiting for some data from stdin, the data is written on screen but the program does not capture it from stdin.
What I want to do is execute the command "do_something_command" and not only show it.
Can someone explain this behavior to me? How do I achieve my intention?
I completely get what you are asking. You can achieve this by writing and executing a small piece of code in C yourself. This should give you some idea.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
void print_help(char *prog_name) {
printf("Usage: %s [-n] DEVNAME COMMAND\n", prog_name);
printf("Usage: '-n' is an optional argument if you want to push a new line at the end of the text\n");
printf("Usage: Will require 'sudo' to run if the executable is not setuid root\n");
exit(1);
}
int main (int argc, char *argv[]) {
char *cmd, *nl = "\n";
int i, fd;
int devno, commandno, newline;
int mem_len;
devno = 1; commandno = 2; newline = 0;
if (argc < 3) {
print_help(argv[0]);
}
if (argc > 3 && argv[1][0] == '-' && argv[1][1] == 'n') {
devno = 2; commandno = 3; newline=1;
} else if (argc > 3 && argv[1][0] == '-' && argv[1][1] != 'n') {
printf("Invalid Option\n");
print_help(argv[0]);
}
fd = open(argv[devno],O_RDWR);
if(fd == -1) {
perror("open DEVICE");
exit(1);
}
mem_len = 0;
for (i = commandno; i < argc; i++) {
mem_len += strlen(argv[i]) + 2;
if (i > commandno) {
cmd = (char *)realloc((void *)cmd, mem_len);
} else { // i == commandno
cmd = (char *)malloc(mem_len);
}
strcat(cmd, argv[i]);
strcat(cmd, " ");
}
if (newline == 0)
usleep(225000);
for (i = 0; cmd[i]; i++)
ioctl (fd, TIOCSTI, cmd+i);
if (newline == 1)
ioctl (fd, TIOCSTI, nl);
close(fd);
free((void *)cmd);
exit (0);
}
Compile and execute it with sudo permissions. For example, if you want to execute a command on /dev/pts/3, then simply do a sudo ./a.out -n /dev/pts/3 whoami, runs a whoami on /dev/pts/3.
This code was completely taken from this page.
You seem to use the wrong quotes around the command.
Either remove the quotes and the echo command, or use echo and back-ticks (`).
Try:
echo `date` > /dev/pts/3
or just
date > /dev/pts/3
Note that whatever runs on /dev/pts/3 wouldn't be able to read what pops up "from behind".

libiconv on windows/linux issue

I need to perform character set conversion using iconv on windows. In this case this is transliteration to remove accents, etc. but the issue I am facing is the same for most any target encoding. Here is my Program:
#include "stdafx.h"
#include <vector>
#include <fstream>
#include <iconv.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
std::ifstream ifs("test.txt", std::ios::binary | std::ios::ate);
std::ifstream::pos_type pos = ifs.tellg();
char * pIn = new char[(int)pos + 1];
ifs.seekg(0, std::ios::beg);
ifs.read(pIn, pos);
pIn[pos] = 0;
size_t srclen = strlen(pIn);
char dst[1000];
char * pOut = (char*)dst;
size_t dstlen = 1000;
iconv_t conv = iconv_open("UTF-8", "ASCII//TRANSLIT");
std::cout << srclen << " " << dstlen << std::endl;
auto ret = iconv(conv, (const char**)&pIn, &srclen, &pOut, &dstlen);
std::cout << (int)ret << " " << errno << " " << srclen << " " << dstlen << std::endl;
iconv_close(conv);
return 0;
}
The test.txt file looks like this (UTF-8 w/o BOM):
qwe
Tøyenbekken
Zażółć gęślą jaźń
ZAŻÓŁĆ GĘŚLĄ JAŹŃ
Unfortunately the iconv call stops processing at the first non ASCII character and program outputs:
75 1000
-1 0 69 994
The return value of -1 indicates error, but errno is set to 0 which gives no clue as to what may be wrong.
Any idea what am I doing wrong here? To make the matter more interesting here is the output of iconv.exe located in the same dir as the libiconv2.dll file:
> iconv -f utf-8 -t ascii//translit test.txt
qwe
Toyenbekken
Zaz'ol'c ge'sla ja'z'n
ZAZ'OL'C GE'SLA JA'Z'N
which is ok.
Update after testing on Linux:
The command line version of iconv does not work - it outputs some garbage to the console (in place of non ascii characters).
Using my own code it outputs error code of 84 (which is I guess EILSEQ - Illegal byte sequence) after processing ascii characters.
Any ideas what may be wrong here?
The issue was that I wanted to convert from UTF-8 to ASCII and opened the converter this way:
iconv_t conv = iconv_open("UTF-8", "ASCII//TRANSLIT");
whereas it should be done this way:
iconv_t conv = iconv_open("ASCII//TRANSLIT", "UTF-8");
(argument order). Still not sure why I did not get proper error code.

Resources