Форум программистов, компьютерный форум, киберфорум
Fon Eberkopff
Войти
Регистрация
Восстановить пароль
Карта форума Блоги Сообщество Поиск Заказать работу  
Оценить эту запись

Лаба 9. Поиск слова в строке.

Запись от Fon Eberkopff размещена 16.11.2016 в 20:11
Обновил(-а) Fon Eberkopff 23.11.2016 в 15:09

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**********************************************************************
 * laba9_string.c          15.11.2016
 * 
 * Пользователь вводит с клавиатуры строку с разделителями в виде ' '.
 * Надо выделить слова в предложении. Далее у пользователя запрашивается
 * комбинация символов.
 * Нужно методом двоичного поиска выяснить, есть ли это слово в строке.
 **********************************************************************/
 
#include <stdio.h>  /* printf, putchar, puts, gets */
#include <string.h> /* strcmp */
#include <stdlib.h> /* calloc, free */
 
#define WORDS 10    // максимум слов в предложении
#define SYMBOLS 10  // максимум символов в слове
 
int  MyGetStr(char **);
void MySort(char **, int);
void MyBinarySearch(char **, int);
 
int main(void)
{
    int i, all_words;
    char **p;
    
// выделение памяти для вспомогательного массива указателей
    p = calloc(WORDS, sizeof(char *));
 
// выделение памяти под каждое слово в предложении 
    for(i = 0; i < WORDS; i++) {
        p[i] = calloc(SYMBOLS, sizeof(char));
    }
 
    printf("\n----- Введите слова (не более %d символов):\n", (WORDS * SYMBOLS) - 1);
// каждое слово в отдельный массив символов (создание словаря)
    all_words = MyGetStr(p);
 
    printf("\n----- Введены слова:\n");
    for(i = 0; i < all_words; i++) {
        putchar(' ');
        puts(p[i]);
    }
 
// сортировка массива указателей на слова
    MySort(p, all_words);
 
    printf("\n-----  Указатели на слова отсортированы:\n");    
    for(i = 0; i < all_words; i++) {
        putchar(' ');
        puts(p[i]);
    }
 
// запрос произвольного слова и поиск его в словаре
    MyBinarySearch(p, all_words);
 
// освобождение памяти
    for(i = 0; i < WORDS; i++)
        free(p[i]); 
    free(p);
 
    return 0;
}
 
 
/* Cчитывание потока символов и распределение по словам, 
 * пока не встретим символ конец строки '\n'  */
int MyGetStr(char **p) {
    const int OUT = 0;
    const int IN  = 1;
    int state = OUT;    
    int c, j = 0, i = 0;
 
    while((c = getchar()) != '\n') {
        if(c == ' ') {
            if(state == IN)
                p[i][j] = '\0';
            state = OUT; // устанавливаем состояние вне слова
        } else if(state == OUT) {
                    state = IN;
                    j = 0;
                    p[i][j] = c; // первый символ слова
                    i++;
                    j++;
        } else {
            p[i-1][j] = c; // последующие символы слова
            j++;
        }
    }
    p[i][j] = '\0'; // признак конца строки для каждого слова
    
    return i;
}
 
