反向功能未按预期工作

时间:2019-02-05 15:18:53

标签: c kernighan-and-ritchie

我试图弄清楚该程序:“编写一个使字符字符串s反向的函数reverse。(s)。用它编写一个使它的输入一次反向一行的程序。”

我认为下面的伪代码应该可以工作:

“将字符串s复制到tmp,同时增加迭代器。 将字符串tmp复制到s,同时减少初始迭代器,增加新的

#include <stdio.h>

void reverse(char []);

int main(){
    char string[50]="HelloWorld";
    printf("Consider Given string: %s\n",string);
    reverse(string);
    printf("The same string, reversed: %s\n",string);
}

void reverse(char s[]){
    char tmp[50];
    int i,j;
    for (i=0;(tmp[i]=s[i])!='\0';++i);
    for (j=0;i>0;i--,j++)
        s[j]=tmp[i];
}

作为输出,我得到:

pi@readonly:~/new$ a.out
Consider Given string: HelloWorld
The same string, reversed: 

使用gdb进行调试时,发现以下内容:

Breakpoint 5, reverse (s=0x7efff5a4 "HelloWorld") at 1.c:18
18                              s[j]=tmp[i];
1: j = 0
2: i = 10
3: tmp = "HelloWorld", '\000' <repeats 15 times>, "\360\377v\334\365\377~\340\372\353v\000\000\000\000\224\365\377~,\006\001\000\300\004"
4: s = 0x7efff5a4 "HelloWorld"
(gdb) n
17                      for (j=0;i>0;i--,j++)
1: j = 0
2: i = 10
3: tmp = "HelloWorld", '\000' <repeats 15 times>, "\360\377v\334\365\377~\340\372\353v\000\000\000\000\224\365\377~,\006\001\000\300\004"
4: s = 0x7efff5a4 ""
(gdb) n

Breakpoint 5, reverse (s=0x7efff5a4 "") at 1.c:18
18                              s[j]=tmp[i];
1: j = 1
2: i = 9
3: tmp = "HelloWorld", '\000' <repeats 15 times>, "\360\377v\334\365\377~\340\372\353v\000\000\000\000\224\365\377~,\006\001\000\300\004"
4: s = 0x7efff5a4 ""

问题:

1)为什么在tmp出现在步骤s之前,突然从字符串i=0中消失了,所以字符串for (j=0;i>0;i--,j++)中列出的字符串元素突然消失了?换句话说,在断点17 for处的字符串s发生了什么?

2)是否可以在同一void reverse(char s[]){ for (char tmp[50],int i=j=0;(tmp[i]=s[i])!='\0';++i); for (j=0;i>0;i--,j++) s[j]=tmp[i]; } 循环中使用逗号声明和分配不同的函数类型?换句话说,为什么下面的构造在尝试编译时却给出错误?有没有办法在singe循环中混合使用不同的标识符类型?

构造:

pi@readonly:~/new$ cc 1.c
1.c: In function ‘reverse’:
1.c:14:21: error: expected identifier or ‘(’ before ‘int’
for (char tmp[50],int i=j=0;(tmp[i]=s[i])!='\0';++i);
                 ^~~
1.c:14:36: error: ‘i’ undeclared (first use in this function)
for (char tmp[50],int i=j=0;(tmp[i]=s[i])!='\0';++i);
                                ^
1.c:14:36: note: each undeclared identifier is reported only once for each function it appears in
1.c:15:8: error: ‘j’ undeclared (first use in this function)
for (j=0;i>0;i--,j++)
    ^
1.c:16:9: error: ‘tmp’ undeclared (first use in this function)
s[j]=tmp[i];

错误:

<button class="btn btn-blue" ng-click="handleLoadAndDeactivate()"
   ng-show="'Load' == importAction && 0 == errors"
   title="Load">
     Replace
</button> 

2 个答案:

答案 0 :(得分:3)

在此循环开始时:

for (j=0;i>0;i--,j++)
    s[j]=tmp[i];

tmp[i]在字符串的末尾包含终止的空字节。因此,您将该空字节复制到s的开头,从而得到一个空字符串。

在索引i时从tmp的值中减去1。这样,您就从最后一个常规字符开始,到第一个常规字符结束。

for (j=0;i>0;i--,j++)
    s[j]=tmp[i-1];

答案 1 :(得分:1)

C字符串以\0字符终止,并且您的reverse函数将此字符串终止字符从源字符串的结尾复制到目标字符串的开头。然后,目标字符串将为“空”,因为它始于开头。

您必须考虑两件事:

首先,在访问tmp时从头开始:

for (j=0;i>0;i--,j++)
    s[j]=tmp[i-1];

第二,请确保目标字符串已终止。如果目标字符串与源字符串相同,则由于\0已经存在,因此无需执行任何操作。

如果您以某种方式复制到另一个目标,则必须在循环后写s[j]='\0'