为什么不strcpy工作?

时间:2014-05-02 00:36:09

标签: c strcpy

    char sentence2[10];

    strncpy(sentence2, second, sizeof(sentence2));  //shouldn't I specify the sizeof(source) instead of sizeof(destination)?

    sentence2[10] = '\0';                       //Is this okay since strncpy does not provide the null character.

    puts(sentence2);
//////////////////////////////////////////////////////////////

    char *pointer = first;
    for(int i =0; i < 500; i++)                 //Why does it crashes without this meaningless loop?!
    {
        printf("%c", *pointer);
        if(*pointer == '\n')
            putchar('\n');
        pointer++;
    }

所以这就是问题所在。当我运行此代码的第一部分时,程序崩溃。 但是,当我添加只在内存位置打印垃圾值的for循环时,它不会崩溃但仍然不会正确地strcpy。

其次,在使用strncpy时,我不应该指定sizeof(source)而不是sizeof(destination),因为我正在移动源的字节吗?

第三,在strncpy之后添加空终止字符是有道理的,因为我已经读过它不会自己添加空字符,但是我得到一个警告,它可能超出界限从我的pelles c IDE存储。

第四,最重要的是,为什么不简单的strcpy工作?!?!

/////////////////////////////////////////////// /////////////////////////////////////

更新:

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

void main3(void)
{
    puts("\n\n-----main3 reporting for duty!------\n");
    char *first = "Metal Gear";
    char *second = "Suikoden";
    printf("strcmp(first, first)  = %d\n", strcmp(first, first));   //returns 0 when both strings are identical.
    printf("strcmp(first, second) = %d\n", strcmp(first, second));  //returns a negative when the first differenet char is less in first string.  (M=77  S=83)
    printf("strcmp(second, first) = %d\n", strcmp(second, first));  //returns a positive when the first different char is greater in first string.(M=77  S=83)

    char sentence1[10]; 
    strcpy(sentence1, first);
    puts(sentence1);
    char sentence2[10];
    strncpy(sentence2, second, 10); //shouldn't I specify the sizeof(source) instead of sizeof(destination).
    sentence2[9] = '\0';                        //Is this okay since strncpy does not provide the null character.

    puts(sentence2);
    char *pointer = first;
    for(int i =0; i < 500; i++)                 //Why does it crashes without this nonsensical loop?!
    {
        printf("%c", *pointer);
        if(*pointer == '\n')
            putchar('\n');
        pointer++;
    }
}

这就是我自学编程的方式。我编写代码并评论我所知道的所有内容 下次我需要查找某些内容时,我只需在文件中查看自己的代码即可。在这一篇中,我正在尝试学习c。

中的字符串库

3 个答案:

答案 0 :(得分:3)

你的问题从这里开始:

char sentence1[10]; 
strcpy(sentence1, first);

first中的字符数(不包括终止空字符)为10。为sentence1分配的空间必须至少为11,以使程序以可预测的方式运行。既然你已经使用了你不应该使用的内存,那么期待任何事情都行不通。

您可以通过更改

来解决此问题
char sentence1[10]; 

char sentence1[N]; // where N > 10.

然而,你必须问问自己。你想通过在错误边缘的堆栈上分配内存来实现什么目标?您是否想要了解事情在错误/正确的边界上的表现?如果第二个问题的答案是肯定的,那么希望你能从中吸取教训。如果没有,我希望你学会了如何分配足够的内存。

答案 1 :(得分:2)

char *first = "Metal Gear";
char sentence1[10]; 
strcpy(sentence1, first);

这不起作用,因为first有11个字符:字符串中的十个字符加上空终止符。所以你需要char sentence1[11];或更多。

strncpy(sentence2, second, sizeof(sentence2));  
  

//我不应该指定sizeof(source)而不是sizeof(destination)?

没有。 strncpy的第三个参数应该是目标的大小。 strncpy函数将始终写入那么多字节。

如果你想使用strncpy,你还必须打开一个空终止符(并且必须有足够的空间用于该终结符),除非你确定strlen(second) < sizeof sentence2

一般来说,strncpy几乎不是一个好主意。如果要将以null结尾的字符串放入可能太小的缓冲区中,请使用snprintf

  

这就是我自学编程的方式。

通过反复试验学习C并不好。问题是如果你编写错误的代码,你可能永远不会知道。它似乎可以工作,然后再失败。例如,它取决于sentence1之后关于你的strcpy是否会踩到任何其他变量的脚趾的记忆内容。

从书本中学习是最好的主意。如果您没有其他任何一个,K&amp; R 2是一个不错的起点。

如果您还没有书,请查看标准功能的在线文档。您可以通过阅读他们的手册页或他们在C标准草案中的定义等来了解strcpystrncpy的所有相关内容。

答案 2 :(得分:1)

这是数组边界写入错误。指数仅为0-9

sentence2[10] = '\0';

应该是

sentence2[9] = '\0';

第二,你保护目的地免受缓冲区溢出的影响,所以指定它的大小是合适的。

编辑:

最后,在这段非常糟糕的代码中,真的不值得一提,既不与strcpy()也不是strncpy()相关,但似乎让我对@nonsensicke不满意,似乎写了非常详细和深思熟虑的帖子......有以下内容:

char *pointer = first;
for(int i =0; i < 500; i++)
{
    printf("%c", *pointer);
    if(*pointer == '\n')
        putchar('\n');
    pointer++;
}

在for循环中使用int i = 0是特定于C99的。根据您的编译器和编译器参数,它可能导致编译错误。

for(int i =0; i < 500; i++)

更好

int i = 0;
...
for(i=0;i<500;i++)

您忽略了检查printf的返回代码或表示您故意忽略它。毕竟I / O可能会失败......

printf("%c", *pointer);

更好

int n = 0;
...
n = printf("%c", *pointer);
if(n!=1) { // error! }

(void) printf("%c", *pointer);

有些人会因为你的if语句没有使用{}而找到你

if(*pointer == '\n') putchar('\n');

更好

if(*pointer == '\n') {
    putchar('\n');
}

但等等还有更多...你没有检查putchar()的回复代码... dang

更好

unsigned char c = 0x00;
...
if(*pointer == '\n') {
    c = putchar('\n');
    if(c!=*pointer) // error
}

最后,在这个令人讨厌的小循环中,你基本上像郁金香在郁金香领域一样在记忆中嬉戏,幸运的是如果你换了换行符。根据操作系统(如果你甚至有操作系统),你可能会遇到某种类型的故障,例如在你的进程空间之外,可能是外部可寻址的RAM等等。实际上提供的信息不够实际,但可能会发生。

除了对其余代码进行某种类型的详细分析之外,我的建议是完全删除它。

干杯!