How to concatenate number to string in macro? - inno-setup

I want to concatinate a version number to a string in inno-setup preprocessor macros. I tried to use the stringer trick (used in c++ macros) like this:
#define stringer_helper(arg) #arg
#define stringer(arg) stringer_helper(arg)
#define version 1
#define myapp "lala " + stringer(version)
but get the error:
Illegal character in input file: '#' (0x23)
How is it possible to append a number define to a string define?

You can use the Str function to typecast your integer variable:
#define MyString "Text"
#define MyInteger 666
#define MyVariable MyString + Str(MyInteger)

Related

Initializing c++ string with integer and chars

#include <iostream>
#include <string>
using namespace std;
int main() {
string str {5, 'c'};
cout << str; // "\005c"
}
Output: c
With gdb, it confirms that str contains "\005c" with
str[0] = '\005'
str[1] = 'c'
Why str[0] is not being printed in output console?
Used c++ version: c++11
ASCII 5 represents a signal intended to trigger a response at the receiving end. It is not visible on the console.
Reference: http://ascii.cl/
For example: try 65 instead of 5, you will see 'A'.
The ASCII number 5 is non printable. ASCII table
ASCII representation of 5 which is 53 is printable.
string str {53, 'c'};
cout << str; // 5c
Since ASCII value of 5 is 53.
So, you can try this way:
#include <iostream>
#include <string>
using namespace std;
int main() {
string str {53, 'c'};
cout << str; // "\005c"
}

Adding two strings together in the preprocessor

I am currently writing a header to make handling my external libs easier.
Here is the minimal code:
#pragma once
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define EXTERNAL_PATH STR(C:/C++ Libraries/)
#define LUA_PATH EXTERNAL_PATH STR(lua 5.3.4/)
#define LUA_INCLUDE LUA_PATH STR(include/)
So basically, I include this header and write something like
#include LUA_INCLUDE (add this two strings) "lua.hpp"
How can I link two strings in the preprocessor together ?
Are you looking for ##? And don't stringify (quote) macro params too early because then there is no way back.
Example:
#define MY_QUOTE(a) #a
#define CONCAT_QUOTE(a,b) MY_QUOTE(a##b)
#define CONCAT(a,b) a##b
// this works OK
#include CONCAT(<iostrea, m>)
// this doesn't as iostream should be just in <> rather than "<>"
#include CONCAT_QUOTE(<iostrea, m>)

Parsing a string with varying number of whitespace characters in C

