【问题标题】:Error when creating split function创建拆分函数时出错
【发布时间】:2014-03-05 15:34:16
【问题描述】:

这是一个根据字符将字符串拆分为字符串数组的函数:

char** split(char c,char* src)
{
    int i=0,size=mystrlen(src);
    int num=count(c,src);
    int foundAt;
    //For example for the string The0red0ruby0read0to0read,there are five occurences of zero
    //so if you used substring and split you would have ten values,but except for the first and
    //last values,every other value would repeat twice,so remove these from 10...to give you 8/2 non-repeating values
    //the formula: 2+(2n-2)/2 ==>2+n-1 ==>count+1
    num=num+1;
            //no malloc/calloc here,let substring take care of this...
    char* res[num];
    while(i<num)
    {
        foundAt=indexof(c,src);
        if(foundAt==0)
        {
            //ignore
            src=substring(src,1,size);
        }
        if(foundAt==-1)
        {
            break;
        }

        if(foundAt>=size)
        {
            //ignore if found at the last charecter or null terminator
            break;
        }   
        res[i]=substring(src,0,foundAt);
        src=substring(src,foundAt,size);
        if(src==NULL)
        {
            break;
        }   
        i++;
    }   
    return res; 
}

这是我尝试使用该功能的方式:

   char* look="Look0here0there0seems0to0be0nothing0here";
char**res=split('0',look);  
printf("The first value is %s\n",res[0]);//=>Look
printf("The third value is %s\n",res[2]);//=>there

使用valgrind运行程序得到的结果:

   ==6221== Invalid read of size 8
   ==6221==    at 0x4016F9: main (inittest.c:424)
   ==6221==  Address 0xfff0003a0 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
   ==6221== 
   The first value is Look
   ==6221== Invalid read of size 8
   ==6221==    at 0x401719: main (inittest.c:425)
   ==6221==  Address 0xfff0003b0 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
   ==6221== 
   The third value is 

我的辅助函数:

 int mystrlen(char* val)
{
    int i=0;
    while(val[i]!='\0')
    {
        i++;
    }
    return i++; 
}

    char* substring(char* src,int start,int end)
{
    int i,size_src=mystrlen(src);
    if(start>size_src|| start<0)
        return NULL;
    if(end>size_src)
        end=size_src;
    //['a','b','c','d'] 1,3 ['b','c']
    //starts at start and reads up to but not including end,the extra charecter in calloc is to add a '\0' there
    int size_res=end-start;
    char* res=calloc(size_res+1,sizeof(char));
    for(i=0;i<size_res;i++)
    {
        res[i]=src[start+i];
    }
    res[i]='\0';
    return res;
}

    int indexof(char c,char* src)
{
    int i=0;
    int size=mystrlen(src);
    for(i=0;i<size;i++)
    {
        if(c==src[i])
            return i;
    }
    return -1;  
}

char* mystrchr(char c,char* src)
{
    int i=0,size=mystrlen(src);
    //must include null charecter
    for(i=0;i<=size;i++)
    {
        if(src[i]==c)
        {
            return src+i;   
        }   
    }
    return NULL;    
}

    int count(char c,char* src)
    {
       int i,size=mystrlen(src);
       int num=0;
       for(i=0;i<size;i++)
       {
          if(c==src[i])
          {
             num++;
          }   
       }
       return num;      
    }

编辑:

我还尝试使用 mystrchr 替换 src 以直接获取指向字符串的指针,在这种情况下,每次都会调用 char 为 0 的条件。

【问题讨论】:

    标签: c string pointers multidimensional-array


    【解决方案1】:

    您的res 变量驻留在堆栈中,并且此内存将在您的函数执行后不久被覆盖。您必须动态分配该内存,例如

    char **res;
    res = calloc(num, sizeof(char *));
    

    也许使用strtok_r解决您的问题会容易得多:

    char *saveptr;
    
    token = strtok_r(stringptr, delim, &saveptr);
    while (token) {
        print(token);
        token2 = strtok_r(NULL, delim, &saveptr);
    }
    

    您必须注意,这将通过将所有分隔符替换为 0 个字符来修改输入字符串。

    【讨论】:

    • 我按照你的建议添加了 calloc,结果代码是 pastebin.com/kDvs3DR1.The 代码是使用 compileonline.com/compile_c_online.php.I 测试的,猜想当我使用 gcc 和 valgrind 在计算机上运行它时,我需要释放字符串数组.在释放数组之前是否需要释放每个字符串?另外,如何使用空格作为分隔符??
    • 是的,完全正确 - 首先释放元素,然后释放指针数组。无论您如何编译/运行程序 - 当程序终止时,所有内存都将被释放。只需使用 " " 代替 delim 变量...
    【解决方案2】:

    我无法清楚地理解您的问题。预定义函数 strchr 将返回第一次出现的字符位置。这个功能可以帮到你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-05
      • 1970-01-01
      • 2017-06-08
      • 2013-05-27
      相关资源
      最近更新 更多