反转C中的字符串不会输出反转行 [英] Reversing a string in C does not output the reversed line
问题描述
我正在尝试在C中反转字符串.reverse函数只是将给定位置(在for循环中)的字符分配给临时对象.我在程序中看不到任何逻辑错误,并且该程序在gcc 4.7.2下使用以下命令成功编译:
I'm trying to reverse a string in C. The reverse function simply assigns the character at a given location (in a for loop) to a temp object. I cannot see any logic errors within the program, and the program compile successfully under gcc 4.7.2 with this command:
gcc -Wall -std=c99 reverse.c
要重新创建问题:
1.)运行程序,然后在shell中输入一个字符串
1.) Run the program and enter a string into your shell
2.)输入完成后,按Enter/和或EOF信号.
2.) Once finished inputting, press enter/and or your EOF signal.
问题是原始字符串或反向字符串均未打印.这也是K& R第二版的练习,如果您完成了该练习,则将希望获得与我不同的解决方案.
The problem is that neither the original string is printed, or the reversed string. This is also an exercise from K&R second edition, if you have completed this exercise, a different solution to mine would be appreciated.
我认为该错误是由于缺少null字符引起的,著名的printf需要以null结尾的字符串将输入输出到cin. getline函数将一个空字符分配给数组的末尾,确保该空字符将是字符串中以printf结尾的字符串中的第一个字符(因此不会打印任何字符/文字).
I think the bug is caused by the absence of a null character, the famous printf requires a null terminated string to print input to cin. The getline function assigns a null character to the end of the array, surely the null character will be the first character in the string thereto ending the printf (and thus no character/literal is printed).
#include <stdio.h>
#define MAXLINE 1000
int geline(char s[], int lim);
void reverse(char line[], int length);
int main()
{
char s[MAXLINE];
char t[MAXLINE];
int k, len;
while ((len = getline(s, MAXLINE)) > 0) {
if (len > 1)
reverse(s, len);
}
printf("%s", s);
return 0;
}
void reverse (char input[], int length)
{
char temp[MAXLINE];
int j = length;
for (int i = 0; i < length; ++i, --j) {
temp[i] = input[i];
input[i] = input[j];
input[j] = temp;
}
}
int getline(char s[], int lim)
{
int c, i;
for (i=0; (c=getchar()) != EOF && c!='\n'; ++i)
s[i] = c;
if (c== '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
推荐答案
(我使用-Wall -std=c99 -O3 -g
进行编译,-g
允许使用gdb
)
(I did my compiling with -Wall -std=c99 -O3 -g
, the -g
to allow use of gdb
)
这是我注意到的事情以及解决这些问题的一些方法.我已经尝试过与您开始使用的样式非常接近(例如,我会将原型中的数组decls转换为指针,但这不是必须的).
Here are the things I noticed and some ways of addressing them. I've tried to hew pretty closely to the style you started with (I would have converted the array decls in the prototypes to pointers, for example, but that's not necessary).
您的getline
原型缺少t
.
int getline(char s[], int lim);
在main
中,您实际上并不需要k
,t[MAXLINE]
,并且您的printf
应该应该在循环中,因此您会看到每个相反的单词.请注意,printf
选择了\n
,因为下面的getline
会将换行符和以EOF结尾的行都转换为同一行(没有换行符):
In main
, you don't actually need k
, t[MAXLINE]
, and your printf
should probably be in the loop so you'll see each word as it's reversed. Note that printf
picks up a \n
, since the getline
below converts both newline and EOF-terminated lines to the same thing (without newlines):
int main()
{
char s[MAXLINE];
int len;
while ((len = getline(s, MAXLINE)) > 0) {
if (len > 0)
reverse(s, len);
printf("%s\n", s);
}
return 0;
}
在上面,getline(s, MAXLINE)
可能是getline(s, sizeof(s) / sizeof(*s) - 1)
,尽管再次注意栅栏错误(请注意- 1
).
In above, the getline(s, MAXLINE)
could have been getline(s, sizeof(s) / sizeof(*s) - 1)
although again, be careful of fencepost errors (note the - 1
).
reverse
函数可以得到极大的改进,而不必担心xor跳过具有变量的疯狂(尽管Daffra的例子很有趣,尤其是它正确地停在了中间).取而代之的是,有意识地索引到中间点才是一个明显的胜利.在此之后,再将temp
数组简化为一个临时字符,将保留您的常规样式.
The reverse
function can be greatly improved without going over to the madness of xor to skip having a variable (although Daffra's example is interesting, especially in that it correctly stops in the middle). Instead, having the sense to just index up to the halfway point is a clear win. Between that and dropping reducing the temp
array to just a temporary character, your general style is retained.
void reverse (char input[], int length)
{
int max = length - 1; /* keep the final NUL in place */
for (int i = 0; i <= max / 2; ++i) {
char ch = input[i];
input[i] = input[max - i];
input[max - i] = ch;
}
}
在上面的gcc -O3
中,可以对代码进行认真的检查,因此没有真正的理由担心在每个循环测试中都要进行长除法等.例如,gdb
报告说,
In the above gcc -O3
can do a serious workover on the code, so there's no real reason to worry that long division is going to be performed on every loop test, etc. For example, gdb
reports that i
itself gets optimized out automatically, which is pretty interesting. Write good, readable code first, have some faith in your compiler, optimize later.
最后,getline
受益于针对lim
的测试(至关重要!),并将换行符转换为NUL.
And last, getline
benefits from testing against lim
(CRITICAL!) and and converting newlines into NULs.
int getline(char s[], int lim)
{
int i, c;
for (i=0; (i <= lim) && ((c=getchar()) != EOF) && (c != '\n'); ++i)
s[i] = c;
s[i] = '\0';
return i; /* return the index to the final NUL, same as length w/o it */
}
将MAXLINE
设置为10暂时表明此版本可以正常处理超长行,将它们分成两个单独的行而不会丢失任何字符.
Setting MAXLINE
to 10 temporarily shows that this version handles overlong lines fairly gracefully, splitting them into two separate ones without losing any of the characters.
请谨慎使用字符串,以非常清楚地决定您是要使用长度来描述字符串,还是要使用结尾处的NUL索引来描述它们.这会影响您对循环,限制,变量名称等的措辞方式,显然使它们混淆是击剑错误的经典来源.
Be careful with strings to very clearly decide whether you want to describe them in terms of length, or in terms of the index to the NUL at the end. This affects how you phrase your loops, limits, variable names, etc, and obviously confusing them is a classic source of fencepost errors.
希望这会有所帮助.
这篇关于反转C中的字符串不会输出反转行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!