#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void print_reverse(char *s)
{
size_t len=strlen(s);
char *t=s+len-1;
printf("%s %s\n",t,s);
while(t>=s){
printf("%c",*t);
t=t-1;
}
puts("");
}
int main(){
print_reverse("Hello");
}
谁能告诉char *t=s+len-1;
和while(t>=s)
的工作方式。我无法理解如何将数字添加到指针,以及如何在while循环中比较指针。该程序用于反转c中的字符串。
答案 0 :(得分:0)
让我们逐行执行此操作:
print_reverse("Hello");
void print_reverse(char *s)
现在s
指向包含以下内容的字符串:
- - ----+----+----+----+----+----+----+---- - -
| H | e | l | l | o | \0 |
- - ----+----+----+----+----+----+----+---- - -
^
s
最后一个字符称为字符串“ NUL”终止符,因为“ NUL”是ASCII值为零(所有不可打印的ASCII值都有三个字母名称)的字符的名称。
size_t len=strlen(s);
现在len
的值为5。请注意,它不包含“ NUL”终止符,因此即使字符串占用6个字节,长度也为5。
char *t=s+len-1;
现在t
的值为s + 4。如果您算一下内存位置,这就是您得到的:
- - ----+----+----+----+----+----+----+---- - -
| H | e | l | l | o | \0 |
- - ----+----+----+----+----+----+----+---- - -
^ ^
s t
请注意,s+strlen(s)
将指向“ NUL”终止符。
printf("%s %s\n",t,s);
该printf应该打印Hello o
while(t>=s)
此while循环将一直持续到t>=s
,这意味着它将为每个字符(包括s
所指向的字符)执行循环的正文。
printf("%c",*t);
这将打印t指向的存储器的内容。它从o
开始,然后向H
的方向继续前进。
t=t-1;
向后移动t的部分。最终,t将超过s,然后循环将结束。循环结束后,它将如下所示:
- - ----+----+----+----+----+----+----+---- - -
| H | e | l | l | o | \0 |
- - ----+----+----+----+----+----+----+---- - -
^ ^
t s
然后这是最后一行:
puts("");
这将打印一个空字符串和最后一个换行符-字符串中没有换行符,但是我们需要一个换行符,因此这是一种实现方式。
答案 1 :(得分:0)
当指针指向数组时,向指针添加整数或从指针中减去整数将指针在数组中来回移动。
应该向此函数传递指向字符串的char *s
,该字符串是以空字符('\0'
)结尾的字符数组。然后size_t len = strlen(s);
将len
设置为此字符串的大小,而char *t = s+len-1;
将t
设置为指向空字符之前的最后一个字符。
然后,在循环t=t-1;
中向后移动t
。
不幸的是,此循环使用t>=s
作为控制条件。当t
移至s
之前的字符时即表示停止,这意味着它已退回到起点之前。但是,C标准仅为数组中的元素以及数组末尾的特殊位置定义了指针算法。如果将此函数传递给指向数组开头的s
,则循环最终将使t
指向数组之前,并且C标准未定义结果。
任何对象都可以视为一个元素的数组。如果您具有某种类型T
和某些对象T x;
,则可以设置一个指针T *p = &x;
,然后允许将指针前进一个元素p = p+1;
。未定义使用*p
取消引用该指针,但是可以像在&x == p
中进行比较,也可以从中减去一个指针。
如果将print_reverse
的指针传递到数组的开头以外的地方,那么它的循环就可以了。但是,这就是示例代码中的用法。 print_reverse("Hello");
不是很好的代码。
任何对象都可以视为字符数组。您可以将指向任何对象的指针转换为指向unsigned char
的指针,然后检查组成对象的字节。这用于特殊目的。学习C时,不应在通用代码中使用它,但应了解它的存在。