将变量连接到另一个变量

时间:2013-05-26 02:53:23

标签: c

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

我无法弄清楚为什么我会收到错误:

  

错误:预期')'字符串常量

之前

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

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

3 个答案:

答案 0 :(得分: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 ;
}

答案 1 :(得分:2)

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

您提到您正在以这种方式设置字符串,因为除了将其与路径连接之外,您还单独使用SITE_NAME,并且您只需要在一个位置更改它。这是一个很好的目标,在某些圈子中称为"don't repeat yourself" (often abbreviated DRY)。但是,即使代码有效(例如,因为您将sprintf调用移至main),由于以下行,您还没有真正实现目标:

char SITE_ROOT[19];

您声明一个固定长度的数组,其大小足以容纳"/var/www/html/test",这只是要求缓冲区溢出。当您将SITE_NAME"test"更改为"someRealSiteName"时,您很可能会在连接时覆盖其他内容,从而导致无法预测的结果。因此,每次更改SITE_NAME时,必须手动重新计算最终字符串的长度并更新数组大小(这很容易出错,比如忘记为null终止符添加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;
}

答案 2 :(得分:1)

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

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