在C中反转字符串不会输出反转的行

我正在尝试反转C中的字符串。反向函数只是将给定位置(在for循环中)的字符分配给临时对象。 我在程序中看不到任何逻辑错误,并且使用以下命令在gcc 4.7.2下成功编译程序:

gcc -Wall -std=c99 reverse.c 

要重新创建问题:

1.)运行程序并在shell中输入一个字符串

2.)完成输入后,按enter /和/或您的EOF信号。

问题是既没有打印原始字符串,也没有反转字符串。 这也是K&R第二版的练习,如果你完成了这个练习,我将不胜感激我的另一个解决方案。

我认为该错误是由缺少空字符引起的,着名的printf需要一个以空字符结尾的字符串来打印输入到cin。 getline函数将一个空字符分配给数组的末尾,当然空字符将是字符串中结束printf的第一个字符(因此不会打印字符/文字)。

 #include  #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

以下是我注意到的事情以及解决它们的一些方法。 我试图密切关注你开始使用的样式(例如,我会将原型中的数组decls转换为指针,但这不是必需的)。

你的getline原型错过了。

 int getline(char s[], int lim); 

main ,你实际上并不需要kt[MAXLINE] ,你的printf可能应该在循环中,所以你会看到每个单词都被反转。 请注意, printf选择\n ,因为下面的getline将换行符和EOF终止行转换为相同的东西(没有换行符):

 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)虽然再次注意fencepost错误(注意- 1 )。

reverse函数可以大大改进,而不必考虑xor的疯狂跳过变量(虽然Daffra的例子很有趣,特别是它正确地停在中间)。 相反,拥有只是指向中途点的感觉是明显的胜利。 在它之间以及将temp数组减少为临时字符之间,将保留您的常规样式。

 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报告i自己会自动优化,这非常有趣。 首先编写好的,可读的代码,对编译器有一定的信心,稍后进行优化。

最后, getline受益于针对lim (CRITICAL!)的测试以及将换行符转换为NUL。

 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会暂时显示此版本相当优雅地处理超长行,将它们分成两个单独的行而不会丢失任何字符。

小心字符串以非常清楚地决定是要根据长度来描述它们,还是根据最后的NUL索引来描述它们。 这会影响你如何表达你的循环,限制,变量名等,显然混淆它们是fencepost错误的经典来源。

希望这可以帮助。

有两个逻辑错误:

  • int j = length; 应该是int j = length - 1;
  • temp[i] = input[i] ... input[j] = temp;

最后一个错误有两种方法:

  • temp定义为单个char: char temp; ... temp = input[i]; input[i] = input[j]; input[j] = temp; char temp; ... temp = input[i]; input[i] = input[j]; input[j] = temp;
  • temp使用正确的索引: temp[i] = input[i]; input[i] = input[j]; input[j] = temp[i] temp[i] = input[i]; input[i] = input[j]; input[j] = temp[i]

试试这段代码:

 #include  #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; int j = length - 1; for (int i = 0; i < j; ++i, --j) { temp = 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; } 
  int j = length - 1; // Thanks to @chux for (int i = 0; i < j; ++i, --j) { // or <= length / 2 char temp = input[i]; input[i] = input[j]; input[j] = temp; 

不需要temp,也没有完全正确使用。

您需要两次交换值,这将在循环的后半部分恢复交换。 🙂


你的原型错过了't'( geline )。 因此可能

 ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

被采取?

你可以使用这个快速function:

 inline char * reverse(char *p) { char *save=p; char *q = p; while(q && *q) ++q; for(--q; p < q; ++p, --q) *p = *p ^ *q, *q = *p ^ *q, *p = *p ^ *q; return save ; } 

请看一下这段代码:

 #include  #define MAXLINE 1000 int geline(char s[], int lim); void reverse(char line[], int length); int main() { char s[MAXLINE]; int len; while ((len = geline(s, MAXLINE)) > 1) { if (len > 1) { reverse(s, len); printf("%s", s); } } return 0; } void reverse (char input[], int length) { char temp; int j = length-1; for (int i = 0; i < j; ++i, --j) { temp = input[i]; input[i] = input[j]; input[j] = temp; } } int geline(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; } 

这里只需要进行2次更改,反之亦然。 内部function反向就这样做

 int j = --length; 

而不是这个:

 input[j] = temp; //you should use input[j] = temp[i];