2012-02-21 12 views
0

ниже - небольшое приложение C. Он попросит вас ввести слово. Он перестает спрашивать, когда достигло четырех уникальных слов. Но в приведенной ниже форме он не будет работать должным образом, пока вы не раскомментируете соответствующие строки.c while loop рассматривает локальную переменную в цикле как глобальную, почему?

#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] = response и words[words_added] = tmp.

Зачем нужна переменная tmp, а не response?

Я предполагаю, что response будет иметь одинаковый адрес на каждой итерации, а tmp получит новый адрес на каждой итерации. но почему? но они оба были объявлены в том же цикле while?

+0

Код плохо поврежден и выставляется неопределенное поведение. Ваша проблема в том, что вы не назначили постоянное хранилище для списка существующих слов - только указатели на них. – dmckee

+0

[вы не хотите, чтобы ваша программа была точкой входа для переполнения буфера] (http://stackoverflow.com/a/456312/1025391)! – moooeeeep

+0

@moooeeeep, который был бы немного параноиком здесь, это всего лишь небольшой фрагмент кода кода, но точка взята ;-) –

ответ

2

Когда вы назначаете words[words_added] = response, вы копируете адрес (а не содержимое) response в массив. Таким образом, в исходной форме ваш код должен видеть второе слово и каждое последующее слово как дубликаты. Когда вы используете tmp, код сравнивает каждый новый response с предыдущим tmp, который хранился в (каждое место) words[], а затем копирует его в 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'? –

+0

Вы абсолютно правы - хорошо поймайте! Я пересмотрел свой ответ, и я думаю, что я объяснил поведение более точно. Не могли бы вы проверить мои подозрения, что будут обнаружены только немедленные дубликаты? Если вы можете это подтвердить, я уверен, что мы понимаем, что происходит. –

+0

ПОДТВЕРЖДЕНО!Я могу точно видеть, что вы имеете в виду, не было «перераспределения», но вместо этого мой код только сравнивал «ответ» с последним «другим» ответом, который был скопирован в temp !. Почему я всегда предполагал, что перераспределение происходит внутри циклов? SMH. благодаря! –

1

Вы делаете это неправильно - вы указываете массив указателей - words[words_added] - на переменную, которая изменяется на каждой итерации - response

Вам необходимо хранение на хранение для words[words_added] на каждой итерации перед началом работы:
strcpy(words[words_added], response);

P.S. Не помещайте полуколонны после закрытия брекетов }

+0

tmp и ответ одного типа. так что tmp также меняет каждую итерацию? –

+1

не имеет значения - возможно, это сработало - но это была аномалия - сделайте соответствующее распределение памяти 'malloc' (и не забудьте освободить' free', когда закончите) – KevinDTimm

+0

в реальной программе, это именно то, что у меня есть но я действительно хочу понять, почему компилятор давал «ответ» на специальное обращение. Все остальные локальные переменные в цикле while всегда перераспределяются, никогда не видя, что переменная ведет себя так, как делает 'response'. Я действительно хочу знать, почему. –