// сортировка массива указателей на слова
void MySort(char **p, int all_words)
{ 
    size_t i, j;
    
    for(i = 0; i < all_words - 1; i++) {
        for(j = 0; j < all_words - 1 - i; j++){
            if(strcmp(p[j], p[j+1]) > 0) {
                char *tmp = p[j];
                p[j] = p[j + 1];
                p[j + 1] = tmp; 
            }
        }
    }
}
 
 
// поиск слова в массиве методом двоичного поиска   
void MyBinarySearch(char **p, int all_words)
{   
    char find_word[SYMBOLS];
    size_t left, right, flag, index = 0;
 
    printf("\n Введите слово для поиска или '.' для завершения: ");
    gets(find_word);
    while(46 - find_word[0]) { // 46 - это код символа '.'
        left = flag = 0;
        right = all_words - 1;
        while(left <= right) {
            index = (left + right) >> 1;
            if(strcmp(find_word, p[index]) < 0)
                right = --index;        
            else if(strcmp(find_word, p[index]) > 0)
                left = ++index;         
            else{
                flag = 1;
                break;
            }
        }
        if(flag)
            printf("\n\tСлово есть в словаре\n");
        else
            printf("\n\tСлова в словаре нет\n");
        printf("\n Введите слово для поиска или '.' для завершения: ");
        gets(find_word);
    }
}
Всего комментариев 4
Комментарии
  1. Старый комментарий
    Аватар для HighPredator
    Возьмите за правило, если пишите на си,
    1) соблюдать сигнатуру главной функции
    2) не кастовать указатели на void в общем, и возвращаемые значения из аллокаторов в частности
    Запись от HighPredator размещена 17.11.2016 в 09:17 HighPredator вне форума
  2. Старый комментарий
    Аватар для Fon Eberkopff
    Цитата:
    Сообщение от HighPredator Просмотреть комментарий
    Возьмите за правило, если пишите на си,
    1) соблюдать сигнатуру главной функции
    2) не кастовать указатели на void в общем, и возвращаемые значения из аллокаторов в частности
    1)
    Я так понимаю Вы имеете в виду параметры (int argc, char* argv[]). Но ведь в мою программу при её запуске ничего передовать не надо. И в то же время мне не нужно идентифицировать функцию main среди других одноимённых функций с различными параметрами (перегрузка в С++).
    Почему тогда мне нужно указывать параметры (int argc, char* argv[]) в случае моей программы?
    ---------
    2)
    Мне 2-ой совет не совсем понятен. Что значит "кастовать указатели на void"?
    Нашёл, что кастовать - "комп. жарг. осуществлять преобразование типов данных".
    Сalloc возвращает мне не типизированный указатель void *, а я его привожу к указателю на указатель на char (char **) в строке 27 и к указателю на char (char *) в строке 30.
    Мне не надо было этого делать? Почему?
    Запись от Fon Eberkopff размещена 17.11.2016 в 15:17 Fon Eberkopff вне форума
    Обновил(-а) Fon Eberkopff 17.11.2016 в 15:18
  3. Старый комментарий
    Аватар для HighPredator
    Цитата:
    Я так понимаю Вы имеете в виду параметры (int argc, char* argv[])
    Не совсем.
    Цитата:
    Но ведь в мою программу при её запуске ничего передовать не надо.
    Вот. Стандратом языка на текущий момент разрешены следующие формы главной функции:
    C
    1
    2
    
    int main(void);
    int main(int argc, char* argv[]);
    Первый кейс ваш. А вообще, когда вы не указываете void в скобках, то это означает, что функция может принимать любое их число. Пример: http://rextester.com/IDK92605

    Цитата:
    Мне не надо было этого делать? Почему?
    Если коротко, то в си указатель на void всегда принудительно приводится к нужному типу (в отличие от С++ например, где этого нет). Поэтому, каст избыточен раз, и может привести к ошибкам два. Подробнее почитайте здесь: https://www.cyberforum.ru/c-be... 30688.html
    Запись от HighPredator размещена 18.11.2016 в 08:37 HighPredator вне форума
  4. Старый комментарий
    Аватар для Fon Eberkopff
    1) с сигнатурой разобрался (нашёл стандарт, увидел описание main + провёл пробы с Вашим примером с различным числом параметров).
    2) С кастом указателей пока полностью разобраться не могу, так как после ряда изменений (в т.ч. не связанных с приведением указателей) программа стала не адекватно завершаться. Я эту проблему описал в разделе Си для начинающих.
    А тот факт, что не надо кастовать указатели на void я вижу в целом ряде современных источников и сам стараюсь разобраться в этих вопросах глубже.

    Спасибо Вам за рекомендации по коду ))
    Запись от Fon Eberkopff размещена 22.11.2016 в 13:49 Fon Eberkopff вне форума
    Обновил(-а) Fon Eberkopff 22.11.2016 в 13:51
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru