strcpy复制数组,程序异常奔溃

问题:解释一下我备注错误的地方为什么会使程序崩溃。
图片说明

开发IDE:codeblock17.12
链接:https://pan.baidu.com/s/1wwoP4v_Y5xYJtH7WZIWjdw 密码:gm87

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct element
{
    char *key;
    char *content;
}element;
char buf[2048]={0};
int get_elements(element **p,char * file_name)
{
    FILE * fp=fopen(file_name,"r");
    if(fp==NULL)
    {
        printf("打开文件失败!");
        return -1;
    }
    *p=(element*)malloc(sizeof(element));
    //char buf[2048]={0};
    int index=0;
    while(!feof(fp))
    {
        if(fgets(buf,sizeof(buf),fp)!=NULL)
        {
            (*p)[index].key=(char *)calloc(strlen(buf),sizeof(char));
            //strcpy((*p)[index].key,buf);//错误
            //strncpy((*p)[index].key,buf,strlen(buf));//错误
            //strcpy((*p)[index].key,&buf[0]);//错误
            strcpy((*p)[index].key,&buf[1]);//正确
            memset(buf,0,sizeof(buf));
        }
        if(fgets(buf,sizeof(buf),fp)!=NULL)
        {
            (*p)[index].content=(char *)calloc(strlen(buf),sizeof(char));
            //strcpy((*p)[index].content,buf);
            strcpy((*p)[index].content,&buf[6]);
            memset(buf,0,sizeof(buf));
        }
        printf("%s%s",(*p)[index].key,(*p)[index].content);

        index++;
        if((*p=(element*)realloc(*p,sizeof(element)*(index+1))) == NULL)
        {
            puts("error");
            return -1;
        }
        //memset(*p+index,0,sizeof(element));
    }
    fclose(fp);
    return index;
}
int search_element(element *p,int n,const char * key)
{
    int i=0;
    for(i=0;i<n;i++)
    {
        //if(strcmp(p[i].key,key)==0)//p[i].key[3]是'\n'字符,key[3]是'\0'字符
        if (strncmp(p[i].key, key, strlen(key)) == 0)
        {
            printf("%s",p[i].content);
            return 1;
        }
    }
    return -1;
}
//最好还是传指针的地址,不然就是野指针
int free_elements(element *p,int n)
{
    int i=0;
    for(i=0;i<n;i++)
    {
        if (p[i].key)
            free(p[i].key);
        if (p[i].content)
            free(p[i].content);
    }
    free(p);
    return 0;
}
int main()
{
    char file_name[]="dict.txt";
    element *p=NULL;
    int n = get_elements(&p,file_name);//将词典的内容读到内存
    search_element(p,n,"you");
    free_elements(p,n);
    return 0;
}

工程文件包:
链接:https://pan.baidu.com/s/1FfHerOqcVlGoP3-vSvXMIA 密码:b1gu

4个回答

如果dict.txt是如下格式
key:content
可以做如下修改,代码中对于一些问题做出了建议,不对之处可以讨论
#include
#include
#include
typedef struct element
{
char *key;
char *content;
}element;

char buf[2048]={0};
int get_elements(element **p, char * file_name)
{
FILE * fp=fopen(file_name,"r");
if(fp==NULL)
{
printf("打开文件失败!\n");
return -1;
}
//*p=(element*)malloc(sizeof(element));
//char buf[2048]={0};
//index为string.h库中函数名,在包含该库的时候建议不使用
int iIndex=0;
while(!feof(fp))
{
//将内存分配放在这里,确保文件有内容可读的时候才分配内存
if((*p=(element*)realloc(*p,sizeof(element)*(iIndex+1))) == NULL)
{
puts("error");
return -1;
}

    memset(buf,0,sizeof(buf));
    if(fgets(buf,sizeof(buf),fp)!=NULL) //读取文件一次,读取
    {
        (*p)[iIndex].key=(char *)calloc(strlen(buf),sizeof(char));
        //strcpy((*p)[index].key,buf);//错误
        //strncpy((*p)[index].key,buf,strlen(buf));//错误
        //strcpy((*p)[index].key,&buf[0]);//错误
        char *sepIndex = index(buf, ':');
        //查找key
        strncpy((*p)[iIndex].key, buf, sepIndex-buf);//strcpy很容易造成内存益处,建议使用strncpy
        //查找content
        (*p)[iIndex].content=(char *)calloc(strlen(buf),sizeof(char));
        strncpy((*p)[iIndex].content, sepIndex+1, strlen(sepIndex+1)); 
        sepIndex = NULL;

/*
if(fgets(buf,sizeof(buf),fp)!=NULL)
{
(*p)[index].content=(char *)calloc(strlen(buf),sizeof(char));
//strcpy((*p)[index].content,buf);
strcpy((*p)[index].content,&buf[6]);
memset(buf,0,sizeof(buf));
}
*/
printf("%s: %s",(*p)[iIndex].key,(*p)[iIndex].content);
}

    ++iIndex;

/*
//如果扩展内存放这里,意味着如果已经到了文件尾,还是继续分配了内存,造成资源浪费
if((*p=(element*)realloc(*p,sizeof(element)*(iIndex+1))) == NULL)
{
puts("error");
return -1;
}
//memset(*p+index,0,sizeof(element));
/
}
fclose(fp);
return iIndex;
}
int search_element(element *p,int n,const char * key)
{
int i=0;
for(i=0;i<n;i++)
{
//if(strcmp(p[i].key,key)==0)//p[i].key[3]是'\n'字符,key[3]是'\0'字符
if (strncmp(p[i].key, key, strlen(key)) == 0)
{
printf("%s",p[i].content);
return 1;
}
}
return -1;
}
//最好还是传指针的地址,不然就是野指针
//这里你只释放了结构体内部的指针,对于结构体本身的指针并没有释放
/

int free_elements(element *p,int n)
{
int i=0;
for(i=0;i<n;i++)
{
if (p[i].key)
free(p[i].key);
if (p[i].content)
free(p[i].content);
}
free(p);
return 0;
}
*/
int free_elements(element **p,int n)
{
int i=0;
for(i=0;i<n;i++)
{
if ((*p)[i].key)
free((*p)[i].key);
if ((*p)[i].content)
free((*p)[i].content);
}
free(*p);
*p = NULL;
return 0;
}
int main()
{
char file_name[]="dict.txt";
element *p=NULL;
int n = get_elements(&p,file_name);//将词典的内容读到内存
search_element(p,n,"you");
free_elements(&p,n);
return 0;
}

qq_24964575
小哥哥咯 回复weixin_41475349: codeblocks,我发现了我的错误,我的内存溢出了,没有考虑到'\0'的内存空间的分配
大约 2 年之前 回复
weixin_41475349
weixin_41475349 回复qq_24964575: 对于静态数组来讲,其数组名在某些环境下代表的就是其首地址,猜测可能跟你的编译器有关
大约 2 年之前 回复
weixin_41475349
weixin_41475349 回复qq_24964575:我上面的代码是在LinuxMint18.3编译运行的,都是正常运行的,你的使用什么编译器
大约 2 年之前 回复
qq_24964575
小哥哥咯 #a Trans:art. 一;字母A #a.m. Trans:n. 上午 #a/c Trans:n. 往来帐户@往来:come - and - go; contact; intercourse@n. 往来帐户 #aardvark Trans:n. 土猪 #aardwolf Trans:n. 土狼
大约 2 年之前 回复
qq_24964575
小哥哥咯 我按你的方式修改了代码,将“strcpy((*p)[i].key,&buf[1]);”替换为“strncpy((*p)[i].key,buf,strlen(buf));”还是不行
大约 2 年之前 回复
qq_24964575
小哥哥咯 文件的格式在我发的第二个工程文件包里有
大约 2 年之前 回复
qq_24964575
小哥哥咯 回复qq_24964575: 我现在的代码是可以运行的,只不过将现在的代码替换为我备注错误的代码时就崩溃了
大约 2 年之前 回复
qq_24964575
小哥哥咯 非常感谢!能解释一下我备注错误的地方为什么会使程序崩溃。
大约 2 年之前 回复

你的dict.txt格式是什么样的

qq_24964575
小哥哥咯 回复qq_24964575: 在提问的最后我发了工程文件包,你可以查看一下。
大约 2 年之前 回复
qq_24964575
小哥哥咯 GBK
大约 2 年之前 回复

p=(element)malloc(sizeof(element));
//char buf[2048]={0};
int index=0;
while(!feof(fp))
{

可以检查一下内存是否对齐,打印一下目标地址和源地址。

qq_24964575
小哥哥咯 我现在的代码是可以运行的,只不过将现在的代码替换为我备注错误的代码时就崩溃了
大约 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