C 조건부 전 처리기 지시문에서 문자열을 비교하는 방법
C에서 이와 같은 작업을해야합니다. 문자를 사용하는 경우에만 작동하지만 문자열이 필요합니다. 어떻게 할 수 있습니까?
#define USER "jack" // jack or queen
#if USER == "jack"
#define USER_VS "queen"
#elif USER == "queen"
#define USER_VS "jack"
#endif
전 처리기 지시문에서 가변 길이 문자열 비교를 완전히 수행하는 방법이 없다고 생각합니다. 그래도 다음을 수행 할 수 있습니다.
#define USER_JACK 1
#define USER_QUEEN 2
#define USER USER_JACK
#if USER == USER_JACK
#define USER_VS USER_QUEEN
#elif USER == USER_QUEEN
#define USER_VS USER_JACK
#endif
또는 코드를 약간 리팩토링하고 대신 C 코드를 사용할 수 있습니다.
[업데이트 : 2018.05.03]
주의 사항 : 모든 컴파일러가 동일한 방식으로 C ++ 11 사양을 구현하는 것은 아닙니다. 아래 코드는 내가 테스트 한 컴파일러에서 작동하지만 많은 주석가는 다른 컴파일러를 사용했습니다.
Shafik Yaghmour의 답변에서 인용 : 컴파일 시간에 C 문자열의 길이 계산. 이것은 정말로 constexpr입니까?
상수 표현식은 컴파일 타임에 평가된다는 보장이 없습니다. 우리는 C ++ 표준 섹션 5.19 상수 표현식 초안의 비 규범 적 인용 만 있습니다.
[...]> [참고 : 변환 중에 상수 표현식을 평가할 수 있습니다 .—end note]
그 단어 can는 세상의 모든 차이를 만듭니다.
따라서 constexpr컴파일러 작성자의 사양 해석에 따라이 (또는 모든) 답변에 대한 YMMV .
[2016.01.31 업데이트]
일부는 문자열 비교가 필요없는 목표를 달성하여 OP 의 전체 측면을 피 했기 때문에 이전 답변을 좋아하지 않았으므로 compile time string compare여기에 더 자세한 답변이 있습니다.
당신은 할 수 없습니다! C98 또는 C99에는 없습니다. C11에서도 마찬가지입니다. MACRO 조작의 양은이를 변경하지 않습니다.
에서 const-expression사용되는 정의는 #if문자열을 허용하지 않습니다.
문자를 허용하므로 문자로 제한하면 다음을 사용할 수 있습니다.
#define JACK 'J'
#define QUEEN 'Q'
#define CHOICE JACK // or QUEEN, your choice
#if 'J' == CHOICE
#define USER "jack"
#define USER_VS "queen"
#elif 'Q' == CHOICE
#define USER "queen"
#define USER_VS "jack"
#else
#define USER "anonymous1"
#define USER_VS "anonymous2"
#endif
#pragma message "USER IS " USER
#pragma message "USER_VS IS " USER_VS
할 수 있습니다! C ++ 11에서. 비교를 위해 컴파일 시간 도우미 함수를 정의한 경우.
// compares two strings in compile time constant fashion
constexpr int c_strcmp( char const* lhs, char const* rhs )
{
return (('\0' == lhs[0]) && ('\0' == rhs[0])) ? 0
: (lhs[0] != rhs[0]) ? (lhs[0] - rhs[0])
: c_strcmp( lhs+1, rhs+1 );
}
// some compilers may require ((int)lhs[0] - (int)rhs[0])
#define JACK "jack"
#define QUEEN "queen"
#define USER JACK // or QUEEN, your choice
#if 0 == c_strcmp( USER, JACK )
#define USER_VS QUEEN
#elif 0 == c_strcmp( USER, QUEEN )
#define USER_VS JACK
#else
#define USER_VS "unknown"
#endif
#pragma message "USER IS " USER
#pragma message "USER_VS IS " USER_VS
따라서 궁극적으로 USER및에 대한 최종 문자열 값을 선택하려는 목표를 달성하는 방식을 변경해야합니다 USER_VS.
C99에서는 컴파일 시간 문자열 비교를 할 수 없지만 컴파일 시간에 문자열을 선택할 수 있습니다.
컴파일 시간 스팅 비교를 수행해야하는 경우 해당 기능을 허용하는 C ++ 11 또는 최신 변형으로 변경해야합니다.
[원래 답변]
시험:
#define jack_VS queen
#define queen_VS jack
#define USER jack // jack or queen, your choice
#define USER_VS USER##_VS // jack_VS or queen_VS
// stringify usage: S(USER) or S(USER_VS) when you need the string form.
#define S(U) S_(U)
#define S_(U) #U
업데이트 : ANSI 토큰 붙여 넣기는 때때로 명확하지 않습니다. ;-디
#매크로 앞에 단일을 넣으면 베어 값 대신 해당 값의 문자열로 변경됩니다.
##두 토큰 사이 에 double을 넣으면 토큰이 단일 토큰으로 연결됩니다.
따라서 매크로 USER_VS는 설정 방법에 따라 jack_VS또는 .queen_VSUSER
캐릭터 라인 화 매크로 S(...)명명 된 매크로의 값이 문자열로 변환됩니다 있도록 매크로 간접를 사용합니다. 매크로 이름 대신.
따라서 USER##_VS이된다 jack_VS(또는 queen_VS사용자가 설정 한 방식에 따라) USER.
나중에 stringify 매크로가 ( 이 예에서) S(USER_VS)의 값으로 사용되면 해당 값 ( )을 문자열로 변환 하는 간접 단계로 전달됩니다 .USER_VSjack_VSS_(jack_VS)queen"queen"
사용자가 설정 한 경우 USER에 queen그 최종 결과는 문자열입니다 "jack".
토큰 연결에 대해서는 https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html을 참조하십시오.
토큰 문자열 변환에 대해서는 https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification을 참조하십시오.
[오타 수정을 위해 2015.02.15 업데이트 됨]
문자열 대신 숫자 값을 사용하십시오.
마지막으로 상수 JACK 또는 QUEEN을 문자열로 변환하려면 문자열 화 (및 / 또는 토큰 화) 연산자를 사용하십시오.
다음은 clang으로 나를 위해 일했습니다. 기호 매크로 값 비교로 나타나는 것을 허용합니다. #error xxx 는 컴파일러가 실제로하는 일을 보는 것입니다. 교체 고양이 와 정의를 #DEFINE 고양이 (A, B) B A ## 휴식 것들.
#define cat(a,...) cat_impl(a, __VA_ARGS__)
#define cat_impl(a,...) a ## __VA_ARGS__
#define xUSER_jack 0
#define xUSER_queen 1
#define USER_VAL cat(xUSER_,USER)
#define USER jack // jack or queen
#if USER_VAL==xUSER_jack
#error USER=jack
#define USER_VS "queen"
#elif USER_VAL==xUSER_queen
#error USER=queen
#define USER_VS "jack"
#endif
As already stated above, the ISO-C11 preprocessor does not support string comparison. However, the problem of assigning a macro with the “opposite value” can be solved with “token pasting” and “table access”. Jesse’s simple concatenate/stringify macro-solution fails with gcc 5.4.0 because the stringization is done before the evaluation of the concatenation (conforming to ISO C11). However, it can be fixed:
#define P_(user) user ## _VS
#define VS(user) P_ (user)
#define S(U) S_(U)
#define S_(U) #U
#define jack_VS queen
#define queen_VS jack
S (VS (jack))
S (jack)
S (VS (queen))
S (queen)
#define USER jack // jack or queen, your choice
#define USER_VS USER##_VS // jack_VS or queen_VS
S (USER)
S (USER_VS)
The first line (macro P_()) adds one indirection to let the next line (macro VS()) finish the concatenation before the stringization (see Why do I need double layer of indirection for macros?). The stringization macros (S() and S_()) are from Jesse.
The table (macros jack_VS and queen_VS) which is much easier to maintain than the if-then-else construction of the OP is from Jesse.
Finally, the next four-line block invokes the function-style macros. The last four-line block is from Jesse’s answer.
Storing the code in foo.c and invoking the preprocessor gcc -nostdinc -E foo.c yields:
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo.c"
# 9 "foo.c"
"queen"
"jack"
"jack"
"queen"
"jack"
"USER_VS"
The output is as expected. The last line shows that the USER_VS macro is not expanded before stringization.
The answere by Patrick and by Jesse Chisholm made me do the following:
#define QUEEN 'Q'
#define JACK 'J'
#define CHECK_QUEEN(s) (s==QUEEN)
#define CHECK_JACK(s) (s==JACK)
#define USER 'Q'
[... later on in code ...]
#if CHECK_QUEEN(USER)
compile_queen_func();
#elif CHECK_JACK(USER)
compile_jack_func();
#elif
#error "unknown user"
#endif
Instead of #define USER 'Q' #define USER QUEEN should also work but was not tested also works and might be easier to handle.
EDIT: According to the comment of @Jean-François Fabre I adapted my answer.
If your strings are compile time constants (as in your case) you can use the following trick:
#define USER_JACK strcmp(USER, "jack")
#define USER_QUEEN strcmp(USER, "queen")
#if $USER_JACK == 0
#define USER_VS USER_QUEEN
#elif USER_QUEEN == 0
#define USER_VS USER_JACK
#endif
The compiler can tell the result of the strcmp in advance and will replace the strcmp with its result, thus giving you a #define that can be compared with preprocessor directives. I don't know if there's any variance between compilers/dependance on compiler options, but it worked for me on GCC 4.7.2.
EDIT: upon further investigation, it look like this is a toolchain extension, not GCC extension, so take that into consideration...
#define USER_IS(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9)\
ch0==c0 && ch1==c1 && ch2==c2 && ch3==c3 && ch4==c4 && ch5==c5 && ch6==c6 && ch7==c7 ;
#define ch0 'j'
#define ch1 'a'
#define ch2 'c'
#define ch3 'k'
#if USER_IS('j','a','c','k',0,0,0,0)
#define USER_VS "queen"
#elif USER_IS('q','u','e','e','n',0,0,0)
#define USER_VS "jack"
#endif
it basically a fixed length static char array initialized manually instead of a variable length static char array initialized automatically always ending with a terminating null char
It's simple I think you can just say
#define NAME JACK
#if NAME == queen
'Program Club' 카테고리의 다른 글
| Holo.Light 테마를 사용하고 pre-honeycomb 장치에서 'Light'로 돌아가는 방법은 무엇입니까? (0) | 2020.10.13 |
|---|---|
| 우편 배달부와의 Websocket 연결 (0) | 2020.10.12 |
| 원자 운영 비용 (0) | 2020.10.12 |
| Android Play 스토어에서 데이터 가져 오기 (0) | 2020.10.12 |
| CreateProcess 오류 = 206, main () 메서드를 실행할 때 파일 이름 또는 확장자가 너무 깁니다. (0) | 2020.10.12 |