Multi-line wide string constant that allows single line comments in C++ - visual-c++

This question of how to break up a (wide) string constant along multiple lines in code has been asked and answered multiple times on this platform (here, for example). I have been using the following approach to declare a static wide string in the class definition itself:
#include <Windows.h>
#include <iostream>
class Test
{
public:
static constexpr WCHAR TEST[] = L"The quick brown fox" \
L"jumped over the" \
L"lazy dog!";
/* ... */
};
int main ()
{
wprintf(Test::TEST);
return 1;
}
However, this approach does not work very well if you want to start commenting each line of your multi-line string. The only way you can achieve this is if you stick a multi-line comment in between the string and the backslash (\) like so:
class Test
{
public:
static constexpr WCHAR TEST[] = L"The quick brown fox" /* A comment */\
L"jumped over the" /* Another comment*/\
L"lazy dog!";
/* ... */
};
If you put a comment after the backslash (\), then a compiler error is raised. This means, you cannot use the traditional single line comment (//) with this method. As a matter of fact, if you put a single space after the backslash (\), then a compiler error is generated.
My question is as follows, is there a way to declare a wide string over multiple lines where you can use single line comments (//) to comment each line?
I am idling looking for something like this (similar to Java):
static constexpr ... = L"The quick brown fox" + // A little comment here...
L"jumped over the" + // A little comment there.
L"lazy dog!";
I understand things are incredibly different in Java (i.e. namely everything is an object), but I am just giving this as an example of what I am after.

Simply drop the backslashes:
static constexpr WCHAR TEST[] = L"The quick brown fox" // a comment
L"jumped over the" // another comment
L"lazy dog!"; // yet another comment
Comments are replaced by space characters in translation phase 3. Adjacent string literals are concatenated in translation phase 6.

Related

C++ override quotes

Ok, so I'm using C++ to make a library that'd help me to print lines into a console.
So, I want to override " "(quote operators) to create an std::string instead of the string literal, to make it easier for me to append other data types to that string I want to output.
I've seen this done before in the wxWidgets with their wxString, but I have no idea how I can do that myself.
Is that possible and how would I go about doing it?
I've already tried using this code, but with no luck:
class PString{
std::string operator""(const char* text, std::size_t len) {
return std::string(text, len);
}
};
I get this error:
error: expected suffix identifier
std::string operator""(const char* text, std::size_t len) {
^~
which, I'd assume, want me to add a suffix after the "", but I don't want that. I want to only use ""(quotes).
Thanks!
You can't use "" without defining a suffix. "" is a const char* by itself either with a prefix (like L"", u"", U"", u8"", R"()") or followed by suffixes like (""s, ""sv, ...) which can be overloaded.
The way that wxString works is set and implicit constructor wxString::wxString(const char*); so that when you pass "some string" into a function it is essentially the same as wxString("some string").
Overriding operator ""X yields string literals as the other answer.

I used cin to get a string input as shown below in the code and it works fine. Is it alright?

#include<iostream>
#include<stdio>
using namespace std;
int main()
{ int n;
char s[15];
cin>>n;
cin>>s;
cout<<n*2<<"\n";
cout<<s;
return 0;
}
I tried with gets and fgets function but they don't work just after cin..
I'm kind of confused on what you are asking here, but I have noticed something here that can be fixed.
Yes the code you have compiles and it works. However, it could be improved.
When prompted to input something to your char array, you'll notice that it will not accept whitespaces. So if I input, Jon Smith, the output will only be Jon and the rest of the string input is cut off. To fix this, you will need to make a call the the getline() function.
The documentation of getline() states:
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n'..)
This will allow you to get whitespaces from the input and put the entire input back into a string.
If you add this function call to your code where the second input prompt lies and you were to run the code, you would notice that you will only get prompted once and then the program would finish running before the second prompt appears to be executed. This is because getline() does not ignore leading whitespace characters and it stops reading any further because the cin>> before it is seen as a newline character.
To make getline() work with cin>>, you must use cin.ignore() before the call to getline(). Below is some code that I wrote to make this adjustment:
// Example program
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
string s; //using string allows us to use getline()
cout<<"Enter a number: "; //Let user know they are being prompt for number
cin>>n;
cin.ignore(); //ignore the leading newline
cout<<"Enter a string: "; //let user know being prompt for string
getline (cin,s);
cout<<n*2<<"\n";
cout<<s;
return 0;
}
Again, the code you have works and compiles. I'm not sure if my solution is the answer you are hoping to get but I hope that you are able to find this useful! Cheers!

How to set carriage return location or equivalent?

I am looking for a way to set where the carriage return, returns to or an equivalent way to do so.
For example I have a line like this:
^ denotes cursor location
myshell>cat file.txt
^
After carriage return it should look like this.
myshell>cat file.txt
^
You're probably after what's collectively called ANSI escape sequences. Its hard to search for if you really have no idea what you're after.
This tiny example saves/restores cursor position:
#include <stdio.h>
int main(int argc, char**argv)
{
char cmd_buf[100];
cmd_buf[0]=0;
while(strncmp(cmd_buf, "quit", 4))
{
printf("mypromt>\033[s <-Cursor should go there\033[u");
fflush(stdout);
fgets(cmd_buf, sizeof(cmd_buf), stdin);
printf("\nYou entered: %s\n", cmd_buf);
}
}
Note that in terminator, gnome-terminal and xterm on Ubuntu, this "magically" supports CTRL+U as-is, but not CTRL+A or CTRL+E.
There are many, many more sequences available. The wikipedia page is probably the simplest reference to get you started.
Update: Also, unless you're doing this as a learning exercise (which I get the impression Benjamin is), to build an interactive shell, you should probably use one of the two well established libraries for shell-style line editing, namely:
readline (GPLv3, but far more popular)
editline (BSD licensed, closest "second place")
They are the libraries that provide the emacs-style (typical default) and vi-style keybindings and history features we all know and love from bash, python, lua, perl, node, etc, etc.
For positioning on the screen, termios is of limited use (the ioctl's dealing with screensize are not in POSIX), and unless you want to assume a lot about the terminal characteristics, control characters and escape sequences have their limitations.
You can do what's asked in curses using the filter function to tell the library you want to use just the current line of the display. As written, the question is puzzling since it does not mention any output other than the current line. But for example (this is exactly what was asked):
#include <curses.h>
int
main(void)
{
int ch, y, x;
filter();
initscr();
cbreak();
addstr("myshell>");
getyx(stdscr, y, x);
while ((ch = getch()) != ERR) {
if (ch == '\n')
move(y, x);
}
endwin();
return 0;
}
However, a usable program would do more than that. There's an example of the filter() function in ncurses-examples, which you may find useful for reading. A screenshot:

qt "resource" string

I am wanting to have a place where i can store all the strings used in my applicaton, so i can modify them in one place and not all the places. Something like a resource file, where i can put a label on the strings and just call the label.
I am not aware of anything offered by QT for this, so would I just need to create a header file with all those strings and include it everywhere I need it? What is the appropriate way to do this and could you offer a small example?
Thanks!!
I haven't used it yet, but I think, that the Qt Internationalization would allow you to do something like this, since one of it's options is to take all strings out of the application code so they can be replaced by translations. Even if you don't want to use any other features of this module, it would allow you to solve your problem. Replacing a string for a label would look like this:
QLabel *label = new QLabel(tr("Password:"));
The tr() function is already part of the Qt classes and you get a few more functions and macros for free that help to search and replace strings.
The strings to be replaced can then be managed with QtLinguist.
You can find a more detailed explanation here: Internationalization with Qt
In the old days[1], when using Windows resources, people have been using:
// in your project_strings.h file
#define STRING_PASSWORD 1
...
// resources project.rc
#include "project_strings.h"
STRINGTABLE
BEGIN
STRING_PASSWORD "Password:"
...
END
// in some other file
#include "project_strings.h"
CString str(STRING_PASSWORD);
The CString knew about windows resources (ugly dependency) and could go and read the string password. The #define is definitively very ugly in modern C++, but resources would not understand a static const variable or an inline function.
The easiest way to replicate this in a somewhat similar way is to use a header file with string declarations and then reference those strings anywhere you need them.
// in your project_strings.h
namespace MyProjectStrings {
const char *password;
...
}
// the project_strings.cpp for the strings
#include "project_strings.h"
namespace MyProjectStrings {
const char *password = "Password:";
...
}
// some random user who needs that string
#include "project_strings.h"
std::string password(MyProjectStrings::password);
Now all your strings are in project_strings.cpp and you cannot as easily translate them with tr()... but you could transform all those strings declarations with functions:
// in your project_strings.h
namespace MyProjectStrings {
const char *password(); //[2]
...
}
// the project_strings.cpp for the strings
#include "project_strings.h"
namespace MyProjectStrings {
const char *password() { return QObject::tr("Password:"); }
...
}
// some random user who needs that string
#include "project_strings.h"
std::string password(MyProjectStrings::password()); //[3]
And Voilà! You have a single long table of all your strings in one place and translatable.
[1] Many people still use that scheme!
[2] The function could return std::string to 100% prevent modifying the original.
[3] In this last example the string reference uses () since it's a function call.

LPCSTR, TCHAR, String

I am use next type of strings:
LPCSTR, TCHAR, String i want to convert:
from TCHAR to LPCSTR
from String to char
I convert from TCHAR to LPCSTR by that code:
RunPath = TEXT("C:\\1");
LPCSTR Path = (LPCSTR)RunPath;
From String to char i convert by that code:
SaveFileDialog^ saveFileDialog1 = gcnew SaveFileDialog;
saveFileDialog1->Title = "Сохранение файла-настроек";
saveFileDialog1->Filter = "bck files (*.bck)|*.bck";
saveFileDialog1->RestoreDirectory = true;
pin_ptr<const wchar_t> wch = TEXT("");
if ( saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK ) {
wch = PtrToStringChars(saveFileDialog1->FileName);
} else return;
ofstream os(wch, ios::binary);
My problem is that when i set "Configuration Properties -> General
Character Set in "Use Multi-Byte Character Set" the first part of code work correctly. But the second part of code return error C2440. When i set "Configuration Properties -> General
Character Set in "Use Unicode" the second part of code work correctly. But the first part of code return the only first character from TCHAR to LPCSTR.
I'd suggest you need to be using Unicode the whole way through.
LPCSTR is a "Long Pointer to a C-type String". That's typically not what you want when you're dealing with .Net methods. The char type in .Net is 16bits wide.
You also should not use the TEXT("") macro unless you're planning multiple builds using various character encodings. Try wrapping all your string literals with the _W("") macro instead and a pure unicode build if you can.
See if that helps.
PS. std::wstring is very handy in your scenario.
EDIT
You see only one character because the string is now unicode but you cast it as a regular string. Many or most of the Unicode characters in the ASCII range has their same number as in ASCII but have the second of their 2 bytes set to zero. So when a unicode string is read as a C-string you only see the first character because C-strings are null ( zero ) terminated. The easy ( and wrong ) way to deal with this is to use std:wstring to cast as a std:string then pull the C-String out of that. This is not the safe approach because Unicode has a much large character space then your standard encoding.

Resources