Below is a function returning a pointer to string, and this function is polymorphism, which means it could return any classmate's name.
const char* get_classmate_name(void);
Here is a task that asks you to put/get classmate's information into/from in info.txt
under each classmate's folder, for example:
/good_class/Anderson/info.txt/
/good_class/Cindy/info.txt/
/good_class/Lily/info.txt/
I attempted to define those attributes with define macro:
#define CLASS_PATH "/good_class"
#define CLASSMATE_PATH CLASS_PATH##"/"get_classmate_name() //wrong
#define CLASSMATE_INFO_PATH CLASSMATE_PATH"/info.txt"
Obviously, the second macro is wrong because it's not allowed to concatenate symbolic constant, in this case CLASS_PATH
, with const char*
by using ##
operator.
I want program to be simple such like
static bool folder_is_found(const char* folder_path);
int main(void)
{
if ((!folder_is_found(CLASS_PATH)) || (!folder_is_found(CLASSMATE_PATH)))
{
reutrun -1;
}
const char* classmate_height = get_classmate_height(CLASSMATE_INFO_PATH);
printf("classmate's height is :%s", classmate_height);
return 0;
}
How to correctly define CLASSMATE_PATH
?
CodePudding user response:
You cannot define CLASSMATE_PATH
as a macro, because the classmate's name (obtained via get_classmate_name()
) is only known at run-time, and not at compile-time.
A possible function you may use in order to concatenate multiple strings at once is snprintf()
:
char* get_classmate_path(void) {
const size_t max_path_size = 200;
char* res = malloc(max_path_size);
if (res == NULL) {
return NULL;
}
int bytes = snprintf(res, max_path_size, "%s/%s", CLASS_PATH, get_classmate_name());
if (bytes < 0 || (size_t) bytes >= max_path_size) {
free(res);
return NULL;
}
return res;
}
int main(void) {
printf("Classmate path: %s\n", get_classmate_path());
// POSSIBLE OUTPUT: Classmate path: /good_class/Anderson
}
It is trivial, then, to concatenate even more strings together:
char* get_classmate_info_path(void) {
const size_t max_path_size = 200;
char* res = malloc(max_path_size);
if (res == NULL) {
return NULL;
}
int bytes = snprintf(res, max_path_size, "%s/%s/info.txt", CLASS_PATH, get_classmate_name());
if (bytes < 0 || (size_t) bytes >= max_path_size) {
free(res);
return NULL;
}
return res;
}
NOTE: the previous examples make use of dynamic memory allocation (via malloc()
); you may want to have a detailed look at how dynamic memory works in C (for instance, you should call free()
after you're done using the result of get_classmate_path()
, but that's out of answer's scope).
NOTE 2: the previous functions (get_classmate_path()
and get_classmate_info_path()
) may return NULL
in case of errors.
CodePudding user response:
Macros are not functions even if sometimes they look similar.
- Macros are evaluated before the C code compilation starts. The preprocessor does not know anything about C language.
##
concatenated tokens in macro during the preprocessing stage (ie before C code compilation).##
does something completely different than a concatenation of the adjacent string literals (both have to be string literals and concatenation happens compile time, not run time).
You need to use functions instead of macros to achieve what you want.