Доброго времени суток, уважаемые!
На старости лет возникла необходимость переписать часть имеющихся наработок на perl/pascal на языке Си - "политика партии" поменялась, плюс кое-где возникают проблемы с производительностью. Плюс есть желание к саморазвитию. Засел опять за книги, но дело идёт туго, Си для меня оказался очень причудливым языком, в особенности в части работы со строковыми данными, а как раз обработка строк в моих программах - краеугольный камень.
Для начала попытался написать несколько функций, которые занимаются подсчетом лексем в строке, вычисляют позицию заданной лексемы в строке и извлекают из строки лексему по порядковому номеру. И вроде бы всё даже работает, но поскольку некоторые моменты работы с указателями я постиг интуитивно, хотелось бы услышать мнение более опытных программистов о качестве данного кода, какие ошибки я мог допустить, и т.п. В общем - посмотрите, пожалуйста, и прокомментируйте, что стоит изменить-исправить.
Заранее спасибо.
Да, ещё момент - возможно, я изобретаю велосипед (хотя что-то не находил пока готовых библиотек с таким функционалом) - если так, то с благодарностью приму ссылки на готовенькое-проверенное, и тем не менее, все равно прошу прокомментировать мой код - учиться-то надо...
Собственно, код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_BUFFER 256 // максимальная длина строки
#define WD " ,.:;?!\t\n\r\"\"\'" // символы-разделители
// Функции для работы с лексемами
int wordcount(const char *str, const char *worddelim)
/*
Возвращает число лексем в строке str, разделенных разделителями worddelim
*/
{
int i, count, len;
count = i = 0;
len = strlen(str);
while (i<=len)
{
while ((i<=len) && (strchr(worddelim, str[i]) != NULL)) i++; // пока текущий символ из worddelim, двигаемся к концу
if (i<=len) count++; // начало лексемы, увеличиваем счётчик лексем
while ((i<=len) && (strchr(worddelim, str[i]) == NULL)) i++; // пока текущий символ НЕ из worddelim, двигаемся к концу
}
return count;
}
int wordpos(const unsigned int n, const char *str, const char *worddelim)
/*
Возвращает позицию лексемы номер n в строке str с разделителями worddelim
Если лексемы номер n не существует, возвращает -1
*/
{
int i, count, len;
count = i = 0;
len = strlen(str);
while ((i<=len) && (count != n))
{
while ((i<=len) && (strchr(worddelim, str[i]) != NULL)) i++; // пока текущий символ из worddelim, двигаемся к концу
if (i<=len) count++; // начало лексемы, увеличиваем счётчик лексем
if (count != n) // если это не лексема номер n - ищем следующую.
while ((i<=len) && (strchr(worddelim, str[i]) == NULL)) i++; // пока текущий символ НЕ из worddelim, двигаемся к концу
else
return i; // это лексема номер n - возвращаем её позицию
}
return -1; // нет лексемы с номером n - возвращаем -1
}
char *extractword(const unsigned int n, char *str, char *worddelim)
/*
Извлекает лексему номер n из строки str с разделителями worddelim и возвращает указатель на нее
Если лексемы номер n нет, возвращает NULL
*/
{
int i, j, len;
char *word;
word = NULL;
len = strlen(str);
i = wordpos(n, str, worddelim); // ищем позицию лексемы номер n
if (i == -1) return word; // лексемы номер n нет - возвращаем NULL
if (wordpos(n+1, str, worddelim) != -1) j = wordpos(n+1, str, worddelim)-i;
// лексема не последняя - ее длина равна позиция следующей лексемы минус позиция искомой лексемы
else j = len - i;
// лексема последняя - ее длина равна длина строки минус позиция искомой лексемы
word = (char *) calloc(j+1, sizeof(char)); // выделяем память под искомую лексему - длина лексемы плюс '\0'
j = 0;
while ((i<len) && (strchr(worddelim, str[i]) == NULL)) word[j++] = str[i++];
word[strlen(word)] = '\0'; // копируем лексему из строки str во временную переменную word и завершаем ее '\0'
return word;
}
// Проверяем, как это работает
int main()
{
int i, wcount;
char *s, *d1;
s = (char *) calloc(STR_BUFFER, sizeof(char));
d1 = (char *) calloc(STR_BUFFER, sizeof(char));
strncpy(s, "Hello, my crazy world!", STR_BUFFER);
printf(" String - \"%s\", delimeters - \"%s\"\n\n", s, WD);
wcount = wordcount(s, WD);
printf(" Word count - %u\n\n", wcount);
for (i = 1; i <= 5; i++)
{
printf(" Word number %i start position - %i\n", i, wordpos(i, s, WD));
}
printf("\n");
for (i = 1; i <= wcount; i++)
{
d1 = extractword(i, s, ". ");
printf(" Word number %d - %s\n", i, d1);
}
free(s); free(d1);
return 0;
}
Результат:
|
---|
String - "Hello, my crazy world!", delimeters - " ,.:;?! ""'"
Word count - 4
Word number 1 start position - 0 Word number 2 start position - 7 Word number 3 start position - 10 Word number 4 start position - 16 Word number 5 start position - -1
Word number 1 - Hello, Word number 2 - my Word number 3 - crazy Word number 4 - world!
|