繁体   English   中英

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

[英]Reversing a string in C does not output the reversed line

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

gcc -Wall -std=c99 reverse.c

重新创建问题:

1.)运行程序,然后在外壳中输入一个字符串

2.)输入完毕后,按Enter /和或EOF信号。

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

我认为该错误是由于缺少null字符引起​​的,著名的printf需要以null结尾的字符串将输入输出到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;
}

有两个逻辑错误:

  • 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 <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;
}
 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是不需要的,并且不是完全正确使用的。

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


您的原型geline “ t”( geline )。 因此,也许

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

被采取?

您可以使用此快速功能:

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

(我使用-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)尽管再次注意栅栏错误(请注意- 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索引来描述它们。 这会影响您如何表达循环,限制,变量名称等的方式,并且很明显地使它们混淆是栅栏错误的经典来源。

希望这可以帮助。

请看下面的代码:

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

此处仅需要进行2次更改,它将起到相反的作用。 内部功能反向只是这样做

int j = --length;

代替这个:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM