"undeclared identifier" error in simple macro expansion - visual-c++

I have a very simple macro that I use for shorthand when declaring exceptions. When in debug mode it adds the current file and line number.
I'm in the process of modifying my code to support unicode, and suddenly I'm getting "undeclared identifier" errors whenever my macro is used. I'm probably missing something really simple, as the macro itself is rather simple. Can anyone tell what the issue is?
Here's the macro declaration:
#ifdef _DEBUG
#define EXCEPTION(msg, mm) Exception(msg, mm, _T(__FILE__), _T(__LINE__))
#else
#define EXCEPTION(msg, mm) Exception(msg, mm)
#endif
I don't think it's needed, but just in case, here's the Exception constructor declaration:
Exception(LPCTSTR msg, BOOL manageMsg = FALSE, LPCTSTR f = NULL, int l = -1);
When compiling in release mode I don't get any errors, but when in debug mode I do, so it's something with the __FILE__ and __LINE__ bits, but I can't figure out what the actual issue is.

This wasn't exactly the same problem I had, but I am posting the solution to my issue here because I came across this question during my investigations.
If you encounter this error message with a multiline macro, turn on visible whitespace in your editor. You may have whitespace after the '\' continuation character at the end of the line:
#define FOO_BAR(aFoo) \
FOO_BASE(aFoo, "bar")
The space at the end causes the parser to parse the first line of the macro definition as complete (FOO_BAR expands to '\ '), and the second line is interpreted as a function declaration, hence "undeclared identifier 'aFoo'").

The __LINE__ macro evaluates to an integer. The _T macro puts an L on the front of strings to make them Unicode strings. It's meant to be followed by an opening double quotation mark, like L"file.cpp". But in your case, it's followed by the integer literal that __LINE__ expands to. You're getting something like this: L23. Get rid of the second _T call.
#define EXCEPTION(msg, mm) Exception(msg, mm, _T(__FILE__), __LINE__)
This might have been more easily diagnosed if you had included the name of the identifier that the compiler didn't recognize. Compilers usually include that information in their error messages.

Related

Indentation appears in the output string when broken it over multiple lines

I have large f-string, and I am braking it (see below), for code readability.
but when I print (print to file, it is String.IO object) the string I get the indentation leading each new line (except the first), and I don't want that (my IDE is vscode).
When taking the same f-string below, to the python shell interpreter (REPL), the output string is proper.
def foo():
ml.append(f"""
#define {ip}_{mtype}_{secname}_{fieldname}_MASK (MASK({H},{L}))
#define {ip}_{mtype}_{secname}_{fieldname}_START_BIT ({fieldsb})\n""")
the output file looks like:
#define QM_MEM_CBTIRDY_LENGTH (0x40) //good line
#define QM_MEM_CBTIRDY_DATA_MASK (GENMASK(31,0)) //bad line (with indentation)
#define QM_MEM_CBTIRDY_DATA_START_BIT (0)
I have fix it by removing the indentation between each new line (but its ugly cos the strings with the same function def indentation level, and this is ugly)
def foo():
ml.append(f"""
#define {ip}_{mtype}_{secname}_{fieldname}_MASK (MASK({H},{L}))
define {ip}_{mtype}_{secname}_{fieldname}_START_BIT ({fieldsb})\n""")
how can i get rid of these indentation characters in the final string ?
Triple-quoted (multiline) strings are supposed to preserve the formatting, so that's why you're getting those identations.
You can use concatenation instead:
ml.append(f"#define {ip}_{mtype}_{secname}_{fieldname}_MASK (MASK({H},{L}))\n"
f"#define {ip}_{mtype}_{secname}_{fieldname}_START_BIT ({fieldsb})\n")
or if you still prefer multi-line strings, you can trim them in a similar way to docstrings.

Is there any easy way to replace %20 by a space in a CString?

