如何获得strcpy目标字符串足够大?

时间:2015-07-17 04:36:30

标签: c string strcpy

经过几年的缺席,我已经恢复了C编码的乐趣。

我给自己做了一个练习,使用fgets()安全地将文本从标准输入复制到字符串,然后复制到字符串足够大,即只有足够的容量才能保存没有。我实际输入的字符,最终是从头开始制作列表,堆栈等,换句话说,用指针播放。

我已经把这个 kludge 气味的唯一方法告诉了我,因为我在控制流的后期定义了strcpy()的目标字符串变量。是否有更优雅/动态的方式来做到这一点?

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

#define MAXLENGTH 20

int main(int argc, char *argv[]) {

    char message[MAXLENGTH];

    printf("Enter a string: \n");
    fgets(message, MAXLENGTH, stdin);

    /* various tests here, omitted for brevity */

    char destinationString[strlen(message)];

    /*
     *    Just testing to prove that
     *    the strlen() of the destination
     *    string is LESS than MAXLENGTH
     */
    printf("Here's the strlen() of destinationString: %lu\n", strlen(destinationString));
    printf("Here's the sizeof() destinationString: %lu,\n" sizeof(destinationString));
    printf("Here's the contents of the copy: %s", destinationString);

    return 0;
}

2 个答案:

答案 0 :(得分:3)

您当然可以使用malloc动态执行此操作。

考虑这样的事情:

int main(int argc, char *argv[]) {
    char *destinationString;
    /* ... */

    /* Don't forget to allocate one extra byte for the termination character */
    destinationString = malloc(strlen(message) + 1);

    if (!destinationString)
        return -1;

    strcpy(destinationString, message);
    /* Note: Normally, you should probably use strncpy to avoid overflow
       but here, we're sure that there's enough space so strcpy is acceptable */

    /* ... */

    free(destinationString); /* When you're done using it */

    /* ... */
}

我也在注释中指出了这一点,但是为了重新迭代,你实际上需要在目标字符串缓冲区中分配strlen(message) + 1个字节,否则它会溢出。额外的字符是将空终止字符存储在C字符串的末尾。

答案 1 :(得分:0)

代码有很多选择。这是2:

  1. malloc()以及之后的free()正确大小的记忆由@tangrs同样回答。请注意,sizeof() destinationString将是指针的大小。

    size_t size = strlen(message) + 1;
    char *destinationString = malloc(size);
    memcpy(destinationString, message, size);
    
  2. 使用可变长度数组VLA,可在C99中使用,也可选择在C11中使用。

  3. 使用代码清理的VLA方法

    #include <string.h>
    #define MAXLENGTH 20
    
    int main(int argc, char *argv[]) {
        char message[MAXLENGTH];
    
        printf("Enter a string: \n");
        if (fgets(message, sizeof message, stdin) == NULL) { 
          return -1;
        }
    
        // Use type `size_t`
        size_t size = strlen(message) + 1;
        char destinationString[size];
        memcpy(destinationString, message, size);
    
        // Notice "%zu"
        // `sizeof destinationString` is the size of an array
        printf("Here's the strlen() of destinationString: %zu\n", strlen(destinationString));
        printf("Here's the sizeof() destinationString: %zu,\n" sizeof destinationString);
        printf("Here's the contents of the copy: \"%s\"", destinationString);
        return 0;
    }
    

    输入"Hello!" 输入

    Here's the strlen() of destinationString: 8
    Here's the sizeof() destinationString: 9,
    Here's the contents of the copy: "Hello!
    "
    

    在我的系统上,输入以"\r\n"结束。要删除那些潜在的讨厌字符的缓冲区,请使用:

    fgets(message, sizeof message, stdin);
    buffer[strcspn(message, "\r\n")] = '\0';
    size_t size = strlen(message) + 1;
    ...