C环不会退出
早上好! 事后看来,这将成为这些令人眼花缭乱的问题之一,但对于我来说,我很难过。我正在经历C编程语言中的一些练习,并且我设法编写了一些代码来初始化一个循环。在谷歌搜索之后,我找到了将循环初始化为0的更好方法,但我不明白为什么我写的循环没有完成。我用调试器发现这是因为'c'变量永远不会达到50,它会达到49,然后回滚到0,但我无法弄清楚它为什么会翻滚。代码附在下面,有没有人知道这里发生了什么?C环不会退出
#include <stdio.h>
#define IN 1
#define OUT 0
/* Write a program to print a histogram of the lengths of words in
itsinput. */
main()
{
int c=0;
int histogram[50]={0}
int current_length=0;
int state=OUT;
//Here we borrow C so we don't have to use i
printf("Initializing...\n");
while(c<51){
histogram[c] =0;
c=c+1;
}
c=0;
printf("Done\n");
while((c=getchar()) != EOF){
if((c==32 || c==10) && state==IN){
//End of word
state=OUT;
histogram[current_length++];
}else if((c>=33 && c<=126) && state==OUT){
//Start of word
state=IN;
current_length=0;
}else if((c>=33 && c<=126) && state==IN){
//In a word
current_length++;
} else {
//Not in a word
//Example, " " or " \n "
;
}
}
//Print the histogram
//Recycle current_length to hold the length of the longest word
//Find longest word
for(c=0; c<50; c++){
if(c>histogram[c])
current_length=histogram[c];
}
for(c=current_length; c>=0; c--){
for(state=0; state<=50; state++){
if(histogram[c]>=current_length)
printf("_");
else
printf(" ");
}
}
}
这是因为histogram[c] = 0
写过去histogram
内存时c = 50
。所以基本上histogram[50]
覆盖c和使它0
这是因为阵列从0
开始C.所以50元件阵列中的最后一个有效索引是49。
从技术上讲,虽然有趣和可利用,你不能依赖于此。这是未定义行为的表现。内存可以很容易地有另一种布局,导致事情“正常工作”或做更有趣的事情。
histogram
有50个元素:从指数0到49的索引
您尝试写入指数50 全盘皆输
做
while (c < 50)
,或者避免魔术常量
while (c < sizeof histogram/sizeof *histogram)
并非所有的常量都是魔法。一个简单的'const int histogram_size = 50;'也可以工作,并且(IMO)比'sizeof histogram/sizeof * histogram'更具可读性。 – Caleb 2012-03-24 12:43:42
@Caleb:在C中,一个'const int'定义创建一个只读对象,而不是一个常量。有时候你真的需要一个常量:'sizeof arr/sizeof * arr'就是这样一个常量。 – pmg 2012-03-24 12:47:22
无论哪种方式,您都会得到相同的号码。如果您使用sizeof数学,您仍然必须在某处指定数组大小。所以,你可以给这个值赋一个名字,说'int histogram [histogram_size];'声明'histogram',或者你可以说'int histogram [50];'。我认为前者更好地解决了你提出的“魔术常数”问题。 – Caleb 2012-03-24 13:01:54
您正在以直方图访问元素0到50,它只包含元素0到49(C/C++使用零索引,因此数组的最大元素将始终为大小1)。
为了避免这样的错误,你可以定义柱状图尺寸为常数,并利用它来进行有关直方图阵列的所有操作:
#define HISTOGRAM_SIZE 50
或者(仅适用于C99或C++,见下文评论):
const int HISTOGRAM_SIZE = 50;
然后:
int histogram[HISTOGRAM_SIZE];
和:
while(c<HISTOGRAM_SIZE)
'#define'是一个C预处理程序语句,将在编译之前进行处理。对于编译器来说,它看起来好像你已经在任何使用HISTOGRAM_SIZE的地方编写了50个,所以你不会得到额外的开销。
'const int'给你一个类似的解决方案,它在很多情况下会给出与定义相同的结果(我不是100%确定在哪些情况下,其他人可以*阐述),但也会给你额外的类型检查奖励。
注意这行:'while(c Till 2012-03-24 12:22:04
声明“int histogram [50] = {0}'后缺少分号。既然你已经在声明中初始化了'直方图',你不需要在循环中重做,它应该检查'c 2012-03-24 12:23:08
永不回收变量。尽可能将它们的范围设置为本地(小),并在需要时声明新范围。无论如何编译器会优化这个。 – bitmask 2012-03-24 12:29:54