2013-04-07 2 views
0

Я работаю через K & R (второе издание) для собственного назидания и столкнулся следующее упражнение (упражнение 2-2 p42):Kernighan и Ritchie Упражнение 2-2 Отладка?

Write a loop equivalent to the following without using && or ||: 

    for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i) 
      s[i] = c; 

Это было мое решение:

#include <stdio.h> 

/* write a loop equivalent to the following without using && or || 

    for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i) 
      s[i] = c; 
*/ 

int main() 
{ 
    int counter = 0, lim = 1000; 
    int s[lim], c; 

    while(counter < lim-1) 
    { 
     while((c = getchar()) != '\n') 
     { 
      while(c != EOF) 
      { 
       s[counter] = c; 
      } 
     } 
     counter++; 
    } 
    return 0; 
} 

I ожидал отступы и, следовательно, вся программа выходила нормально, как только она столкнулась с символом новой строки ('\n') или символом EOF (Ctrl-d на моей машине Linux), но, к моему удивлению, он счастливо водит солдат. Я попытался отладить его, используя gdb, но все еще не мог понять.

Что я не вижу?

Приложение: Я попытался изменить последовательность тестов, пока выполняются циклы while, и добавил оператор if, чтобы выйти из внешнего цикла, если c == '\n', но я все еще не вижу его! Я также испытываю трудности с попыткой запустить GDB, вводя текст в командную строку, и одновременно распечатать значение c, даже когда я попытался связать gdb с pid исполняемой копии исполняемого файла. Я понимаю, что есть, вероятно, другие способы решения этого упражнения, например. устанавливая флаг или переменную OK_TO_EXECUTE, которая истинна только в том случае, если выполняются все три условия, но меня беспокоит тот факт, что я, похоже, не могу найти ошибку в кажущейся простой программе. Именно поэтому я возвращаюсь к K & R, чтобы более тщательно изучить книгу и правильно решить упражнения.

Redone код (все еще глючит !!!):

#include <stdio.h> 

/* write a loop equivalent to the following without using && or || 

    for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i) 
      s[i] = c; 
*/ 

int main() 
{ 
    int counter = 0, lim = 1000; 
    int s[lim], c; 



    while((c = getchar()) != EOF) 
    { 
     if (c == '\n') 
      break; 

     while(c != '\n') 
     { 
      while(counter < lim-1) 
      { 
       s[counter] = c; 
       counter++; 
      } 
     } 
    } 
    return 0; 
} 

РЕШИТЬ! - Я думаю! Кажется, я наконец понял это. Внутренние петли, как написано в моем повторном решении, будут продолжаться бесконечно или в лизинге до достижения lim. Я добавил перерыв заявления и думаю, что я нахожусь на пути к решению.

Я все еще борюсь с тем, как запустить gdb по этой проблеме; введите записи в командной строке И print значение c. Связывание gdb с pid исполняемого файла по-прежнему не работает должным образом. Я даже разместил separate question относительно gdb.

+1

Перейдите на страницу http://lysator.liu.se/c и ознакомьтесь с учебниками C, перечисленными там. Они довольно устарели (почти столько же, сколько и K & R2), но все же очень актуальны. – vonbrand

+0

@vonbrand Спасибо, что указали этот ресурс. – haziz

ответ

1

Вы добавили петли, которые не существовали в оригинале ... это концептуально и логически неправильно.Наиболее очевидное решение использует break:

for (i = 0; i < lim-1; ++i) 
{ 
    c = getchar(); 
    if (c == '\n') 
     break; 
    if (c == EOF) 
     break; 

    s[i] = c; 
} 

Или, если вы притворяетесь, что C не имеет break, вы можете сделать что-то вроде этого:

for (i = 0; i < lim-1; ++i) 
{ 
    c = getchar(); 
    if (c == '\n') 
     i = lim-1; 
    else if (c == EOF) 
     i = lim-1; 
    else 
     s[i] = c; 
} 

Или вы можете использовать Pascal подход:

#include <stdbool.h> 
... 
bool done = false; 
for (i = 0; !done && i < lim-1; ++i) 
{ 
    c = getchar(); 
    if (c == '\n') 
     done = true; 
    else if (c == EOF) 
     done = true; 
    else 
     s[i] = c; 
} 
+0

Спасибо! Я, наконец, понял это сам, подумав об этом немного дальше, хотя мое решение все еще более запутано, чем ваше, и, возможно, все еще неисправно. Я немного расстроен тем, что не смог найти решение по-видимому простой проблемы, а также не смог эффективно использовать GDB для решения этой проблемы. Я использовал GDB в прошлом, но немного ржавый и просто не мог вспомнить или выяснить, как вводить аргументы командной строки И печатать значения переменных одновременно, даже когда я связал gdb с pid исполняемого файла. – haziz

3

, но к моему удивлению, он радостно солдат на

У вас есть три вложенных цикла. Новая строка завершит одну из внутренних циклов, в то время как крайняя петля будет счастливо продолжать (пока вы не нажмете Введитеlim раз).

Я могу дать вам подсказку: вы, вероятно, не должны использовать вложенные циклы для этого.

+0

Duh! Благодарю. Мне нужно подумать об этом на мгновение, но я подозреваю, что обращение логики внутренних петель к внешнему циклу может достичь желаемого эффекта. – haziz

+2

@haziz Нет, подумайте 'break'. –

Смежные вопросы