C中String复制函数strcpy中的分段错误

时间:2017-02-19 09:22:57

标签: c

#include<stdio.h>
#include<string.h>
int main()
{
    char temp[4][10],wc[10];
    int i=0,j;
    FILE *fp;
    fp=fopen("ip.txt","r");
    fscanf(fp,"%s",wc);
    while(strcmp(wc,"\n"))
    {
        strcpy(temp[i],wc);
        fscanf(fp,"%s",wc);
        i++;
    }

    for(j=0;j<i;j++)
    {
        printf("%s",temp[j]);
    }
}

输出:segmentation fault(core dumped)

ip.txt包含:

LOOP ADD AREG,A
 SUB B,A

错误在哪里?

2 个答案:

答案 0 :(得分:2)

我的朋友们,在看完你的问题之后,我发现你在程序的最后一个循环中错误地将j写入i。对于i == 4,数组temp[]将继续越过边界,这将导致分段错误。处理的方法是在最后一个循环中用j替换i,strcmp(wc,"\n")永远不会在第一个循环中变为0,所以temp[]也会越过边界。说实话,我建议你下次在问题中记下这个愿望。复制wc也很危险进入指针数组的元素,尤其是在为它们分配空间之前,这也是导致分段错误的原因。

答案 1 :(得分:2)

fscanf(fp,"%s",wc);    

%s将匹配一系列非空白字符,并将该序列存储在wc。现在,由于\n 是一个空格字符,此调用将忽略它!

所以wc永远不会等于\n

因此,while(strcmp(wc,"\n")是一个infinie循环,因为strcmp永远不会返回0。 (即使到达文件ip.txt的末尾!)

语句i++在某些时候会使i大于4(数组限制),那就是当您遇到分段错误时。 (尽管你可以避免无限循环!)

其他问题:

  1. fscanf(fp,"%s",wc);
    现在,如果非空白字符序列大于9个字符,该怎么办? fscnaf会在序列结尾处存储一个addiotional \0字节,覆盖缓冲区wc(大小为10,还记得吗?)
    为避免缓冲区溢出,请始终将maximum field width%s一起使用。例如

    fscanf(fp,"%9s",wc); 
    
  2. fp=fopen("ip.txt","r");
    现在你怎么知道fopen成功了?在使用fp进行任何处理之前,请务必检查NULL是否为fp,例如

    if(fp=fopen("ip.txt","r"))
    {
        //`fp` code goes here
    }
    else
        printf("fopen failed!\n");  
    
  3. 解决方案:
    您还没有提到,但如果您的目标是将单词中的单词存储在数组temp中,请执行处理,然后再将下一行中的单词存储在数组temp中,然后您就可以了使用fgets()获取缓冲区中的一行。然后使用sscanf()从该缓冲区中检索每个单词以将它们存储在temp数组中。

    类似的东西:

    char buffer[50], temp[4][10], *buf, *wc;
    int i;
    
    while(fgets(buffer, 50, stdin) != NULL)
    {
        i = 0;
        buf = buffer;
        while((wc = strtok(buf, " \n")) && (i < 4))
        {
            strcpy(temp[i++], wc);
            if (buf && i)
                buf = NULL;
        }
    
        // process words here
    
    }