如何在C中向后迭代数组?

时间:2010-10-03 18:40:33

标签: c arrays

我正在尝试输入一串字符,然后像

一样向后输出

输入:你好 输出:olleH

我有一个有效的例子,但是除了最后一个字母之外,我收到了每一个字母。

#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100

int main(void) {
int my_stg2[MAX_SIZE];
int i = 0;
int j;
char my_stg[MAX_SIZE];

int input ;

input = getchar();

while (input != '\n'){//The new line is the stopping point.


    my_stg2[i] = input;
    ++i;
 input = getchar();


}
    for (j=0;i>=0;i--){



    my_stg[j]  = my_stg2[i];
    j++;
}

printf("%s\n" , my_stg);

}

我尝试了上面的代码,但是我得到了大字符串的奇怪输出。有人可以为我修复循环吗? http://imgur.com/PK97b.png

6 个答案:

答案 0 :(得分:28)

确定。为了解决这样的情况,你应该真正做Kristopher Johnson所说的并在纸上完成它,以弄清楚你的变量在程序执行过程中会如何变化。笔和纸是程序员最重要的工具之一。

因为我知道如果你不知道该怎么做就很难做到这一点,让我来谈谈你。

假设输入"Hello\n"。在开始循环之前,您将拥有以下值:

i = 0 & input = 'H'

然后你继续循环:

while (input != '\n') { my_stg2[i] = input; ++i; input = getchar(); }

对于循环中的每次迭代,您的值将更改为:

i = 1 & input = 'e' & my_stg2[0] = 'H'
i = 2 & input = 'l' & my_stg2[1] = 'e'
i = 3 & input = 'l' & my_stg2[2] = 'l'
i = 4 & input = 'o' & my_stg2[3] = 'l'
i = 5 & input = '\n' & my_stg2[4] = 'o'

因此。 i现在是5.

现在进入第二个循环,然后执行以下操作:

for (j = 0; j <= i; j++) { --i; my_stg[i] = my_stg2[j]; }

你开始循环,在减少i后你有以下价值对:

j = 0 & i = 5 & my_stg[4] = my_stg2[0] = 'H'
j = 1 & i = 4 & my_stg[3] = my_stg2[1] = 'e'
j = 2 & i = 3 & my_stg[2] = my_stg2[2] = 'l'

......在第三步,循环停止。您得到的输出是"leH"

现在,为什么循环停止了?查看条件,您就会找到答案。

答案 1 :(得分:2)

调整你的for循环,如下所示

for (j=0; j < i; j++)
{
    my_stg[i - (j + 1)]  = my_stg2[j];
}

my_stg[i] = 0;

答案 2 :(得分:2)

这就是你拥有的

// The following line is pseudo-code.
// The '\0' is required in C to mark end of a character string.
orig := 'H', 'e', 'l', 'l', 'o', '\0'

包含字符数n = 6(不要忘记\0)。

以下是您想要实现的目标

reverse := 'o', 'l', 'l', 'e', 'H', '\0'

所以,这就是我们要做的事情:

一个。在\0

中添加reverse[ n - 1 ]

B中。我们会从索引orig开始阅读i = 0 转发,并从索引reverse开始向j = n - 1 向后写。为此,我们使用两个索引变量:

  i, for indexing orig, starting at 0 and incrementing up to n - 1

  j, for indexing reverse, starting at n - 1 and decrementing down to 0

℃。从orig[ i ]复制到reverse[ j ]

for( i = 0, j = n - 1; (i <= n - 1) && (j >= 0); ++i, --j ) {
   reverse[ j ] = orig[ i ];
}

答案 3 :(得分:2)

您的计划有2个错误。

首先,要意识到第一个循环中“i”的值总是设置为“我们下次写入的索引”。

i = 0; input = getchar();
while (input != '\n'){
    my_stg2[i] = input;
    ++i;
    input = getchar();
}

写完“Hello!”后退出该循环,你将有

my_stg2[] = {'H', 'e', 'l', 'l', 'o', '!'}, i=6

当你开始从my_stg2中读取数值时,你应该从(i-1)而不是从i开始阅读。

第二个问题是,在将my_stg2的内容复制到my_stg后,您需要执行以下操作:

my_stg2[j] = 0;

这是因为C中的字符串使用尾随空来确定字符串的结尾。你附加的图片中的字符串后面有垃圾字符的原因是因为printf()代码将继续打印内存中的每个连续字节,直到它达到0,并且你从未在my_stg字符串的末尾显式地放置0。

或者,您可以使用

在程序开头将my_stg2的全部内容初始化为0
memset(my_stg2, 0x00, sizeof(my_stg2));

这对C来说是一个重要的教训 - 当你声明一个需要初始化它的变量时,或者它会在某些平台上填充先前存储在内存位置的任何内容。

答案 4 :(得分:2)

您的代码中有几个问题:

  1. int my_stg2[MAX_SIZE];是声明时的随机整数数组。它们在您的平台上是sizeof(int) - 可能是32位或64位;

  2. char my_stg[MAX_SIZE];是声明时的随机字符数组。这些是你平台上的sizeof(char) - 可能是8位;

  3. 您正在使用my_stg[j] = my_stg2[i];的分配交换整数和字符而不进行投射。

  4. 您没有在while循环中检查缓冲区溢出。如果有人在MAX_SIZE之前输入了超过\n个字符,您将超出您分配的缓冲区;

  5. 您不是null终止字符串。如果您使用的是getchar()单个字符。你需要在那之后放一个NUL,否则你将会遇到一个带有printf()

  6. 的失控字符串
  7. while循环中,您需要检查EOF

  8. 这是违反直觉的,但getchar()是它自己的小循环之类的构造。在EOF或CR之前,它不会进入while循环。然后它将转储所有字符。那么,您不应该针对getchar()测试CR。

  9. 你的第二个循环被一个人关闭;您正在复制最后一个字符后的值。

  10. 此代码可以按照您的预期运行:

    #include <stdio.h>
    #include <stdlib.h>
    #define MAX_SIZE 100
    
    int main(void) {
        char my_stg[MAX_SIZE], my_stg2[MAX_SIZE];
        int i,j,input = 0;
    
        while ((input=getchar())!=EOF) {
            if(input=='\n' || i>=MAX_SIZE-1) break;
            my_stg2[i++] = (char)input;
            my_stg2[i+1] = (char)0l;
        }
    
        printf("my_stg2= %s\ni=%i\n",my_stg2,i);
    
        for (j=0;i>0;i--,j++){
           my_stg[j]  = my_stg2[i-1];
           my_stg[j+1]=(char)0l;
           printf("i=%i %s\n",i,my_stg);
        }
        printf("%s\n" , my_stg);
        return EXIT_SUCCESS;
    }
    

    因为将字符串视为具有NUL终止而感到有点乏味,所以大多数人使用标准C库来表示字符串。

    您可能还想更有效地思考这个循环。使用1/2内存和1/2步骤使用递归函数反转字符串,如下所示:

    void strrev ( char *buff, int start, int end )
    {
        char tmp ;
        static int i=0;
    
        if ( start >= end ) {i=0; return;}
    
        printf("%i strrev=%s\n",++i,buff);
    
        tmp = *(buff + start);
        *(buff + start) = *(buff + end);
        *(buff + end) = tmp ;
    
        strrev (buff, ++start, --end );
    }
    

    如果查看输出,您可以看到它是步数的1/2而没有复制到另一个缓冲区:

    Hello World!!!
    my_stg2= Hello World!!!
    i=14
    i=14 !
    i=13 !!
    i=12 !!!
    i=11 !!!d
    i=10 !!!dl
    i=9 !!!dlr
    i=8 !!!dlro
    i=7 !!!dlroW
    i=6 !!!dlroW 
    i=5 !!!dlroW o
    i=4 !!!dlroW ol
    i=3 !!!dlroW oll
    i=2 !!!dlroW olle
    i=1 !!!dlroW olleH
    !!!dlroW olleH
    Recursive:
    1 strrev=!!!dlroW olleH
    2 strrev=H!!dlroW olle!
    3 strrev=He!dlroW oll!!
    4 strrev=HeldlroW ol!!!
    5 strrev=HelllroW od!!!
    6 strrev=HelloroW ld!!!
    7 strrev=Hello oWrld!!!
    reverse the reverse: Hello World!!!
    

答案 5 :(得分:1)

查看数组问题的指针反向解决方案:

const char *loop = my_stg2 + strlen(my_stg2);
...
do {
  my_stg[loop-my_stg2] = *loop;
} while( my_stg2 != loop-- );