0

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?

7
  • Why do you need the ; in your #define Commented Sep 15, 2021 at 8:05
  • The ; will cause an error here - (!folder_is_found(CLASSMATE_PATH))) Commented Sep 15, 2021 at 8:07
  • Thanks. I corrected this typo! Commented Sep 15, 2021 at 8:08
  • 1
    You cannot use a macro to concatenate a string literal with the result of a function call. A preprocessor macro is text replacement at compile time. (simplified) So the result of your macro will be the string literal followed by the function name which is a syntax error. What you could do is to define a C function that does the concatenation and use this function in the macro definition. Commented Sep 15, 2021 at 8:16
  • 1
    char buffer[PATH_MAX]; snprintf(buffer, sizeof(buffer), "/good_class/%s/info.txt", get_classmate_name()) might be what you are looking for... Or print all three parts into format string "%s/%s/%s". Commented Sep 15, 2021 at 8:23

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Pedantic point: if (bytes < 0 || (size_t) bytes >= max_path_size) { --> if (bytes < 0 || (unsigned) bytes >= max_path_size) {. size_t may narrow the int value in rare cases where range of int exceeds SIZE_MAX. (unsigned) bytes never loses info when bytes >= 0.
1

Macros are not functions even if sometimes they look similar.

  1. Macros are evaluated before the C code compilation starts. The preprocessor does not know anything about C language.
  2. ## 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.