Tom*_*Tom 2 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;
for (length = length; length>=0; length--){
puts (string[length]);
}
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
a.c:10: warning: passing argument 1 of ‘puts’ makes pointer from integer without a cast
/usr/include/stdio.h:668: note: expected ‘const char *’ but argument is of type ‘char’
/tmp/cc5rpeG7.o: In function `main':
a.c:(.text+0x29): warning: the `gets' function is dangerous and should not be used.
Run Code Online (Sandbox Code Playgroud)
我该怎么办?
Jon*_*ler 11
忘记函数gets()存在 - 它是致命的.请fgets()改用(但请注意,它不会删除行尾的换行符).
您希望一次放置一个字符:用于putchar()将其写入stdout.不要忘记在循环后向输出添加换行符.
此外,for (length = length; length >= 0; length--)不是惯用C.使用以下之一:
for ( ; length >= 0; length--)for (length = strlen(string) - 1; length >= 0; length--)for (int length = strlen(string) - 1; length >= 0; length--)最后一种方法使用了添加到C99的功能(很久以前就可以在C++中使用).
此外,我们可以辩论是否length适合变量的名称.最好将其重命名为i或pos类似,因为虽然它被初始化为输入的长度,但实际上它被用作数组索引,而不是任何长度.
主观:不要在函数名称和参数列表之间放置空格.C的创始人不这样做 - 你也不应该这样做.
第一个互联网蠕虫 - 1988 年的Morris蠕虫 - 利用了fingerd用来gets()代替的程序fgets().从那以后,许多程序因为使用了gets()而没有使用fgets()或其他替代方案而被崩溃.
根本问题是gets()不知道有多少空间可用于存储它读取的数据.这会导致"缓冲区溢出",这个术语可以在您最喜欢的搜索引擎中搜索,该搜索引擎将返回大量条目.
如果某人输入150个字符的输入到示例程序,那么gets()将在数组中存储150个字符,其长度为100.这永远不会带来快乐 - 它通常会导致核心转储,但通过精心选择的输入 - 通常由Perl生成或Python脚本 - 你可能会让程序执行任意其他代码.如果程序将由具有"提升权限"的用户运行,这真的很重要.
顺便说一句,gets()很可能是来自于标准C库在下一版本(C1X -见n1494从中移除WG14).它不会在很长一段时间内(20年?)从实际的C库中消失,但应该用这个实现(或类似的东西)替换它:
#undef NDEBUG
#include <assert.h>
char *gets(char *buffer)
{
assert("Probability of using gets() safely" == 0);
}
Run Code Online (Sandbox Code Playgroud)
另一个小细节,部分在对主要问题的评论中讨论.
显示的代码显然是C99; length通过该功能的部分声明在C89中无效.鉴于此,main()函数不显式返回值是"OK" ,因为C99标准遵循C++标准的引导并允许您省略返回值,main()并且效果与结束时相同return(0);或return 0;结束.
因此,这个问题中的程序不能因为没有return最终的问题而严重失误.然而,我认为这是一个比较特殊的标准化决策,并且如果标准已经将该条款排除在外 - 或者做了一些更激进的事情,例如允许无处不在但错误的void main()观察,当控制从那里返回时,结果是成功状态返回到环境.让标准的这一方面发生变化是不值得的 - 遗憾的是 - 但作为一种个人风格的决定,我没有利用授予的许可来省略最终return的main().如果代码必须与C89编译器一起使用,那么它应该return 0;在结尾处显式(但是length必须修复声明).