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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 17.11.2012, 12:39   #41
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Пример разработки программы по методологии экстремального программирования (Test-driven development)

Покажу на простом примере. Нужно написать функцию, которая переводит все символы строки в верхний регистр (верхний регистр - это все символы строки "с большой буквы")

Например мы вводим:
Hello, World!

А получаем:
HELLO, WORLD!

Итак приступим. Добавим к проекту следующие файлы (не забываем подключить CuTest.h и CuTest.c (скачать с этого сайта: http://cutest.sourceforge.net/)):

main.c
Код:
#include <stdio.h>
#include "CuTest.h"

CuSuite* StrUtilGetSuite();

void RunAllTests(void) {
    CuString *output = CuStringNew();
    CuSuite* suite = CuSuiteNew();

    CuSuiteAddSuite(suite, StrUtilGetSuite());

    CuSuiteRun(suite);
    CuSuiteSummary(suite, output);
    CuSuiteDetails(suite, output);
    printf("%s\n", output->buffer);
}

int main(void)
{
    RunAllTests();

    return 0;
}
StrUlil.c
Код:
#include <string.h>
#include <ctype.h>
#include "CuTest.h"

char* StrToUpper(char* str) {
    return str;
}

void TestStrToUpper(CuTest *tc) {
    char* input = strdup("hello world");
    char* actual = StrToUpper(input);
    char* expected = "HELLO WORLD";
    CuAssertStrEquals(tc, expected, actual);
}

CuSuite* StrUtilGetSuite() {
    CuSuite* suite = CuSuiteNew();
    SUITE_ADD_TEST(suite, TestStrToUpper);
    return suite;
}
Видим, что в файле есть только заготовка для будущей функции, которая называется StrToUpper. Она сейчас не переводит все буквы строки в верхний регистр, а возвращает то, что приняла на входе.

Вызываем StrToUpper и выполняем сравнение:
Код:
void TestStrToUpper(CuTest *tc) {
    char* input = strdup("hello world");
    char* actual = StrToUpper(input);
    char* expected = "HELLO WORLD";
    CuAssertStrEquals(tc, expected, actual);
}
input - это строка с входными данными для исследуемой программы
expected - это строка с ожидаемыми данными
actual - это выходными данными от исследуемой программы

То есть мы передаём в функцию StrToUpper строку "hello world" и ожидаем получить строку "HELLO WORLD". Но так как функция StrToUpper в данном исполнении просто возвращает то, что приняла, то мы на выходе этой функции получим "hello world", что и будет замечено при запуске тестов:



Наша задача избавиться от этого сообщения путём исправления функции StrToUpper. Но сначала добавим ещё тестов:

И запустим тестирование:



Исправить ситуацию можно только написанием правильной функции StrToUpper:

Код:
char* StrToUpper(char* str) {
    char* p;
    for (p = str ; *p ; ++p) *p = toupper(*p);
    return str;
}
Запускаем тестирование:



Заказчику можно поставлять ПО прямо с модульными тестами. А запускать модульное тестирование, например, с ключом --test. Удобно производить доработку и контролировать ПО с помощью запуска тестирования. Всегда можно добавлять дополнительные тесты. При добавлении нового файла к проекту, функции этого файла также тестируются, как и в рассмотреном примере. Более подробно написано в файле README.TXT framework'a CuTest с сайта: http://cutest.sourceforge.net/

Пример использования ключа -t для запуска модульного тестирования:

main.c
Код:
#include <stdio.h>
#include "CuTest.h"

CuSuite* StrUtilGetSuite();

void RunAllTests(void) {
    CuString *output = CuStringNew();
    CuSuite* suite = CuSuiteNew();

    CuSuiteAddSuite(suite, StrUtilGetSuite());

    CuSuiteRun(suite);
    CuSuiteSummary(suite, output);
    CuSuiteDetails(suite, output);
    printf("%s\n", output->buffer);
}

#include "StrUtil.h"

int main(int argc, char* argv[])
{
    int c, runtest = 0;

    while (--argc > 0 && (*++argv)[0] == '-')
        while (c = *++argv[0])
            switch (c) {
            case 't':
                runtest = 1;
                break;
            default:
                printf("illegal option %c\n", c);
                break;
            }

    if (runtest) {
        RunAllTests();
    }

    //
    // Here our code
    //

    return 0;
}
StrUtil.h
Код:
#ifndef STRUTIL_H
#define STRUTIL_H

char* StrToUpper(char* str);

#endif // STRUTIL_H
P.S. Чтобы в среде Eclipse добавить аргумент командной строки '-t' для debugger'а нужно перейти: Run -> Debug Configurations. Выбрать вкладку (x) = Arguments. И поле Program arguments написать: -t

Последний раз редактировалось 8Observer8; 17.11.2012 в 14:51. Причина: добавил содержимое файла StrUtil.h
8Observer8 вне форума Ответить с цитированием
Старый 17.11.2012, 13:14   #42
tungsten
Пользователь
 
Регистрация: 05.11.2012
Сообщений: 16
По умолчанию

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Я так понимаю, что вы разрабатываете программы в среде FreeBSD из командной строки.
Да, все верно, этакий трибьют авторам этой книги и языку в целом, ведь он написан для Unix для PDP, а FreeBSD ближе всего к изначальной концепции Юникс.
Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Вы пользуетесь консольным отладчиком? То есть, вы умеете выполнять программы пошагам в косольном отладчике?
Мне стыдно. Нет я никогда не пользовался отладчиком вообще. Выполнять программу по шагам я пробовал в универе когда изучали ассемблер.
В общем то цель моих работ - использовать только командную строку без ГУЁв и пообвыкнуть в консоли. А в идеале если была бы настоящая PDP-11 и первая редакция этой книги я бы использовал именно такую комбинацию. Но за неимением...
Быть может я когда нибудь и буду участвовать в разработке каких либо приложений, тогда безусловно мне понадобятся среды разработки и прочие удобства, а пока только для удовольствия.
Все же GDB изучить думаю необходимо, но на экране монитора читать неудобно, думаю должны быть печатные книги.
tungsten вне форума Ответить с цитированием
Старый 17.11.2012, 13:37   #43
tungsten
Пользователь
 
Регистрация: 05.11.2012
Сообщений: 16
По умолчанию

ну а последнее сообщение скорее всего не для меня адресовано :D
в коде я не разобрался, есть символы звездочки я не знаю что это.
Мне пока рано прикручивать дополнительные процедуры из внешних файлов и использовать их. Я пока на уровне упражнения 1.22
tungsten вне форума Ответить с цитированием
Старый 17.11.2012, 13:46   #44
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Не обращайте внимания. Это и для вас тоже. Но только для будущего. У вас хороший темп. И модульное тестирование вам совсем не нужно сейчас. Я его буду использовать для тестирования ваших решений. Это я больше для себя написал, чтобы не забыть. Работайте так, как задумано в учебнике. Авторы не зря так преподносят материал. Ничего лишнего! Используйте только то, что "известно" к моменту выполнения задания.

P.S. Git (не EGit) - консольный. Eго Linus Torvalds придумал. Для совместных разработок - это очень необходимая вещь. POSIX - значит git есть для всех unix-подобных систем.

Последний раз редактировалось 8Observer8; 17.11.2012 в 14:12.
8Observer8 вне форума Ответить с цитированием
Старый 19.11.2012, 12:14   #45
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Комментарий к сообщению о TDD

После фразы:
Цитата:
Наша задача избавиться от этого сообщения путём исправления функции StrToUpper. Но сначала добавим ещё тестов:
Файл StrUtil.c должен быть таким:
Код:
#include <string.h>
#include <ctype.h>
#include "CuTest.h"

char* StrToUpper(char* str) {
    char* p;
    for (p = str ; *p ; ++p) *p = toupper(*p);
    return str;
}

void TestStrToUpper(CuTest *tc) {
    char* input = strdup("hello world");
    char* actual = StrToUpper(input);
    char* expected = "HELLO WORLD";
    CuAssertStrEquals(tc, expected, actual);
}

void TestStrToUpper_EmptyString(CuTest *tc) {
    char* input = strdup("");
    char* actual = StrToUpper(input);
    char* expected = "";
    CuAssertStrEquals(tc, expected, actual);
}

void TestStrToUpper_UpperCase(CuTest *tc) {
    char* input = strdup("HELLO WORLD");
    char* actual = StrToUpper(input);
    char* expected = "HELLO WORLD";
    CuAssertStrEquals(tc, expected, actual);
}

void TestStrToUpper_MixedCase(CuTest *tc) {
    char* input = strdup("HELLO world");
    char* actual = StrToUpper(input);
    char* expected = "HELLO WORLD";
    CuAssertStrEquals(tc, expected, actual);
}

void TestStrToUpper_Numbers(CuTest *tc) {
    char* input = strdup("1234 hello");
    char* actual = StrToUpper(input);
    char* expected = "1234 HELLO";
    CuAssertStrEquals(tc, expected, actual);
}

CuSuite* StrUtilGetSuite() {
    CuSuite* suite = CuSuiteNew();
    SUITE_ADD_TEST(suite, TestStrToUpper);
    SUITE_ADD_TEST(suite, TestStrToUpper_EmptyString);
    SUITE_ADD_TEST(suite, TestStrToUpper_UpperCase);
    SUITE_ADD_TEST(suite, TestStrToUpper_MixedCase);
    SUITE_ADD_TEST(suite, TestStrToUpper_Numbers);
    return suite;
}
8Observer8 вне форума Ответить с цитированием
Старый 22.11.2012, 17:04   #46
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Решил потренироваться на упражнениях из книги K&R в разработке по TDD. В TDD принцип такой: пишем заглушку для функции, потом - тесты. Естественно, что первый запуск тестов даст отрицательный результат. И мы пишем тело нашей функции, чтобы тесты стали положительные.


Инструментарий
- среда NetBeans 7.1.2 http://netbeans.org/downloads/ (можно, наверное, сразу для С и С++ скачать, но я так не пробовал, так как мне и Java нужна)
- CuTest http://cutest.sourceforge.net/ (к каждому своему проекту нужно подключать два файла: CuTest.h и CuTest.c)


Плагин С и С++ для NetBeans

Для разработки программ в NetBeans на C и С++ нужно поставить плагин. На стартовой странице есть ссылка, где описано, как поставить плагин и отладчик dbg (см. рисунок ниже) Для удобства, вот эта ссылка: http://netbeans.org/kb/trails/cnd.ht...gn=welcomepage




CUnit

Я ещё поставил CUnit. Как я понял, эта основа подходит и для разработки C++ классов. Описание, того, как поставить CUnit в NetBeans находится по ссылке выше, в секции: Developing C and C++ Projects (см. рисунок ниже) Для удобства, вот эта ссылка: http://netbeans.org/kb/docs/cnd/c-unit-test.html



Я сразу не до конца понял, как ставить CUnit. Ответы на все свои вопросы я нашёл здесь (см. сообщения от ysim, особенно последнее): http://forums.netbeans.org/post-91875.html


CuTest

Я буду использовать CuTest (эта основа только для С программ). Ещё раз повторюсь: CuTest http://cutest.sourceforge.net/ (к каждому своему проекту нужно подключать два файла: CuTest.h и CuTest.c)


Git

В NetBeans есть Git. Очень удобно сохранять версии разрабатываемой программы. В меню: Team->Git->Initialize->выбираем хранилище. Теперь, чтобы сохранить файл в хранилище, нужно в меню: Team->Summit->вводим комментарий->нажимаем Commit


Установка аргументов командной строки

File->Project Properties (project name)->Run->Run Command->дописываем после "${OUTPUT_PATH}" аргументы командной строки, например: -t

Последний раз редактировалось 8Observer8; 22.11.2012 в 17:06.
8Observer8 вне форума Ответить с цитированием
Старый 22.11.2012, 17:24   #47
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Упражнение 1.20. Напишите программу detab, которая бы заменяла символы табуляции во входном потоке соответствующим количеством пробелов до следующей границы табуляции. Предположим, что табуляция имеет фиксированную ширину n столбцов. Следует ли сделать n переменной или символическим параметром?

Мне понравился следующий ответ, там detab сделали отдельной функцией: http://clc-wiki.net/wiki/K%26R2_solu..._1:Exercise_20


Detab.h
Код:
#ifndef DETAB_H
#define DETAB_H

void Detab(char to[], char from[]);

#endif // DETAB_H

Detab.c
Код:
#include <string.h>
#include <ctype.h>
#include "CuTest.h"

#define TABWIDTH 4      /* tabsize */

/* detab: replaces tabs with blanks */
void Detab(char to[], char from[])
{
    int i, j, n;

    i = j = n = 0;
    while ((to[j] = from[i]) != '\0') {
        if (to[j] == '\t')
            for (n = 0; n < TABWIDTH; ++n, ++j)
                to[j] = ' ';
        else
            ++j;
        ++i;
    }
}

#define BSIZE 100

void TestDetab(CuTest *tc)
{
    char* input = strdup("		fd");
    char actual[BSIZE];
    char* expected = "        fd";

    Detab(actual, input);
    CuAssertStrEquals(tc, expected, actual);
}

CuSuite* StrUtilGetSuite()
{
    CuSuite* suite = CuSuiteNew();
    SUITE_ADD_TEST(suite, TestDetab);
    return suite;
}

main.c
Код:
#include <stdio.h>
#include "CuTest.h"

CuSuite* StrUtilGetSuite();

void RunAllTests(void)
{
    CuString *output = CuStringNew();
    CuSuite* suite = CuSuiteNew();

    CuSuiteAddSuite(suite, StrUtilGetSuite());

    CuSuiteRun(suite);
    CuSuiteSummary(suite, output);
    CuSuiteDetails(suite, output);
    printf("%s\n", output->buffer);
}

#include "Detab.h"

int main(int argc, char* argv[])
{
    int c, runtest = 0;

    while (--argc > 0 && (*++argv)[0] == '-')
        while (c = *++argv[0])
            switch (c) {
            case 't':
            	runtest = 1;
                break;
            default:
                printf("illegal option %c\n", c);
                break;
            }

    if (runtest) {
        RunAllTests();
    }

    //
    // Here our code
    //

    return 0;
}

P.S. Для запуска тестов нужен ключ: -t
8Observer8 вне форума Ответить с цитированием
Старый 09.07.2015, 00:50   #48
Wonz
Новичок
Джуниор
 
Регистрация: 09.07.2015
Сообщений: 1
По умолчанию Упражнение 1.14 выводит частоту ввода символов снизу вверх

Код:
/* A program to print vertical histograms.
*****************************************/
#include <stdio.h>

#define HIGHT 40 
#define VAL 48
#define VAL2 16

int main(void)
{
	int chr;
	float  nletters[VAL];
	int index;

	index = 0;
	/* set all array-elements to zero */
	while (index<VAL)
		nletters[index++] = 0;

	/* INPUT */
	
	index = 0;
	system("cls"); // clean console
	puts("Enter your input:");
	while ((chr = getchar()) != EOF) {
		if ((chr >= 'a' & chr <= 'z') || (chr >= 'A' & chr <= 'Z')) {
			++nletters[index];
		}
		else {
		
			++index;
		}
	}

	/*search frequencies*/
	int  frequency2[VAL2];
	int chr2;
	int index2;
	int next = 1, next2 = 2;
	for (index2 = 0; index2 < VAL2; ++index2) {
		frequency2[index2] = ((nletters[index] + nletters[next] + nletters[next2])/3);
		++index;
		++next;
		++next2;
	}

	/* OUTPUT */
	int j;

	system("cls"); // clean console
	for (j = HIGHT; j > 0; j--) {
		index2 = 0;
		while (index2 < VAL2) {
			if (frequency2[index2] >= j)
				putchar('*');
			else
				putchar(' ');
			++index2;
		}
		putchar('\n');	
	}
	printf("Your histogram.\n");

	return 0;
}

Последний раз редактировалось Stilet; 09.07.2015 в 08:27.
Wonz вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Упражнения c# veter48 Помощь студентам 0 12.07.2011 18:53
[Си] Упражнения Fobo5 Помощь студентам 1 02.02.2011 21:22
(С) Простое упражнение из Кернигана, Ричи. Пробелы Матвейка Помощь студентам 1 07.06.2009 12:37
Упражнения делфи MAKEDON Свободное общение 1 26.08.2008 02:31