我正在尝试输入一串字符,然后像
一样向后输出输入:你好 输出: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
答案 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的全部内容初始化为0memset(my_stg2, 0x00, sizeof(my_stg2));
这对C来说是一个重要的教训 - 当你声明一个需要初始化它的变量时,或者它会在某些平台上填充先前存储在内存位置的任何内容。
答案 4 :(得分:2)
您的代码中有几个问题:
int my_stg2[MAX_SIZE];
是声明时的随机整数数组。它们在您的平台上是sizeof(int) - 可能是32位或64位;
char my_stg[MAX_SIZE];
是声明时的随机字符数组。这些是你平台上的sizeof(char) - 可能是8位;
您正在使用my_stg[j] = my_stg2[i];
的分配交换整数和字符而不进行投射。
您没有在while
循环中检查缓冲区溢出。如果有人在MAX_SIZE
之前输入了超过\n
个字符,您将超出您分配的缓冲区;
您不是null终止字符串。如果您使用的是getchar()
单个字符。你需要在那之后放一个NUL,否则你将会遇到一个带有printf()
在while
循环中,您需要检查EOF
这是违反直觉的,但getchar()
是它自己的小循环之类的构造。在EOF或CR之前,它不会进入while循环。然后它将转储所有字符。那么,您不应该针对getchar()测试CR。
你的第二个循环被一个人关闭;您正在复制最后一个字符后的值。
此代码可以按照您的预期运行:
#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-- );