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

时间:2013-07-01 17:10:32

标签: c string function input

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

gcc -Wall -std=c99 reverse.c

要重新创建问题:

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

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

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

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

#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;
}

6 个答案:

答案 0 :(得分:2)

有两个逻辑错误:

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

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

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

试试这段代码:

#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;
    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;
}

答案 1 :(得分:1)

 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);
是的?

答案 2 :(得分:1)

你可以使用这个快速功能:

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 ;
}

答案 3 :(得分:1)

(我使用-Wall -std=c99 -O3 -g编译,-g允许使用gdb

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

您的getline原型错过了t

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错误的经典来源。

希望这有帮助。

答案 4 :(得分:0)

请看一下这段代码:

#include <stdio.h>

#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;
}

答案 5 :(得分:0)

这里只需要进行2次更改,并且反之亦然。 内部功能反向只需执行此操作

int j = --length;

而不是:

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