Поиск в тексте символов (c++)

  • Автор темы o1ps
  • Дата начала
Статус
Закрыто для дальнейших ответов.
O

o1ps

#1
Возникла задача : Задан текст, состоящий из слов, записанных через запятые, и заканчивающийся точкой.
Длина текста не больше 150 символов, могут быть использованы любые символы. Словом
считается после-довательность символов, не содержащая пробел. Сформировать строку из
5-символьных слов, несо-держащих букву s. Получить массив кубов цифровых слов.


Вот код, который мне удалось реализовать:
Код:
//#include "stdafx.h"
#include <stdlib.h>
// для функции exit()

#include <string.h>
#include <iostream.h>
#include <cstdio>
// для функций работы с файлами

void main(void) {
char
text[149],	// загруженный из файла текст

*_word,	// рабочая переменная для корректного
// разделения строки на слова

**words,	// здесь будут храниться все слова из строки

fourSW[150], // в этом массиве будут храниться слова длиной в 4
// символа, содержащие буквы и цифры

**repeatWord;
// этот массив будет содержать повторяющиеся слова

words = new char*[150];
repeatWord = new char*[150];

int
i,	//
j,	// счётчики циклов
k,	//

word=0,		// количество слов в загруженной строке

lengths[150],		// длины каждого слова

digitPos=0,		// рабочая переменная, которая будет содержать
// информацию о словах содержащих цифры

repeat[150],		// количество повторений для каждого слова

squares[150][3],	// кубы цифровых слов

sq=0,			// количество цифровых слов

repeats=0;		// общее количество различных слов в тексте

FILE *fp;	// указатель на дескриптор файла

/* Нижеследующие переменные созданы для показа умения работы со строковыми функциями */
char text1[9]="Proverka";
char text2[10]="Propil'on";
char *p;

if ((fp = fopen("data.txt", "r")) == NULL) goto fileNotExists;
// открываем файл, если не удаётся - уходим в ошибку

fread(&text, sizeof(char), 150, fp);
cout << "Loaded text: " << text << endl << endl;
fclose(fp);
// читаем из файла 150 символов, выводим текст, закрываем файл

/* следующий блок делит считанную строку на массив слов, с которым
гораздо удобнее работать */
do {
if (word==0) {
_word = strtok(text, ",");
} else {
_word = strtok(NULL, ",");
}	// для определения каждого последующего слова используется
// функция strtok()

if (_word == NULL) break;

word++;
words[word] = new char[strlen(_word)];
words[word] = _word;
lengths[word] = strlen(_word);
// заносим слово в массив words[], а его длину - в lengths[]
} while (1);

cout << endl << "Words (length = 5) with digits and characters:" << endl;

strcpy(fourSW, "");
/* следующий блок кода найдёт все слова, содержащие и буквы и цифры,
и не имеющие при себе буквы s */
for (i=1; i<=word; i++) {
digitPos=strcspn(words[i], "s");
// ищем, на какой позиции встречается буква в слове
if (atoi(words[i])==0 && digitPos>0 && digitPos!=lengths[i] && lengths[i]==4) {
strcat(fourSW, words[i]);
strcat(fourSW, ", ");
}
}
cout << fourSW << endl << endl;
// выводим найденное

/* следующие блок кода ищет все повторяющиеся слова в тексте */
for(i=1; i<=word; i++) {
for(j=i; j<=word; j++) {
if (words[i]==words[j]) {
for(k=1; k<=repeats; k++) {
if (0==strcmp(words[i], repeatWord[k])) {
repeat[k]++;
goto n1;
}
}
repeats++;
repeatWord[repeats] = new char[lengths[i]];
repeatWord[repeats]=strdup(words[i]);
repeat[repeats]=1;
}
}
}

n1:
cout << "Repeat words: " << endl;
for (i=1; i<=repeats; i++)
if (repeat[i]>1)
cout << repeatWord[i] << " [" << repeat[i] << "], ";
// выводим слова, у которых количество повторений больше единицы

/* следующий блок кода находит цифровые слова и выводит их кубы */
cout << endl << endl << "Numeric words, and its squares: " << endl;

for (i=1; i<=word; i++) {
for(int j=0; j<lengths[i]; j++)
if (atoi(&words[i][j])==0 && words[i][j]!='0') goto n2;

sq++;
squares[sq][1]=atoi(words[i]);
squares[sq][2]=(atoi(words[i])*atoi(words[i])*atoi(words[i]));
n2:
cout << "";
}

for (i=1; i<=sq; i++)
cout << "Number: " << squares[i][1] << "; square: " << squares[i][2] << endl;

cout << endl << "------------------------------------------" << endl << endl;

// весь остальной код показывает умение работать со строковыми функциями

cout << "text1='" << text1 << "';" << endl;
cout << "text2='" << text2 << "';" << endl;

p=strstr(text1, "ov");

cout << "strcmp(text1, text2) = '" << strcmp(text1, text2) << "'" << endl;
cout << "strncmp(text1, text2, 3) = '" << strncmp(text1, text2, 3) << "'" << endl;
cout << "strlwr(text1) = '" << strlwr(text1) << "'" << endl;
cout << "strupr(text2) = '" << strupr(text2) << "'" << endl;
strrev(text1);	// функция заменяет строку
cout << "strrev(text1) = '" << text1 << "'" << endl;
strrev(text1);// возвращаем строку после вывода в исходное состояние
cout << "strspn(text2, 'ORP') = '" << strspn(text2, "ORP") << "'" << endl;
cout << "strstr(text1, 'rk') = '" << p << "'" << endl;
cout << "strchr(text1, 'r') = '" << strchr(text1, 'r') << "'" << endl;
cout << "strrchr(text1, 'r') = '" << strrchr(text1, 'r') << "'" << endl;

fp=fopen("output.txt", "w");
for(i=1; i<word; i++) {
fwrite(words[i], sizeof(char), lengths[i], fp);
fputs(", ", fp);
}
fclose(fp);

// удаляем все переменные, что мы использовали в процессе
delete repeatWord, repeats, text1, text2, text, _word, fourSW, words, lengths, digitPos, squares, sq, repeat, fp;

exit(0);

fileNotExists:
cout << "File with input data not found" << endl;
}

Не получается найти слова, не содержащие "S". Подскажите пожалуйста, будьте любезы, как доделать код для нормальной реализации данной задачи.
Буду очень признателен.
 

grigsoft

Well-known member
15.11.2005
735
0
#2
Код вставленный специально для показа умения работать со строковыми функциями - это мило. Жаль только весь остальной код это старательно опровергает.
Отвечая на вопрос - strchr тебя спасет с буквой S.
Замечания (можно не читать, если ты не будущий программист, а филолог выполняющий задание по информатике).
1. Сваленный в кучу код в main, в результате - goto. Все это должно быть разбито на небольшие функции и красиво записано.
2. Переменные должны всегда обнуляться при определении.
3. Чтение 150 символов в буфер длиной 149.
4. Что это?
Код:
words[word] = new char[strlen(_word)];
words[word] = _word;
А вот это?
Код:
repeatWord[repeats] = new char[lengths[i]];
repeatWord[repeats]=strdup(words[i]);
И вот это?
Код:
if (words[i]==words[j])
Явно стоит перечитать главу о работе со строками в С\С++.

5. Лень проверять, но кажется мне что atoi("21год") нормально вернет тебе 21. В любом случае atoi("год") == atoi("000"), так что не стоит ее использовать для поиска цифровых слов. strtol в лучшем случае.

И это не вдаваясь в своеобразный цикл поиска повторных слов и глубины алгоритмов - только то что глаз режет.
 
O

o1ps

#3
заменил
Код:
if ((fp = fopen("data.txt", "r")) == NULL) 
{
cout << "File with input data not found" << endl;
//  getch();
exit(0);
}
По поводу поиска слов без "s" переделал цикл:
Код:
for (i=1; i<=word; i++) {
if(strstr(words[i], "s")==NULL)
{
strcat(fourSW, words[i]);
strcat(fourSW, ", ");
}
}
Но вопрос - выводит все слова без "s". Подскажите пожалуйста как точно организовать цикл по подсчету количества символов, ибо необходимы только слова 5-символьной длины.
Буду очень признателен.
 
P

Pasha

#4
Для: o1ps
Цикл по подсчету количества символов? strlen.
 
O

o1ps

#5
Код:
if(strstr(words[i], "s")==NULL) 
if(strstr(words[i], "s")==NULL)) 
if (strlen(words[i], "s")==5)
??
 
Статус
Закрыто для дальнейших ответов.