I need to replace some %20 by spaces and got compile errors which i do not understand:
CString str = _T("foo%20bar");
str.Replace('%20',' '); // C4305 argument: truncation from 'int' to 'wchar_t'
str.Replace(_T('%20'),_T(' ')); // C4305 argument: truncation from 'int' to 'wchar_t'
str.Replace(_T("%20"),_T(" ")); // C2664 'int ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Replace(const wchar_t *,const wchar_t *)': cannot convert argument 1 from 'const char [4]' to 'wchar_t'
What is wrong?
The CString::Replace() method takes null-terminated string pointers as input, not individual characters. Your string literals need to use " instead of ', eg:
CString str = _T("foo%20bar");
str.Replace(_T("%20"), _T(" "));
Note that matches your last example, which you say is also erroring. The only way that can fail with the error message you have shown is if you have a misconfiguration in your project, where UNICODE is defined 1 but _UNICODE is not defined 2.
1: as evident by CString being mapped to CStringT<wchar_t>.
2: as evident by the compiler saying _T("%20") is a const char[] rather than a const wchar_t[].
CString uses TCHAR from the Win32 API, not _TCHAR from the C runtime library. Usually they are interchangeable, but not so in your situation. So, you need to either fix your project's configuration so that _UNICODE is also defined, or else use the Win32 TEXT() macro to match CString's use of TCHAR:
CString str = TEXT("foo%20bar");
str.Replace(TEXT("%20"), TEXT(" "));
Or, simply stop using TCHAR-based APIs altogether (TCHAR dates back to the days of Win9x/ME when Microsoft was pushing everyone to start migrating their code to Unicode), and really should not be used in modern coding if you can avoid it. Just use wchar_t strings directly instead, eg:
CStringW str = L"foo%20bar";
str.Replace(L"%20", L" ");
The last one should have worked, except that you seem to have a wide CString in a project without the UNICODE and/or _UNICODE macro defined.
In this combination, the _T() macro isn't giving you a compatible string literal. But L"whatever" will.
str.Replace(L"%20", L" ");
Notice that this does what you asked, but is not adequate for URL unescaping. You should convert all %xx sequences.
%20 may be formatted string like %d. and Replace function return replaced String and str is not replaced.
try like: str = str.Replace(_T("%%20"), _T(" "));
or
try like: str = str.Replace(_T("%20"),_T(" "));
Extra Info
If you look at this Format specification syntax: printf and wprintf functions article you will see the following clarification:
A basic conversion specification contains only the percent sign and a type character. For example, %s specifies a string conversion. To print a percent-sign character, use %%. ...

What does "?\s" mean in Elixir?

In the Elixir-documentation covering comprehensions I ran across the following example:
iex> for <<c <- " hello world ">>, c != ?\s, into: "", do: <<c>>
"helloworld"
I sort of understand the whole expression now, but I can't figure out what the "?\s" means.
I know that it somehow matches and thus filters out the spaces, but that's where my understanding ends.
Edit: I have now figured out that it resolves to 32, which is the character code of a space, but I still don't know why.
erlang has char literals denoted by a dollar sign.
Erlang/OTP 22 [erts-10.6.1] [...]
Eshell V10.6.1 (abort with ^G)
1> $\s == 32.
%%⇒ true
The same way elixir has char literals that according to the code documentation act exactly as erlang char literals:
This is exactly what Erlang does with Erlang char literals ($a).
Basically, ?\s is exactly the same as ?  (question mark followed by a space.)
# ⇓ space here
iex|1 ▶ ?\s == ?
warning: found ? followed by code point 0x20 (space), please use ?\s instead
There is nothing special with ?\s, as you might see:
for <<c <- " hello world ">>, c != ?o, into: "", do: <<c>>
#⇒ " hell wrld "
Also, ruby as well uses ?c notation for char literals:
main> ?\s == ' '
#⇒ true
? is a literal that gives you the following character's codepoint( https://elixir-lang.org/getting-started/binaries-strings-and-char-lists.html#utf-8-and-unicode). For characters that cannot be expressed literally (space is just one of them, but there are more: tab, carriage return, ...) the escaped sequence should be used instead. So ?\s gives you a codepoint for space:
iex> ?\s
32

Problems assigning char string to char array

