家庭作业:在C中,如何仅使用指针获取数组的子串?

时间:2010-02-21 15:48:28

标签: c arrays pointers

使用指针运算,可以将一个数组中的字符分配给另一个数组。我的问题是,如果给出任意的起点和终点,怎么做呢?

int main(void)
{
    char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
    int start = 2, count = 3;
    char string2[10] = {0};
    char *ptr1 = &string1[start];
    char *ptr2 = string2;
    while (*ptr2++ = *ptr1++) { } //but stop after 3 elements???
    printf("%s",&string2);
}

我缺少某种指针算法来计算/测试特定数组中的元素数量。我不想声明一个积分来计算循环!我想用指针完成所有操作。谢谢!

4 个答案:

答案 0 :(得分:3)

当您撰写ptr1++;时,它等同于ptr1 = ptr1 + 1;。向指针添加整数会使指针的内存位置按指向的类型的大小(以字节为单位)移动。如果ptr1char指针,其值为0x5678,则将其递增1会使其成为0x5679,因为sizeof(char) == 1。但如果ptr1Foo *sizeof(Foo) == 12,那么递增指针会使其值0x5684

如果要指向一个元素,该元素距离已经有指针的元素有3个元素,则只需向该指针添加3即可。在你的问题中,你写道:

char *ptr1 = &string1[start]; // array notation

与以下内容相同:

char *ptr1 = string1 + start; // pointer arithmetic

您可以按如下方式重写:

int main(void)
{
    char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
    int start = 2, count = 3;
    char string2[10] = {0};

    // Ensure there is enough room to copy the substring
    // and a terminating null character.
    assert(count < sizeof(string2));

    // Set pointers to the beginning and end of the substring.
    const char *from = string1 + start;
    const char *end = from + count;

    // Set a pointer to the destination.
    char *to = string2;

    // Copy the indicated characters from the substring,
    // possibly stopping early if the end of the substring
    // is reached before count characters have been copied.
    while (from < end && *from)
    {
        *to++ = *from++
    }

    // Ensure the destination string is null terminated
    *to = '\0';

    printf("%s",&string2);
}

使用const和有意义的变量名称(from, tosrc, dst代替ptr1, ptr2)可帮助您避免错误。使用assert并确保字符串为空终止可帮助您避免调试段错误和其他奇怪现象。在这种情况下,目标缓冲区已经归零,但是当您复制此代码的一部分以在其他程序中使用时,它可能不是。

答案 1 :(得分:2)

#include <stdio.h>

int main(void)
{
    char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
    int start = 2, count = 3;
    char string2[10] = {0};
    char *ptr1 = &string1[start];
    char *stop = ptr1 + count;
    char *ptr2 = string2;
    while ((ptr1 < stop) && (*ptr2++ = *ptr1++));
    printf("%s",string2);
    return 0;
}

答案 2 :(得分:2)

我通常在这些情况下使用一组特定的变量名称,名为:

  • src - 来源
  • dst - 目的地
  • end - 源(此处使用)或目标
  • 的结尾

所以:

int main(void)
{
    char string1[] = "something";
    int start = 2;
    int count = 3;
    char string2[10] = {0};

    const char *src = &string1[start];
    const char *end = &string1[start+count];
    char *dst = string2;

    assert(count < sizeof(string2);
    while (src < end)
        *dst++ = *src++;
    *dst = '\0';             // Null-terminate copied string!

    printf("%s",&string2);
    return(0);
}

或者,更合理地,打包成功能:

char *copy_substr(char *dst, const char *str, size_t start, size_t len)
{
    const char *src = str + start;
    const char *end = src + len;
    while (src < end)
        *dst++ = *src++;
    *dst = '\0';
    return(dst);
}

int main(void)
{
    char string1[] = "something";
    char *end;
    char string2[10] = {0};

    end = copy_substr(string2, string1, 2, 3);
    printf("%s",&string2);
    return(0);
}

该函数返回指向字符串末尾的指针,该指针是常规的,并且在示例中没有提供明显的好处,但是当您构建字符串时,它确实有一些优点:

struct substr
{
    const char *str;
    size_t      off;
    size_t      len;
};

static struct substr list[] =
{
    { "abcdefghijklmnopqrstuvwxyz",  2, 5 },
    ...
    { "abcdefghijklmnopqrstuvwxyz", 18, 3 },
};

int main(void)
{
    char buffer[256];
    char *str = buffer;
    char *end = buffer + sizeof(buffer) - 1;
    size_t i;

    for (i = 0; i < 5; i++)
    {
         if (str + list[i].len >= end)
             break;
         str = copy_substr(str, list[i].str, list[i].off, list[i].len);
    }

    printf("%s\n", buffer);
    return(0);
}

重点是返回值 - 指向字符串末尾NUL的指针 - 是字符串连接操作所需要的。 (在此示例中,对于具有已知长度的字符串,您可以在没有此返回值的情况下生存而无需重复使用strlen()或strcat();在被调用函数复制无法通过调用确定的数据量的上下文中例程,指向结尾的指针更有用。)

答案 3 :(得分:0)

为了获得静态数组中的大小(即元素数量),通常会执行

sizeof(string1) / sizeof(*string1)

它将数组的大小(以字节为单位)除以每个元素的大小(以字节为单位),从而为您提供数组中元素的数量。

但是,当您显然尝试实现strcpy克隆时,如果源字符*ptr1'\0'(C字符串为零终止),则可以简单地中断循环。如果您只想复制N个字符,则可以在ptr1 >= string1 + start + count

时中断