2012-02-21 85 views
0

下面是一个小的C应用程序。它会要求你输入一个单词。它停止询问何时获得四个独特的单词。但是在下面显示的形式中,直到取消注释相关行后才能正常运行。c while循环将局部变量视为全局循环,为什么?

#include <stdio.h> 
#include <string.h> 

#define WORDS_COUNT 4 

int main() 
{ 
    char* words[WORDS_COUNT]; 

    int words_added = 0; 
    while (words_added<WORDS_COUNT) 
    { 

     puts ("\n-------enter a word-------"); 

     char response[250]; 

     scanf("%s", response); 

     int i; 
     int duplicate_flag = 0; 
     for (i=0; i < words_added; i++) 
     { 
      if (strcmp(words[i], response) == 0) 
      { 
       duplicate_flag = 1; 
       break; 
      }; 
     }; 

     if (duplicate_flag == 0) 
     { 
      //char tmp[250]; 
      //strcpy(tmp, response); 
      words[words_added] = response; //words[words_added] = tmp; 
      puts("that's new!"); 
      words_added ++; 
     } else { 
      puts("you've said that already..."); 
     }; 

    }; 
    return 0; 
}; 

正如你所看到的主要区别是words[words_added] = responsewords[words_added] = tmp之间。

为什么tmp变量起作用而不是response

我在猜测response将有每次迭代完全相同的地址,并tmp将获得一个新的地址每次迭代。但为什么?但它们都是在同一个循环中声明的?

+0

您的代码被严重破坏并显示未定义的行为。你的问题是,你还没有为现有单词列表分配任何永久存储 - 只有指向它们的指针。 – dmckee 2012-02-21 21:59:19

+0

[你真的不想让你的程序成为缓冲区溢出开发的入口](http://stackoverflow.com/a/456312/1025391)! – moooeeeep 2012-02-21 22:23:18

+0

@moooeeeep这将是一个有点偏执这里,这只是一个小例子的代码片段,但指出;-) – 2012-02-22 07:19:44

回答

2

当您指定words[words_added] = response时,您正在将response的地址(不是内容)复制到数组中。因此,在原始形式中,您的代码应该将第二个单词和后续单词视为重复。当您使用tmp时,代码会比较每个新的response与存储在(每个位置)words[]中的以前的tmp,然后将它复制到tmp中,如果它不是重复的。

所以我怀疑你的代码会检测到重复,立即遵循原来的,但没有一个出现2个或更多的单词后。

words数组包含4个指针,但没有内存分配给这些指针。 您需要为words阵列中的每个元素分配内存,然后将每个字符串复制到它:

if (duplicate_flag == 0) 
{ 
    words[words_added++] = strdup(response); // allocates mem and copies the string 
    puts("that's new!"); 
} else { 
    ... 
} 

然后一定要free在程序结束时的记忆:

for (i = 0; i < words_added; ++i) { 
    free(words[i]); 
} 
+0

“tmp变量分配在堆栈中每次通过for循环,而响应仍然存在的活程序“是的,但为什么'tmp'被分配而不是'response'? – 2012-02-21 22:05:12

+0

你是对的 - 赶上!我已经修改了我的答案,我想我已经更准确地解释了行为。你介意测试我的怀疑,只有即时重复会被发现吗?如果你能确认,我相信我们明白发生了什么。 – 2012-02-22 01:14:21

+0

确认!我可以确切地看到你的意思,没有“重新分配”,而是我的代码只是将'response'与最后一个“不同的”''response''复制到temp !.为什么我总是认为重新分配发生在循环内? SMH。谢谢! – 2012-02-22 07:38:25

1

你做错了 - 你指向一组指针 - words[words_added] - 在每次迭代都会改变的变量 - response

你需要一个在您执行strcpy之前的每次迭代中为words[words_added]储存存储空间:
strcpy(words[words_added], response);

P.S.不要在封闭大括号后放分号}

+0

tmp和响应属于同一类型。所以不是tmp也在改变每一次迭代? – 2012-02-21 22:03:26

+1

并不重要 - 它可能已经工作 - 但这是一个异常 - 做适当的内存分配malloc(并且不要忘记完成时释放'free') – KevinDTimm 2012-02-21 22:05:19

+0

在真正的程序中,这正是我所做的完成了,但我真的很想理解编译器为什么给予“响应”特殊待遇。 while循环中的所有其他局部变量总是被重新分配,从来没有看到一个变量的行为像'response'那样。我真的想知道为什么。 – 2012-02-21 22:09:48