Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.11.2012, 15:25   #1
Sv.
Пользователь
 
Регистрация: 01.11.2012
Сообщений: 48
По умолчанию не могу понять, в чем ошибка

программа должна выводить общее количество слов (m) и количество слов (z), имеющих длину не менее М. иногда z выводит правильно, а иногда нет (на единицу больше). никак не могу понять в чем проблема

Код:
void main()
{int m=1, k=0, z=0, M;
char c=' ';
printf("Vvedite naimen'shuyu dlinu slova M: \n");
scanf("%d", &M);
printf("Vvedite text: \n");
while(c!='.')
{
scanf("%c", &c);
if(c==' ')
{m++;
k=0;}
else if(('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
{k++;}
if(k==M)
{z++;}
}
printf("m=%d z=%d", m, z);
getch();
}
Sv. вне форума Ответить с цитированием
Старый 01.11.2012, 15:33   #2
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Используйте отладчик, это помогает прояснять такие вопросы.

Перед точкой пробела не будет. m у Вас считается с 1 (и по окончании первого слова станет равно 2), поэтому для него ошибки нет. Также, если k стало равно M и следующий символ, положим, запятая - z увеличится ещё раз.
Abstraction вне форума Ответить с цитированием
Старый 01.11.2012, 15:49   #3
Sv.
Пользователь
 
Регистрация: 01.11.2012
Сообщений: 48
По умолчанию

Цитата:
Также, если k стало равно M и следующий символ, положим, запятая - z увеличится ещё раз.
а почему? в условии ведь нет этого. и как от этого избавиться?

Цитата:
Используйте отладчик
что за отладчик?
Sv. вне форума Ответить с цитированием
Старый 01.11.2012, 16:08   #4
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

1) Отладчик, скорее всего, входит в состав используемой Вами интегрированной среды разработки (MS Visual Studio, Borland C++ Bilder, Qt Creator или иной).
2) "Почему" - потому что Вы так написали программу. "Как избавиться" - натурально, переписать программу так, чтобы она работала корректно. Например:
Код:
1. m и z равно нулю, "признак слова" равен 0, "текущая длина" равна 0 пошли по строке.
  2. Если очередной символ - буква, то:
    3. "Признак слова" равен 1, "текущая длина" увеличена на 1.
  4. Иначе, если "признак слова" равен 1 (т.е. слово только что закончилось):
    5. "Признак слова" равен 0. m увеличено на 1.
    6. Если "длина слова" не меньше M, z увеличено на 1.
    7. Если символ - конец строки, выходим из цикла чтения строки.
    8. "длина слова" равна 0.
Легко видеть, что (поскольку C-строка кончается нуль-терминатором, не являющимся буквой) на пункт 5. мы попадаем ровно столько раз, сколько слов в строке. Столь же очевидна и корректность вычисления z.
Abstraction вне форума Ответить с цитированием
Старый 01.11.2012, 17:10   #5
Sv.
Пользователь
 
Регистрация: 01.11.2012
Сообщений: 48
По умолчанию

спасибо большое
я немного по-другому исправила и добавила еще вычисление процента слов, которые имеют длину не менее M

Код:
void main()
{int m=1, k=0, z=0, M; /*m-общее количество слов
z-количество слов, имеющих длину не менее M
k-количество символов*/
double X;
char c=' ';
printf("Vvedite naimen'shuyu dlinu slova M: \n");
scanf("%d", &M);
printf("Vvedite text zakanchivayushchiysya simvolom ".": \n");
while(c!='.')
{
scanf("%c", &c);
if(c==' ')
{m++;
k=0;}
else if(('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
{k++;}
if(k==M)
{z++;}
if(c=='.')
{z--;}
}
X=(z*100.)/m;
printf("m=%d z=%d X=%lf%%", m, z, X);
getch();
}
не могли бы вы еще подсказать, как это сделать через функции. как я понимаю мне здесь нужно две: одна возвращает значение m, а другая значение z
не знаю какой параметр задать и что должно быть в теле функции

Последний раз редактировалось Sv.; 01.11.2012 в 17:13.
Sv. вне форума Ответить с цитированием
Старый 01.11.2012, 17:23   #6
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Функция - это часть кода, которая принимает чётко очерченный набор данных и возвращает чётко очерченный набор результатов. Как общее правило, желательно, чтобы функция была регулярной - т.е. чтобы повторный её вызов с теми же аргументами приводил к тому же результату. Но основной Ваш код посимвольно читает строку, что нельзя просто так повторить (и это, в общем-то, правильно - строка может быть очень длинной). Есть в нём, однако, логически изолированные фрагменты. Например:
Код:
else if(('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
условие внутри if нуждается только в c и возвращает булево значение. Кроме того, это условие легко описать словами: "c - буква или цифра". Это типичное показание к выносу условия в отдельную функцию с говорящим названием.

На правах замечания к условию: либо приглашение к вводу неверно, либо строка "I. Love. Apples." вполне корректна (это текст, заканчивающийся символом '.') и содержит три слова, тогда как Ваша программа насчитает только одно.
Abstraction вне форума Ответить с цитированием
Старый 01.11.2012, 17:45   #7
Sv.
Пользователь
 
Регистрация: 01.11.2012
Сообщений: 48
По умолчанию

Цитата:
На правах замечания к условию: либо приглашение к вводу неверно, либо строка "I. Love. Apples." вполне корректна (это текст, заканчивающийся символом '.') и содержит три слова, тогда как Ваша программа насчитает только одно.
по заданию слова разделяются только пробелами

то есть нельзя сделать, чтобы m и z считались в разных функциях?
Sv. вне форума Ответить с цитированием
Старый 01.11.2012, 18:02   #8
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

В принципе можно. Но для этого надо сначала считать строку в память и указатель на неё передавать в функции вычисления m и z. А для этого (поскольку память не резиновая) нужно заранее знать максимальную длину строки.
Строка при этом читается так:
Код:
const int MAX_LENGTH = 80; //Максимальное число символов в строке
char string[MAX_LENGTH+1]; //Буфер для хранения строки. +1 - техническое требование, 
//в этом "дополнительном" символе размещается нуль-терминатор
fgets(string, MAX_LENGTH+1, stdin);//чтение строки из стандартного потока ввода (stdin),
//не более MAX_LENGTH символов плюс нуль-терминатор '\0'
Далее, вместо
Код:
while(c!='.')
{
scanf("%c", &c);
пишется
Код:
for(int i=0; string[i]!='.'; ++i){
  c = string[i];
Разумеется, можно просто подставлять string[i] всюду, где используется c.
Ну, а после этого можно взять код цикла, скопировать его в две функции, из одной убрать все упоминания об m, из другой - о z и M, и передать обоим в качестве аргумента string (той, которая считает z, понадобится ещё и M).
Abstraction вне форума Ответить с цитированием
Старый 01.11.2012, 18:07   #9
Sv.
Пользователь
 
Регистрация: 01.11.2012
Сообщений: 48
По умолчанию

Abstraction спасибо, вы мне очень помогли
Sv. вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
не могу понять в чем ошибка 6002theJuicy Visual C++ 4 23.05.2012 15:19
в чем ошибка? не могу понять... lexflax C++ Builder 1 28.01.2012 15:35
Си. Не могу понять в чем ошибка Gerbera Помощь студентам 2 12.07.2011 19:11
Не могу понять в чем ошибка.... Blonde Помощь студентам 0 21.05.2011 14:19
Не могу понять, в чем ошибка FlashProStar Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 01.12.2010 12:20