头优先C反向字符串示例

头优先C反向字符串示例,c,C,我一直在学习“头优先C”,我找到了一个创建字符串反转方法的练习 这就是我的解决方案: void reverse_string(char s[]) { for (int i = strlen(s) - 1; i > -1; i--) { printf("%c", s[i]); } } 这是书中的解决方案: void reverse_string(char *s) { size_t len = strlen(s); char *t = s + le

我一直在学习“头优先C”,我找到了一个创建字符串反转方法的练习

这就是我的解决方案:

void reverse_string(char s[]) {
    for (int i = strlen(s) - 1; i > -1; i--) {
       printf("%c", s[i]);
   }
}
这是书中的解决方案:

void reverse_string(char *s) {
    size_t len = strlen(s);
    char *t = s + len - 1;

    while (t >= s) {
     printf("%c", *t);
     t = t - 1;
    }

    puts("");
}

我从书上理解了解决办法,但我的看起来更干净。后一种解决方案更可取吗?如果是,原因是什么?

首先,没有任何一种解决方案可以逆转字符串。他们按相反的顺序打印,但这与反转不同

您的解决方案看起来更好、简洁,而且不丧失可读性,这很好


我不认为这本书中的解决方案更可取。

总结一下评论:

首先,函数名
reverse\u string()
有误导性,因为它不反转字符串,只按相反顺序打印

函数应该使用指向
const char
的指针,而不是指向
char
的指针。有些人还可能认为在参数列表中使用
[]
有点误导,因为这可能会让不太熟悉C的人相信传递的是数组,而不是指向其第一个元素的指针

这两个函数都使用
printf()
打印单个字符。这涉及到不必要的解析格式字符串的工作,一次只输出一个字符。改为使用`putchar()
fputc()

这两个函数之间的功能差异:您的版本不会在反转的字符串后打印换行符。这本书的版本可以做到这一点,但就像对单个字符使用
printf()
一样,它以伪装的方式使用
put(“”
)而不是
putchar('\n')

当一个空字符串被传递给函数时,本书中的版本可能有未定义的行为,因为在这种情况下,
t
将指向
s
指向的数组的第一个元素之前,该元素不能保证工作

您的版本使用
int
eger来存储
strlen()
类型的
size\u t
的结果。
int
eger可能会溢出很长的字符串

两种可能的解决办法:

#include <string.h>  // strlen()
#include <stdio.h>   // putchar()

void print_reverse(char const *str)
{
    for (char const *p = str + strlen(str); p != str; putchar(*--p)); 
    putchar('\n');
}
#包括//strlen()
#include//putchar()
无效打印(字符常量*str)
{
for(char const*p=str+strlen(str);p!=str;putchar(*--p));
putchar('\n');
}
或使用索引:

#include <string.h>  // strlen()
#include <stdio.h>   // putchar()

void print_reverse(char const *str)
{
    for (size_t i = strlen(str); i; putchar(str[--i])); 
    putchar('\n');
}
#包括//strlen()
#include//putchar()
无效打印(字符常量*str)
{
for(size_t i=strlen(str);i;putchar(str[--i]);
putchar('\n');
}

本书中的解决方案具有未定义的行为,因为它在字符串开头之后递减
t
。比较指向数组外部的
t
s
具有未定义的行为。在具有分段指针的体系结构上,如果
=
只测试指针的偏移部分,则它将失败。出于同样的原因,它也会因空字符串而失败

带有指针的便携式解决方案如下所示:

void reverse_string(const char *s) {
    const char *t = s + strlen(s);

    while (t > s) {
        t--;
        putchar(*t);
    }
    putchar('\n');
}
您的版本使用了一个索引,这是可以的,但它有一个小问题:它不处理长度超过
INT\u MAX
的字符串。字符串长度的type
size\u t
可能大于
int
,事实上,即使在
int
size\u t
大小相同的体系结构上,
size\u t
未签名的值也可能大于
int\u MAX

更改类型
i
是不够的,因为您依赖于
i
变为负值。在递减索引之前,这里有一种优雅的测试方法:

void reverse_string(char s[]) {
    for (size_t i = strlen(s); i-- > 0;) {
        putchar(s[i]);
    }
    putchar('\n');
}

一些滑稽的程序员编写这个比较
i-->0
并调用
-->
downto操作符。。。这是一个笑话,表达式被解析为
i
--
0
,中间的空格无关紧要。

两者都是正确的,两者都没有错。在本书的上下文中,这本书中的一本可能更可取,但这并不意味着你不能使用你的解决方案。但是,您的解决方案和图书解决方案之间有一点不同:您的解决方案不打印换行符。是的,我更喜欢您的版本。
strlen()
的结果是
size\u t
,而不是
int
。两个版本都不是最优的。。。不需要使用
printf()
,它必须解析格式字符串,一次只输出一个字符。使用
putchar()
fputc()
。这本书中的代码可以使用
for()
-循环来提高可读性
void reverse_string(char const*str){for(char const*p=str+strlen(str)-1;p>=str;--p){putchar(*p);}putchar('\n');}
我担心书本解决方案会尝试递减指针
t
,直到它指向数组
s
的开始之前。不能保证你能做到这一点。这两个函数都命名错误;两者都不反转字符串,但都以相反的方式打印字符串。如果传递空字符串,则两者都具有未定义的行为。(我看过的“头先”的书不是很好——作者们似乎对当代流行文化的有趣引用比对教学更感兴趣。)两者都不是完全可取的,因为他们使用可变的
printf
,其中需要一个简单的
putchar()