使用指针运算而不是数组索引

3

我正在尝试解决在我的C编程书中发现的问题。

#include <stdio.h>
char *f (char s[], char t[], char out[]);
int main(void)
{
    char s[] = "ISBN-978-8884981431";
    char t[] = "ISBN-978-8863720181";
    char out[10];
    printf ("%s\n", f(s,t,out));
    return 0;
}
char *f (char s[], char t[], char out[]) {
    int i;
    for (i=0; s[i] == t[i]; i++)
    out[i] = s[i];
out[i] = '\0';
return &out[0];
}

从代码中可以看出,此代码使用 &out[0] 作为返回值:这是否意味着整个数组被用作返回值?
char *f (char s[], char t[], char out[]);
int main(void)
{
    char s[] = "ISBN-978-8884981431";
    char t[] = "ISBN-978-8863720181";
    char out[10];
    printf ("%s\n", f(s,t,out));
    return 0;
}
char *f (char s[], char t[], char out[]) {
    for (; *(s+=1) == *(t+=1);)
            *(out+=1) = *s;
    *(out+1) = '\0';
    return out;
}

这是我提出的解决方案,但是提出的代码返回"ISBN-978-88",而我的只返回"8"。数组比字符串长度小,为什么提出的代码可以在没有任何类型的溢出的情况下工作呢?感谢您的回应。

2
你正在向前移动“out”。你返回的是指向字符串中最后一个字符的指针(因为++out会将其逐个移动到末尾)。 - Adriano Repetti
1
使用 *(out+1)='\0';,你可以在索引1处以NULL终止字符结束字符数组。因此,在打印输出时,你只能看到一个字符。 - Deidrei
2
你需要做的是将 out 的初始值复制到另一个变量中,并在最后返回该变量。此外,for 循环通常会写成 while(*++s == *++t) - Jon
3个回答

3
你的代码在副作用上过于激进: += 1 操作(通常简称为 ++)应该在将副本复制到输出后应用,而不是在比较之后应用。
此外,您需要在增加指针之前保存 out 缓冲区的值,以便您可以返回指向已复制字符串开头的指针。
char *orig = out;
for ( ; *s == *t ; s++, t++)
    *out++ = *s;
*out = '\0';
return orig;

在 ideone 上的演示。


1
虽然我同意对副作用过度使用的评论,但这并没有真正回答他的问题。 - Tom Tanner
我没有考虑使用out作为缓冲数组,然后返回原始值。非常感谢。 - PeppeLaKappa

2

你的代码返回的是指向 out 数组结束位置的指针,而不是开始位置。你需要保存 out 的初始值并返回它。

另外,能够在比较语句中进行赋值并不意味着这是一个好主意。这样的代码将很难维护。


1
它还会跳过第一个字符,因为它在解除引用和比较之前增加了两个指针。 - Drew McGowen
@DrewMcGowen 呜,这样做很烦人。 - Tom Tanner

2

&out[0] 等同于 out。由于 C 语言中的数组是通过引用传递的,某种程度上,它确实返回整个数组。

你的解决方案只打印了 "8",因为你返回了指向数组中间的指针。当尝试打印字符串时,它无法知道它在数组/字符串的中间,因此只会打印子字符串。


查看其他人的答案 - 你基本上需要在增加它之前保留“out”的值,并返回该原始值。 - Drew McGowen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接