I'm pretty new to C, and trying to write a function that will parse a string such as:
"This (5 spaces here) is (1 space
here) a (2 spaces here) string."
The function header would have a pointer to the string passed in such as:
bool Class::Parse( unsigned char* string )
In the end I'd like to parse each word regardless of the number of spaces between words, and store the words in a dynamic array.
Forgive the silly questions...
But what would be the most efficient way to do this if I am iterating over each character? Is that how strings are stored? So if I was to start iterating with:
while ( (*string) != '\0' ) {
--print *string here--
}
Would that be printing out
T
h
i... etc?
Thank you very much for any help you can provide.
from http://www.cplusplus.com/reference/clibrary/cstring/strtok/
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-"); /* split the string on these delimiters into "tokens" */
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-"); /* split the string on these delimiters into "tokens" */
}
return 0;
}
Splitting string "- This, a sample string." into tokens:
This
a
sample
string
First of all, C does not have classes, so in a C program you would probably define your function with a prototype more like one of the following:
char ** my_prog_parse(char * string) {
/* (returns a malloc'd array of pointers into the original string, which has had
* \0 added throughout ) */
char ** my_prog_parse(const char * string) {
/* (returns a malloc'd NULL-terminated array of pointers to malloc'd strings) */
void my_prog_parse(const char * string, char buf, size_t bufsiz,
char ** strings, size_t nstrings)
/* builds a NULL-terminated array of pointers into buf, all memory
provided by caller) */
However, it is perfectly possible to use C-style strings in C++...
You could write your loop as
while (*string) { ... ; string++; }
and it will compile to exactly the same assembler on a modern optimizing compiler. yes, that is a correct way to iterate through a C-style string.
Take a look at the functions strtok, strchr, strstr, and strspn... one of them may help you build a solution.
I wouldn't do any non-trivial parsing in C, it's too laborious, the language is not suitable for that. But if you mean C++, and it looks like you do, since you wrote Class::Parse, then writing recursive descent parsers is pretty easy, and you don't need to reinvent the wheel. You can take Spirit for example, or AXE, if you compiler supports C++0x. For example, your parser in AXE can be written in few lines:
// assuming you have 0-terminated string
bool Class::Parse(const char* str)
{
auto space = r_lit(' ');
auto string_rule = "This" & r_many(space, 5) & space & 'a' & r_many(space, 2)
& "string" & r_end();
return string_rule(str, str + strlen(str)).matched;
}

cant convert parameter from char[#] to LPWSTR

When I compile this code in Visual C++, I got the below error. Can help me solve this issue..
DWORD nBufferLength = MAX_PATH;
char szCurrentDirectory[MAX_PATH + 1];
GetCurrentDirectory(nBufferLength, szCurrentDirectory);
szCurrentDirectory[MAX_PATH +1 ] = '\0';
Error message:
Error 5 error C2664: 'GetCurrentDirectoryW' : cannot convert parameter 2 from 'char [261]' to 'LPWSTR' c:\car.cpp
Your program is configured to be compiled as unicode. Thats why GetCurrentDirectory is GetCurrentDirectoryW, which expects a LPWSTR (wchar_t*).
GetCurrentDirectoryW expects a wchar_t instead of char array. You can do this using TCHAR, which - like GetCurrentDirectory - depends on the unicode setting and always represents the appropriate character type.
Don't forget to prepend your '\0' with an L in order to make the char literal unicode, too!
It seems you have define UNICODE, _UNICODE compiler flags. In that case, you need to change the type of szCurrentDirectory from char to TCHAR.
Headers:
#include <iostream>
#include <fstream>
#include <direct.h>
#include <string.h>
#include <windows.h> //not sure
Function to get current directory:
std::string getCurrentDirectoryOnWindows()
{
const unsigned long maxDir = 260;
wchar_t currentDir[maxDir];
GetCurrentDirectory(maxDir, currentDir);
std::wstring ws(currentDir);
std::string current_dir(ws.begin(), ws.end());
return std::string(current_dir);
}
To call function:
std::string path = getCurrentDirectoryOnWindows(); //Output like: C:\Users\NameUser\Documents\Programming\MFC Program 5
To make dir (Folder) in current directory:
std::string FolderName = "NewFolder";
std::string Dir1 = getCurrentDirectoryOnWindows() + "\\" + FolderName;
_mkdir(Dir1.c_str());
This works for me in MFC C++.

C99 Macro to build a quoted string literal after evaluation

I'm developing an embedded application in C99, and the project contains some integer constants defined like:
#define LEVEL1 0x0000
#define LEVEL2 (LEVEL1 + 1)
It has since become useful to keep track of these values for logging purposes, so I would like to use a macro to create a string literal from the evaluated versions of the above. For example:
strncpy(str, STRING(LEVEL2), len);
would ideally evaluate to
strncpy(str, "0x0001", len);
or even
strncpy(str, "0001", len);
Using a two-stage macro with the # operator (as suggested by this question) almost works. It evaluates to
strncpy(str, "(LEVEL1 + 1)", len);
I would like to avoid the use of a run-time function - hence my attempt at a macro solution. Suggestions?
Since the pre-processor stringizer is a massive pain, you need to add a level of indirection both when creating version numbers and when stringizing:
#define STRING1(s) #s
#define STRING(s) STRING1(s)
#define LEVEL(x) x
#define LEVEL1 LEVEL(1)
#define LEVEL2 LEVEL(2)
printf(STRING(LEVEL2));
//2
You cannot do this because the preprocessor knows nothing about the C language so it cannot to evaluation.
I see two options to get the desired result:
Manual evaluation
Write your levels exactly as you want them to appear and use a single stringizer operator:
#define LEVEL1 0x0000
#define LEVEL2 0x0001
#define STRING(x) # x
strncpy(str, STRING(LEVEL2), len);
A disadvantage is that this is error prone and might clash with local coding conventions.
Runtime evaluation
Use one of the string format functions sprintf or snprintf.
#define LEVEL1 0x0000
#define LEVEL2 0x0001
char level[7];
snprintf(level, sizeof level, "%#06x", LEVEL2);
strncpy(str, level, len);
This has the runtime overhead you wanted to avoid.

Resources