参数中char *和strncpy值之间的差异

时间:2013-04-13 04:50:34

标签: c++

我有函数,可以保存参数中的值。我必须实现两种方式,接受输入 - 作为char*,然后通过strncpy

即:a . Add("123456/7890", "John", "Doe", "2000-01-01", "Main street", "Seattle");

它可以正常工作,直到我使用strncpy:

bool status;
char lID[12], lDate[12], lName[50], lSurname[50], lStreet[50], lCity[50];  

strncpy(lID, "123456/7890", sizeof ( lID));
strncpy(lName, "John", sizeof ( lName));
strncpy(lSurname, "Doe", sizeof ( lSurname));
strncpy(lDate, "2000-01-01", sizeof ( lDate));
strncpy(lStreet, "Main street", sizeof ( lStreet));
strncpy(lCity, "Seattle", sizeof ( lCity));
status = c . Add(lID, lName, lSurname, lDate, lStreet, lCity);
//is true 

strncpy(lID, "987654/3210", sizeof ( lID));
strncpy(lName, "Freddy", sizeof ( lName));
strncpy(lSurname, "Kruger", sizeof ( lSurname));
strncpy(lDate, "2001-02-03", sizeof ( lDate));
strncpy(lStreet, "Elm street", sizeof ( lStreet));
strncpy(lCity, "Sacramento", sizeof ( lCity));
// notice, that I don't even save it at this point

strncpy(lID, "123456/7890", sizeof ( lID));
strncpy(lDate, "2002-12-05", sizeof ( lDate));
strncpy(lStreet, "Sunset boulevard", sizeof ( lStreet));
strncpy(lCity, "Los Angeles", sizeof ( lCity));
status = c . Resettle(lID, lDate, lStreet, lCity);

status = c . Print(cout, "123456/7890");
//is true

此时我想打印出ID 123456/7890的值......所以姓名:John,姓:Doe等。 Neverthless它打印出值,保存为最后一个:

123456/7890 Freddy Kruger
2002-12-05 Sunset boulevard Los Angeles
2002-12-05 Sunset boulevard Los Angeles

我的Add声明为:

  bool Add(const char * id,
        const char * name,
        const char * surname,
        const char * date,
        const char * street,
        const char * city);

Resettle函数与Add类似,它只是不带名字和姓氏参数。 所有值都保存到char **数组。

你能否告诉我,如何处理这种情况,能够正确接受两种输入?

Ps:对于char*输入整个程序工作正常,所以我不指望那里有任何错误.. Pps:请不要建议我使用字符串或我在这里不使用的任何其他结构 - 我对进口非常有限,因此我使用char *和其他东西......

3 个答案:

答案 0 :(得分:3)

我认为你不应该在这里使用sizeof。 strncpy需要字符串的长度(要从目标字符串复制到源字符串的字符数)。

sizeof是指针的大小(例如sizrof(IID)=地址大小,我的系统是4)。

我认为你需要strlen()。此外,这需要在源指针上调用,而不是在目标指针上调用。

strncpy(lID, "987654/3210", strlen ("987654/3210"));

确保IID足够复制字符串,否则缓冲区溢出可能会有问题

阅读char * strncpy ( char * destination, const char * source, size_t num );

  

从字符串中复制字符   将源的前num个字符复制到目标。如果在复制num个字符之前找到源C字符串的结尾(由空字符表示),则使用零填充目标,直到已经写入总数为num个字符。

感谢@JonathanLeffler :( strlen()意味着数据不会以空值终止。这很糟糕。至少复制strlen()+ 1个字节来获取空终结符

注意:如果source长于num,则在目标的末尾不会隐式附加空字符(因此,在这种情况下,目标可能不是空终止的C字符串)。

另请阅读:size_t strlen ( const char * str );

答案 1 :(得分:2)

问题不在strncpy()操作中。它是你未向我们展示的材料:

c.Add()
c.Resettle()
c.Print()

其中一个或多个有问题,但由于我们还没有看到它们,我们无法帮助您调试它们。


strncpy()

的演示

在对voodoogiantanswer的评论中讨论了strncpy()的行为。这是一个演示:

strncpy(target, "string", strlen("string"));

不会终止输出:

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

int main(void)
{
    char buffer[32];

    memset(buffer, 'X', sizeof(buffer));
    printf("Before: %.*s\n", (int)sizeof(buffer), buffer);
    strncpy(buffer, "123456/7890", strlen("123456/7890"));
    printf("After:  %.*s\n", (int)sizeof(buffer), buffer);
    return(0);
}

输出:

Before: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
After:  123456/7890XXXXXXXXXXXXXXXXXXXXX

(是的,我很清楚memset()没有空终止缓冲区;对于这个例子它不需要,因为打印是小心的。)

答案 2 :(得分:0)

因为我们不知道lID等人的数据类型。因此sizeof很难发表评论。此外,为什么不使用STL的string容器

相关问题