2
const char *SITE_NAME = "test";
char SITE_ROOT[19];
sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME);

I can't figure out why I'm getting an error of:

error: expected ‘)’ before string constant

Basically I just want to concatenate the variable SITE_NAME onto SITE_ROOT. The error is on the sprintf line. Any ideas?

UPDATE: So the code works if it is inside main(). I had it outside of main() so that I could use those variables inside of functions.

4

3 回答 3

4

The error looks like it might not be shown in the code but the sprintf should be:

sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME);

EDIT:

Here is my complete test code if that helps at all:

#include <string.h>
#include <stdio.h>

int main()
{
    const char *SITE_NAME = "test";
    char SITE_ROOT[19];
    sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME);

    printf( "%s\n", SITE_ROOT ) ;

    return 0 ;
}
于 2013-05-26T02:57:27.187 回答
2

As has been pointed out, the direct problem is that you're trying to call sprintf from outside a function.

You mentioned that you are setting the strings this way because you're using SITE_NAME by itself in addition to concatenating it with the path and you want to only have to change it in one place. This is a good goal, known in some circles as "don't repeat yourself" (often abbreviated DRY). However, even if the code worked (say, because you moved the sprintf call into main), you haven't really achieved your goal due to the following line:

char SITE_ROOT[19];

You are declaring a fixed length array exactly big enough to hold "/var/www/html/test", which is just asking for a buffer overflow. When you change SITE_NAME from "test" to, for example, "someRealSiteName", you'll very probably overwrite something else when you concatenate, causing unpredictable results. So you have to manually recalculate the length of the final string and update the array size (which would be easy to get wrong, say by forgetting to add 1 for the null terminator) every time you change SITE_NAME.

You could, of course, limit the length of SITE_NAME and size SITE_ROOT to hold the longest possible path, but it'd be an artificial limit and you might end up wasting space. Furthermore, you'd still have to verify the length isn't exceeded at run-time (or use a function that will ignore extra characters).

Instead, you could dynamically set the size of SITE_ROOT like so:

#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

const char SITE_PATH[] = "/var/www/html/";
const char SITE_NAME[] = "someRealSiteName";
char *SITE_ROOT = NULL; // just making this explicit, would be set to 0 anyway

int main(void)
{
    size_t siteRootLength = strlen(SITE_PATH) + strlen(SITE_NAME);

    SITE_ROOT = malloc(siteRootLength + 1); //don't forget to account for the terminating '\0'

    strcpy(SITE_ROOT, SITE_PATH);
    strcat(SITE_ROOT, SITE_NAME);

    printf("%s\n", SITE_NAME):
    printf("%s\n", SITE_PATH):
    printf("%s\n", SITE_ROOT):

    return 0;
}

This solution is okay, but has some drawbacks:

  • SITE_ROOT can't be a const pointer , so both the string and the pointer itself could be accidentally changed
  • Site path and name will each be in memory twice (though it sounds like you're okay with that)
  • Concatenation is being done at run-time when it could be done at compile-time
  • Code is longer and more complex than necessary for such a simple task
  • Risk that SITE_ROOT is used before it has the correct value (or is even a valid pointer/string!) in some other initialization code or another thread.

I feel something like the following is better:

#include <stdio.h>

#define SITE_PATH_MACRO "/var/www/html/"
#define SITE_NAME_MACRO "someRealSiteName"

// the preprocessor will merge the two string literals into one
#define SITE_ROOT_MACRO SITE_PATH_MACRO SITE_NAME_MACRO

// you could do without some or all of these if you don't need them
// (or are willing to use the macros directly)
const char SITE_PATH[] = SITE_PATH_MACRO;
const char SITE_NAME[] = SITE_NAME_MACRO;
const char SITE_ROOT[] = SITE_ROOT_MACRO;

int main(void)
{
    printf("%s\n", SITE_NAME);
    printf("%s\n", SITE_PATH);
    printf("%s\n", SITE_ROOT);

    return 0;
}
于 2013-05-30T15:20:30.083 回答
1

Since this is a pretty straightforward case, you can simply initialize the string and then concatenate onto it. You might want to add checks to ensure you don't go beyond you string's boundaries though.

strcpy(SITE_ROOT, "/var/www/html/"); 
strcat(SITE_ROOT, SITE_NAME);
于 2013-05-26T03:15:29.623 回答