尝试拆分和存储类似于strtok的数组

时间:2017-04-26 07:59:47

标签: c string strtok

对于课堂作业,我们已被指示编写一个程序,该程序采用字符串和分隔符,然后采用"单词"并将它们存储在一个新的字符串数组中。即,输入("我的名字是","")将返回一个包含元素的数组" my" "名称" "是&#34 ;.

粗略地说,我所尝试的是:

  1. 使用名为number_of_delimeters()的单独助手来确定字符串数组的大小

  2. 遍历初始数组,找到给定字符串中放置在数组中的元素数

  3. 在我的数组中为每个字符串分配存储空间

  4. 将元素存储在已分配的内存中

  5. 包含指令:

    #include <stdlib.h>
    #include <stdio.h>
    

    这是单独的帮手:

    int number_of_delimiters (char* s, int d)
    {
        int numdelim = 0;
        for (int i = 0; s[i] != '\0'; i++)
        {
            if (s[i] == d)
            {
                numdelim++;
            }
        }
        return numdelim;
    }
    

    `这是函数本身:

    char** split_at (char* s, char d)
    {
        int numdelim = number_of_delimiters(s, d);
        int a = 0;
        int b = 0;
    
        char** final = (char**)malloc((numdelim+1) * sizeof(char*));
    
        for (int i = 0; i <= numdelim; i++)
        {
            int sizeofj = 0;
            while (s[a] != d)
            {
                sizeofj++;
                a++;
            }
    
            final[i] = (char*)malloc(sizeofj);
            a++;
            int j = 0;
    
            while (j < sizeofj)
            {
                final[i][j] = s[b];
                j++;
                b++;
            }
    
            b++;
            final[i][j+1] = '\0';
        }
        return final;
    }
    

    要打印:

    void print_string_array(char* a[], unsigned int alen)
    {
        printf("{");
        for (int i = 0; i < alen; i++)
        {
            if (i == alen - 1)
            {
                printf("%s", a[i]);
            }
            else
            {
            printf("%s ", a[i]);
            }
        }
        printf("}");
    }
    
    int main(int argc, char *argv[])
    {
        print_string_array(split_at("Hi, my name is none.", ' '), 5);
        return 0;
    }
    

    目前返回{嗨,我的名字是无。}

    在做了一些研究之后,我意识到这个函数的目的与strtok相似或相同。但是,查看源代码对此有所帮助,因为它包含了我们尚未在课堂上使用的概念。

    我知道这个问题很模糊,而且代码粗略阅读,但是你能指出这个问题的方法会立即出现问题吗?

3 个答案:

答案 0 :(得分:0)

仅供参考:

File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + fileName);修改您传入的数组!之后

request.setDestinationInExternalFilesDir(Context, Type, Path)

strtok内容将是:

char test[] = "a b c ";
for(char* t = test; strtok(t, " "); t = NULL);

随后您将获得指向测试数组的指针:test{ 'a', 0, 'b', 0, 'c', 0, 0 } test + 0test + 2

strtok会记住你在内部传递给它的指针(很有可能,你在源代码中看到了一个test + 4变量...)所以你可以(并且必须)传递{{ 1}}下次你调用它(只要你想对相同的源字符串进行操作)。

相反,你显然想要复制数据。很好,人们可以这样做。但是我们遇到了一个问题:

NULL

您只需返回数组,但是您正在丢失长度信息! 那么你想如何将长度传递给你的打印功能呢?

static

将失败,因为NULL将始终返回本地系统上指针的大小(很可能是旧硬件上的8,可能是4)!

我的个人建议:创建一个空字符串终止的c字符串数组:

char** final = //...
return final;

void print_string_array(char* a[], unsigned int alen)

然后你的打印功能看起来像这样:

char** tokens = split_at(...);
print_string_array(tokens, sizeof(tokens));

不再有长度问题。实际上,这与C字符串使用的原理完全相同(终止空字符,还记得吗?)。

此外,这是您自己的代码中的问题:

sizeof(tokens)

为了完整性(这已经被n.m.发现,请参阅另一个答案):如果源字符串中没有尾随分隔符,

char** final = (char**)malloc((numdelim + 2) * sizeof(char*));
//                                        ^ (!)

// ...

final[numdelim + 1] = NULL;

将超出输入字符串读取(这是未定义的行为,可能导致程序崩溃)。您还需要检查终止空字符:

void print_string_array(char* a[]) // no len parameter any more!
{
    printf("{");
    if(*a)
    {
        printf("%s", *a);   // printing first element without space
        for (++a; *a; ++a)  // *a: checking, if current pointer is not NULL
        {
            printf(" %s", *a); // next elements with spaces
        }
    }
    printf("}");
}

最后:您想如何处理后续分隔符?目前,您将在数组中插入空字符串?打印出你的字符串如下(带有两个分隔符号 - 我使用*和+像出生和死亡......):

while (j < sizeofj)
{
    final[i][j] = s[b];
    j++; // j will always point behind your string!
    b++;
}

b++;
// thus, you need:
final[i][j] = '\0'; // no +1 !

你会看到。这是为了吗?

编辑2 :带指针算术的变体(仅限):

while (s[a] != d)

答案 1 :(得分:0)

该计划有几个问题。

  1. while (s[a] != d)错误,字符串中的最后一个单词后面没有分隔符。
  2. final[i][j+1] = '\0';错了,j+1太多了。{/ li>
  3. 返回的数组不可用,除非您事先知道有多少元素。

答案 2 :(得分:0)

虽然我现在已经展示了一个更优雅的解决方案,但我已经找到并纠正了我的代码中的问题:

char** split_at (char* s, char d)
{
    int numdelim = 0;
    int x;
    for (x = 0; s[x] != '\0'; x++)
    {
        if (s[x] == d)
        {
            numdelim++;
        }
    }
    int a = 0;
    int b = 0;
    char** final = (char**)malloc((numdelim+1) * sizeof(char*));
    for (int i = 0; i <= numdelim; i++)
    {
        int sizeofj = 0;
        while ((s[a] != d) && (a < x))
        {
            sizeofj++;
            a++;
        }
        final[i] = (char*)malloc(sizeofj);
        a++;
        int j = 0;
        while (j < sizeofj)
        {
            final[i][j] = s[b];
            j++;
            b++;
        }
        final[i][j] = '\0';
        b++;
    }
    return final;
}

我巩固了我之前作为辅助函数的功能,并修改了一些我错误增加的点。