Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无法创建将反转字符串的程序_C_Linux_String_Invert - Fatal编程技术网

C 无法创建将反转字符串的程序

C 无法创建将反转字符串的程序,c,linux,string,invert,C,Linux,String,Invert,我正在使用Linux。 我正在尝试用c语言编写一个程序,它将向后打印字符串。 这是我的密码: #include <stdio.h> #include <string.h> #include <stdlib.h> int main (){ char string[100]; printf ("Enter string:\n"); gets (string); int length = strlen (string)-1;

我正在使用Linux。 我正在尝试用c语言编写一个程序,它将向后打印字符串。 这是我的密码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (){
    char string[100];
    printf ("Enter string:\n");
    gets (string);
    int length = strlen (string)-1;
    for (length = length; length>=0; length--){
        puts (string[length]);
    }
}

我该怎么办?

你应该使用
putchar
而不是
put

所以这个循环:

for (length = length; length>=0; length--){
    puts (string[length]);
}
将是:

for (length = length; length>=0; length--){
    putchar (string[length]);
}

putchar
将单个字符作为参数,并将其打印到
stdout
,这正是您想要的<另一方面,code>put会将整个字符串打印到
stdout
。因此,当您将单个字符传递给需要整个字符串(字符数组,NULL终止字符串)的函数时,编译器会感到困惑。

忘记函数
gets()
存在-这是致命的。改用
fgets()
(但请注意,它不会删除行尾的换行符)

您希望一次放置一个字符:使用
putchar()
将其写入stdout。不要忘记在循环后向输出中添加换行符

另外,(length=length;length>=0;length--)的
不是惯用的C。请使用以下选项之一:

  • (;长度>=0;长度--)的
  • for(长度=strlen(字符串)-1;长度>=0;长度--)
  • for(int-length=strlen(string)-1;length>=0;length--)

最后一个替代使用了添加到C99的特征(以前在C++中是可用的)。 此外,我们还可以讨论

length
是否是变量的合适名称。最好将其重命名为
i
pos
或类似名称,因为尽管它初始化为输入的长度,但实际上它被用作数组索引,而不是任何内容的长度

主观:不要在函数名和参数列表之间留空格。C的开国元勋们不会这么做——你也不应该这么做


为什么它是致命的? 第一个互联网蠕虫——1988年的蠕虫——利用了
fingerd
程序,该程序使用
gets()
而不是
fgets()
。从那时起,许多程序都崩溃了,因为它们使用的是
get()
,而不是
fgets()
或其他替代方法

基本问题是
gets()
不知道有多少空间可用于存储它读取的数据。这会导致“缓冲区溢出”,这是一个可以在您喜爱的搜索引擎中搜索的术语,它将返回大量条目

如果有人向示例程序输入150个字符,那么
get()
将在长度为100的数组中存储150个字符。这永远不会带来快乐-它通常会导致核心转储,但通过精心选择的输入(通常由Perl或Python脚本生成),您可能会让程序执行任意其他代码。如果程序将由具有“提升权限”的用户运行,这一点非常重要

顺便说一句,
gets()
很可能在下一版本中从标准C库中删除(C1x-请参阅中的n1494)。它在很长一段时间内(20年?)不会从实际的C库中消失,但应该用这种实现(或类似的实现)来取代它:

#未定义NDEBUG
#包括
字符*获取(字符*缓冲区)
{
断言(“安全使用gets()的概率”==0);
}

另一个次要细节,在对主要问题的评论中部分讨论

显示的代码显然是针对C99的;在C89中,部分通过函数的
length
声明无效。鉴于此,对于<代码>主()>代码>函数,它不显式返回值,因为C99标准遵循C++标准的领先,允许您省略从<代码>主()/代码>的返回,其效果与<代码>返回(0)相同;code>或
返回0在末尾


因此,这个问题中的程序不能因为结尾没有
返回
而被严格地认为是错误的。然而,我认为这是一个更为特殊的标准化决策,如果标准遗漏了该条款,或者做了一些更激进的事情,比如允许普遍存在但错误的
void main()
,注意到当控制权从中恢复时,结果是将成功状态返回到环境。令人遗憾的是,改变标准的这一方面是不值得的,但作为个人风格的决定,我不会利用许可证省略
main()
中的最终
返回值。如果代码必须与C89编译器一起工作,那么它应该有显式的
返回0
在结尾(但是
长度的声明也必须固定)。

使用
putc
putchar
,因为
put
被指定为获取
char*
,并且您正在向它输入
char

,您也可以使用递归来完成此操作。我认为使用循环时看起来更好

只需使用字符串调用该方法,在方法中打印字符之前,使用相同的字符串(减去第一个字符)再次调用该方法

这将按相反的顺序打印字符串。

首先:

从不使用
get()
;它将在代码中引入一个故障点。无法判断目标缓冲区有多大,因此如果您传递一个大小为容纳10个字符的缓冲区,而输入流中有100个字符,
get()
将很高兴地将这些额外的90个字符存储在缓冲区末尾以外的内存中,可能会破坏一些重要的内容。缓冲区溢出很容易被恶意软件利用;Morris蠕虫专门利用sendmail中的
get()
调用进行攻击

改用
fgets()
;它允许您指定从inp读取的最大字符数
for (length = length; length>=0; length--){
    putchar (string[length]);
}
#undef NDEBUG
#include <assert.h>
char *gets(char *buffer)
{
    assert("Probability of using gets() safely" == 0);
}
char string[100]; 
char *newline;
printf("Enter a string: ");
fflush(stdout);
fgets(string, sizeof string, stdin);
newline = strchr(buffer, '\n');      // search for the newline character
if (newline)                         // if it's present
  *newline = 0;                      // set it to zero