【问题标题】:writing a substring function in c用c写一个子字符串函数
【发布时间】:2014-06-12 10:23:07
【问题描述】:
char *substring(char *string, int index, int length)
{
    //int counter = length - index;
    int counter = 0;
    for(;string[index] != string[length];index++, counter++);
    printf("\n%d\n", counter);
    char *array = malloc(sizeof(char) * counter);
    if(array != NULL)
    {
        ///while(string[index] != string[length])
        while(index != length)
            {
                array[index] = string[index];
                index++;
                array++;
            }
    }
    else
        puts("Dynamic allocations failed\n");
    return array;
}   

1 - 我已经用“长度 - 索引”注释掉了初始化计数器,因为我觉得它不舒服(我也有点喜欢循环的一行:))。那么,如果我以这种更简单的方式使用它,我可以指望计数器吗?

2 - 我对这段代码的问题是它没有返回任何东西。我尝试打印结果,但没有打印任何内容,当我将函数的结果分配给 char * 时,我收到一条错误消息,提示我无法将 void 分配给 char *。但是它是如何返回 void 的呢?

3 - 我可以用指针算术编写这个函数并且根本没有任何数组索引吗?!

4 - 我可以改变 char *array 吗?!。我问这个是因为我认为 char * 不能被变异,但我已经阅读了正确变异 char * 的代码。还是我混淆了常规 char * 和字符串?

注意:我不想使用字符串库函数

【问题讨论】:

  • string[index] != string[length] dis 实际服务的目的是什么?
  • memcpy 怎么样?还是strncpy?不确定这些是否算作“字符串库函数”,尽管它们完全符合您的要求并且通常会更快。
  • @GoldRoger:它的作用与它后面的 while 语句相同。但是由于第二个 while 循环工作得很好而且更简单,所以我把它注释掉了。
  • @Thomas:它仍然是一个库函数。我还没有正确研究图书馆功能。这就是我不想使用它们的原因。
  • 发布了一个不使用任何库但 malloc 和 free 的工作示例。

标签: c substring


【解决方案1】:

您的代码有几个问题。

for(;string[index] != string[length];index++, counter++);

首先,在上述行中,您需要从长度中减去一个,因为数组是从 0 开始索引的。

如果子字符串的最后一个字符在子字符串的其他地方重复,该行也会中断。例如aba where index = 0, length = 3。您的循环将立即停止,因为 string[0] == string[2] 即使您没有到达子字符串的末尾。

但是,计算子串长度的整个循环是不必要的,只需使用length

char* array = malloc(length + 1);

请注意,您需要 +1 来包含 C 字符串中的标准空终止符。

接下来,如果index 不为0,此行将不起作用。

array[index] = string[index];

indexstring 的索引,而不是array 的索引。您应该为您的迭代器使用不同的变量,该变量从索引开始然后递增。然后可以从迭代器中减去index,得到子字符串array中的实际索引。

int i = index;
while(i < length)
{
    array[i - index] = string[i];
}

另请注意,循环中的这一行是不必要的,并且会破坏您的代码。

    array++;

您的迭代器正在递增,因此您无需递增array 指针。另外,如果你直接增加array,那么当你返回它时,它指向哪里?它指向字符串的结尾,而不是开头,所以你当然不会得到任何输出。

最后,不要忘记添加空终止符。在您的循环之后,由于您的迭代器现在将方便地指向最后一个索引,所以只需执行

array[i] = '\0';

另外,由于您专门创建了一个新字符串来保存子字符串并且修改原始string 指针,因此您应该将字符串的参数声明为const。例如:const char *string。这不是必需的,但是有一个 number of reasons 说明 const 正确性很重要。

如果您进行上述更改,您的代码应该可以正常工作。我没有发布完整的代码,因为我认为自己进行更改是一项有价值的练习。

【讨论】:

  • 我想你误解了length的目的;我相当确定这是子字符串的长度,而不是从中提取子字符串的字符串的长度。我同意存在多个问题,但是您对for 循环中问题的分析不正确。
  • 太美了。我喜欢逐行纠正我的错误和误解并解释我哪里出错的答案。非常感谢丹尼尔
  • 澄清一下,Length 是子串的长度
  • 没问题,我很高兴它有帮助。不过,请务必阅读我关于使用空终止符的编辑。这是我最初忘记的一个非常重要的部分。
  • 正确,这是我从你给它的名字中假设的。
【解决方案2】:

1 - 您可以使用 for 循环,但它的速度很慢。简单的减法立即完成同样的工作,我认为没有理由不适应它。

2 - Printf - 删除for循环末尾的分号,关于指针:

void * 是一个通用 指针类型。您应该将其转换为 char *,如下所示:

char *array = (char *)malloc(sizeof(char) * counter);

3 - 是的,*(ptr + 3) 等同于 ptr[3]。在大多数实现中,使用指针也会快一些。

4 - 是的,您可以修改char * 指针指向的内存。它会修改原始字符串,但我不确定这是否是您的目标。

【讨论】:

  • 关于#2,我认为演员有more cons而不是专业人士。
  • 您还想如何在标准 C 中动态分配内存?您需要在某个时间点进行演员表。此外,这正是引入void * 的原因。
  • 是的,我做到了。尽管如此,问题中还是提到了关于类型不匹配的警告。您当然可以告诉他忽略它(在我看来,这比强制执行更糟糕)或告诉他禁用一些警告(甚至更糟)。
  • 他收到的关于类型不匹配的警告不是来自malloc()。即使使用-Wall,将void* 分配给char* 也不会产生警告或错误消息。自己试试吧。
  • @Kelm:这是 C++ 错误消息,而不是 C 错误消息。在 C 中,编译器不能合理地抱怨缺少从 void * 到“其他指针”的转换,但 C++ 编译器不能合法地接受这种没有转换的转换。如果将 C 代码编译为 C++,则需要强制转换——但纯 C 不需要。
【解决方案3】:

工作 100%

    #include "stdafx.h"
    #include "stdlib.h"
    void substring(char * src, char * dst, int index, int length);
    int _tmain(int argc, _TCHAR* argv[])
    {
        char orig[]="test";
        char * newchar = (char*)malloc(2);//1 char + null

        substring(orig, newchar, 1, 1);

        printf(newchar);

        free(newchar);
        system("pause");
        return 0;
    }

void substring(char * src, char * dst, int index, int length)
{
    // Assign src_index to our initial index
    // Assign a new counter for dst position
    // We want only up to the length hence index+length
    // Increment src_index and dst_index
    for(int src_index = index, dst_index = 0; src_index < index + length; src_index ++, dst_index++)
    {
        dst[dst_index] = src[src_index];
    }
    dst[length++] = '\0'; // Null terminate the string, we already accounted for this above.
}

【讨论】:

  • 不是我,但也许是缺乏解释。 OP 可能希望回答他的问题或解释他做错了什么,而不是其他人为他编写的完全不同的代码。
  • 这是可以理解的,但我认为它不值得一票否决,评论肯定,但因为它确实以具体的方式在技术上回答了这个问题......这对我来说是不公平的。
  • 不是我的反对意见,但您重新设计了界面,您可能应该在_tmain() 中使用printf("%s\n", newchar)。如果您使用标准 C 而不是 Microsoft C,那将是更可取的,但这不是一个很好的选择。你当然应该讨论你所做的重大改变。
  • 只是把数据拿出来而已。
猜你喜欢
  • 1970-01-01
  • 2011-06-06
  • 2014-08-01
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-02
相关资源
最近更新 更多