I have already read all prior answers regarding my problem. However, I'm not a very bright coder to am unable to grasp it. Could someone please look into my problem.
I am trying to write a CSV file using entries from a 2D array. string.h has already been included in main().
void create_marks_csv(int rout[][20],float p[][20],float c[][20],int n)
{
system("cls");
char str1[100],str2[100],str3[100];
printf("\nEnter filename for routing matrix: ");
gets(str1);
printf("\n Creating %s.csv file",str1);
FILE *fp;
int i,j;
str1=strcat(str1,".csv");
str1=strcat("C:\\Users\\Neil\\Documents\\Trust CSV Logs\\",str1) ;
fp=fopen(str1,"w+");
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
fprintf(fp,"X");
else
fprintf(fp,"%d",rout[i][j]);
}
fprintf(fp,"\n");
}
fclose(fp);
printf("\nFile created: %s",str1);
system("cls");
}
The warnings and errors are as follows:
5 20 C:\Users\Neil\Documents\main.c [Warning] extra tokens at end of #include directive [enabled by default]
C:\Users\Neil\Documents\main.c In function 'create_marks_csv':
168 6 C:\Users\Neil\Documents\main.c [Error] incompatible types when assigning to type 'char[100]' from type 'char *'
169 6 C:\Users\Neil\Documents\main.c [Error] incompatible types when assigning to type 'char[100]' from type 'char *'
28 C:\Users\Neil\Documents\Makefile.win recipe for target 'main.o' failed
Every time you write str1 =, you are telling the compiler to change str1 so that it points to whatever location in memory is found on the right-hand side of the = sign. But you declared char str1[100], which means that str1, interpreted as a pointer, can only point to the start of the block of 100 characters at the location where this declaration allocated them. So it makes no sense to write str1 =.
Passing a C string constant as the first argument of strcat is likely to be a disaster, although the compiler seems not to mind. The first argument of strcat should be a character buffer big enough to hold the results of the concatenation. In order to concatenate something onto the end of a constant string, you can allocate a buffer big enough, then copy the constant string to it, then call strcat.
In general you can probably do whatever you need to do without using the return value of strcat, that is, no need to ever write strcat on the right-hand side of =.
It is advisable to use fgets instead of gets because then you can protect against the possibility that you will get too much input to fit in your allocated character buffer. If you allocate 100 characters in your largest buffer, you can only afford to accept 95 characters minus the length of the string "C:\\Users\\Neil\\Documents\\Trust CSV Logs\\". (The other 5 characters are required to hold the string ".csv" and the terminating null character).
I saw also that you declare str2 and str3 but I didn't see where you used either of them. It looks like you don't need both of them, but you might find it convenient to use str2 as the buffer for your last concatenation of strings.

What is the meaning of the following code?

What is the meaning of following code :
//Keyboard map
#define LEFT_ARROW 'P'
#define RIGHT_ARROW 'Q'
#define UP_ARROW 'K'
#define DOWN_ARROW 'L'
#define CANCEL 'F'
#define HOME 'A'
#define BLANK 'B'
#define SIGN_TOGGLE 'G'
#define KB_DECIMAL 'R'
#define KB_ZERO 'S'
#define KB_ONE 'C'
#define KB_TWO 'D'
#define KB_THREE 'E'
#define KB_FOUR 'H'
#define KB_FIVE 'I'
#define KB_SIX 'J'
#define KB_SEVEN 'M'
#define KB_EIGHT 'N'
#define KB_NINE 'O'
#define ENTER 'T'
Could anybody explain how it works and why they defined in that way?
Those are just constants. It means that the preprocessor will go through the source code and replace any instance of the word following #define with the character on the right, before compiling the source code. So if there was a line like this in the code:
char myChar = LEFT_ARROW;
the preprocesor will change that code into:
char myChar = 'P';
before compiling.
#define TOKEN REPLACEMENT is a preprocessor directive, it replaces all occurrences of TOKEN into REPLACEMENT, syntactically.
The purpose of your code snippet is to assign names to keyboard bindings, that means, if you say if (key == KB_NINE), the compiler will see if (key == 'O').
The advantage of using preprocessors correctly is not only readability: it also increases maintainability, in case the constants change.
The key definitions seems to be nonsense: for example, KB_ONE is 'C', however, this problem can be solved in a few keystrokes by modifying the constant in one place.
See also: http://en.wikipedia.org/wiki/C_preprocessor#Macro_definition_and_expansion
These are the kind of keys you'd find on the right-hand side of a keyboard. There is no standard way in the C runtime to let a program recognize these keystrokes. So there have been all kinds of non-standard extensions to fix this problem.
One scheme is to let getch() return 0 when such an extended key is pressed, the next getch() call then returns a key code for that extended key. That key code could be the original keyboard scan code. Anything is possible, you'd have to know the original keyboard vendor and CRT supplier to have a clue. Clearly it is ancient, proprietary keyboard interfaces was an excellent vendor lock-in strategy back in the neolithic days of computing.

Resources