2013-05-26 122 views
2
const char *SITE_NAME = "test"; 
char SITE_ROOT[19]; 
sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME); 

我想不通,为什么我得到的错误:串连变量到另一个变量

error: expected ‘)’ before string constant

基本上我只是想连接变量SITE_NAME到SITE_ROOT。错误在sprintf行。有任何想法吗?

更新:因此,如果代码在main()内部,代码将起作用。我把它放在main()之外,这样我就可以在函数内部使用这些变量。

+0

哪条线是给你的错误? – 2013-05-26 02:57:00

+0

@JackManey - 我更新了我的帖子......错误在sprintf行。 – user983223

+0

意想不到的宏可能会搞砸了。检查预处理器输出。 ('cc -E file.c'用于类似unix的编译器;如果您需要更多帮助,请告诉您使用的编译器) –

回答

2

正如已经指出的,直接的问题是你试图从函数外部调用sprintf

你提到你是这样设置字符串的,因为除了将它与路径连接在一起之外,你自己也使用SITE_NAME,并且你只需要在一个地方改变它。这是一个很好的目标,在一些圈子中被称为"don't repeat yourself" (often abbreviated DRY)。然而,即使代码的工作(比如,因为你的移动电话sprintf到主),你还没有真正实现你的目标,由于以下行:

char SITE_ROOT[19]; 

您声明固定长度正好阵大足以容纳"/var/www/html/test",这只是要求缓冲区溢出。当您将SITE_NAME"test"更改为例如"someRealSiteName"时,连接时很可能会覆盖其他内容,从而导致不可预知的结果。因此,每次更改SITE_NAME时,必须手动重新计算最终字符串的长度并更新数组大小(这很容易出错,比如忘记为空终止符添加1)。

当然,您可以限制SITE_NAME的长度和尺寸SITE_ROOT以保持尽可能长的路径,但这是人为的限制,最终可能会浪费空间。此外,您仍然必须验证在运行时长度没有超出(或使用忽略多余字符的函数)。

相反,你可以动态设置的SITE_ROOT大小,像这样:

#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; 
} 

该解决方案是好的,但也有一些缺点:

  • SITE_ROOT不能是const指针,所以字符串和指针本身都可能被意外更改
  • 网站路径和名称将分别在内存中两次(虽然听起来好像你没有问题)
  • 串联是在运行时正在做时,它可以在编译时完成
  • 代码为
  • 风险是SITE_ROOT使用它具有正确的值之前超过必要的时间和更复杂的这样一个简单的任务(或甚至是一个有效的指针/字符串!)在其他一些初始化代码或另一个线程。

我觉得像下面是更好:

#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; 
} 
+0

非常感谢。你的优点/缺点非常有帮助。 – user983223

+0

@ user983223我很高兴你发现它有帮助。我应该指出,字符串文字的合并不仅与宏一起工作,它恰好在那里最有用。所以你可以用'const char SITE_ROOT [] = SITE_PATH_MACRO SITE_NAME_MACRO'去掉一个宏或者'const char SITE_ROOT [] =“/ var/www/html /”SITE_NAME_MACRO'去掉两个宏(如果你没有需要'SITE_PATH'变量) – jerry

4

错误看起来可能不是在代码中显示,但sprintf应该是:

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

编辑:

这里是我完整的测试代码有没有什么帮助所有:

#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 ; 
} 
+0

我已将SITE_NAME前的&符号取消,但仍然出现错误。我添加了&符号,因为我认为SITE_NAME被定义为一个指针并且调用我需要放置一个符号的指针,不是? – user983223

+0

@ user983223这很奇怪,我根本无法重现那个错误。 '%s'格式说明符需要一个c风格字符串,它是一个'char *',它是'SITE_NAME'的字符。如果有帮助,我会用我的完整测试代码更新我的文章。 –

+0

@ user983223然后请发布[SSCCE](http://sscce.org)。 – jerry

1

由于这是一个非常简单的情况,您可以简单地初始化字符串,然后连接到它。您可能想要添加检查以确保您不会超越字符串的界限。

strcpy(SITE_ROOT, "/var/www/html/"); 
strcat(SITE_ROOT, SITE_NAME); 
+1

如果你打算把'SITE_ROOT'作为一个固定长度的缓冲区(它似乎是你暗示的),你可以用'char SITE_ROOT [19] =“/ var/www/html /”'直接初始化它,然后跳过'strcpy'调用。 – jerry

相关问题