Вывести на экран слова, отличающиеся лишь порядком следования букв - C (СИ)
Формулировка задачи:
Всем здрасте! Заранее спасибо, если Вы даже просто подумали над моей проблемкой. В общем, к делу. Задача была таковой:
Дана строка (неизвестной длины) - вывести на экран слова (из данной строки), которые отличаются лишь порядком следования букв (мама - амма - амам и т.д.).
Я долго бился над решением и решил, что это можно сделать следующим образом: разделить строку на слова, в каждом слове буквы свести к одному регистру и отсортировать в алфавитном порядке(написал для этого функцию). Затем каждое слово сравнить таким образом с остальными и, как только найдется "пара" - вывести на экран. Вот мое скудное (наверняка некрасивое), но творение:
Прошу прощения за такое большое количество переменных, не обессудьте.
У меня здесь две проблемы (ну.. пока те, на которые я наткнулся) - 1)Не распознает слова = не выводит их на экран по отдельности (Выдает ошибку, вида "бла-бла-бла, адрес программы. Строка 49. Выражение (string !=NULL). бла-бла-бла")
2) Какая-то глупая ошибка в функции сортировки слова (или не глупая... я ее, в общем, найти не могу)..
Прошу помощи, если вам не трудно)
Я писал пока только для латинских букв.. и в строке не может быть ничего, окромя латинских букв и пробелов.. Потом, как с вашей божьей помощью разберусь с тем, что здесь неверно, пойду разбираться с русскими буквами и знаками препинания. Еще раз спасибо за внимание!
#include <locale>
#include <stdio.h>
#include <stddef.h>
#include <cstdio>
#include <conio.h>
#include <iostream>
#include <string.h>
#define maxn 10000
char S[maxn], *NewWord, **Words;
int i,f,N, WBeg,WEnd,WLeng, Numb, col, row, z;
char *expansion (char *Word) {char *FuncAr; char C; int j;
j=0;
while (Word[j]!='\0') j++;
FuncAr=(char*)calloc(j, sizeof (char));
for (int k = 0;k<=j;k++) FuncAr[k]=Word[k];
FuncAr=strlwr(FuncAr);
j=1;
while (j=1) {
j=0;
for (int k=1; k<=i;k++) { if (FuncAr[k]<FuncAr[k-1]) {j=1;
C=FuncAr[k];
FuncAr[k]=FuncAr[k-1];
FuncAr[k-1]= C;}}}
puts (FuncAr);
return FuncAr;
}
void main ()
{
setlocale (0,"russian");
do{
printf ("Введите вашу строку!\n");
gets_s (S);
i=0;
N=1;
while (S[i]!='\0' && N==1)
{if ((S[i]!=' ') && ! ((S[i]>='A' && S[i]<='Z') || (S[i]>='a' && S[i]<='z'))) /*|| ((unsigned char)S[i]>=(unsigned char)'А' && (unsigned char)S[i]<=(unsigned char)'я')*/
N=0;
i++;
}
if (N==0) printf ("Ввод некорректен. Попробуйте заново\n");
}while (N==0);
N=i;
i=0;
Words = (char**)calloc(N, sizeof(*Words));
Numb=1;
while (i<=N)
{
while (S[i]==' ') i++;
WBeg=i;
while (S[i]!=' ') i++;
WEnd=i;
WLeng=WEnd-WBeg;
Words[Numb]=(char*)calloc(WLeng, sizeof(char));
for (int k = 0, i=WBeg;i<=WEnd; i++, k++) {
Words[Numb][k]=S[i];}
Numb++;
printf ("Слово № %d :\n", Numb);
puts (Words[Numb]);
printf ("\n\n");
}
printf ("Результат:\n");
row=1;
while (row<=Numb) {
for (i=0;i<=Numb;i++) {if (strcmp(expansion(Words[row]),expansion(Words[i]))) puts(Words[row]);}
row++;}
free (Words);
system ("pause");
}Решение задачи: «Вывести на экран слова, отличающиеся лишь порядком следования букв»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//создаем массив из слов введенной строки
char **CreateArray(char line[], int len, int *cnt) {
int i = -1;
int count = 0;
char *buf = (char*) malloc(strlen(line) + 1); //копия исходной строки, уничтожается в процессе подсчета слов
strcpy(buf, line);
char *delims = " ,.-\n";
char *word = strtok(buf, delims);
while (word != NULL) {
++count; //считаем фактическое кво слов
word = strtok(NULL, delims);
}
free(buf);
*cnt = count;
char **words = (char**) malloc(count * sizeof(char*)); //выделяем память под count слов длиной len
while (++i < count)
words[i] = (char*) malloc(len);
word = strtok(line, delims); //заполняем массив словами из строки
i = -1;
while (word != NULL) {
strcpy(words[++i], word);
word = strtok(NULL, delims);
}
return words;
}
//печать массива слов
void ShowArray(char **words, int count) {
int i = -1;
while (++i < count)
printf("%s\n", words[i]);
}
//копия массива слов
char **CopyArray(char **words, int count) {
int i = -1;
char **copy = (char**) malloc(count * sizeof(char*));
while (++i < count) {
copy[i] = (char*) malloc(strlen(words[i]) + 1);
strcpy(copy[i], words[i]);
}
return copy;
}
//очистка памяти
void DestroyArray(char **words, int count) {
while (--count > -1)
free(words[count]);
free(words);
}
//своп двух букв для сортировки по алфавиту
void Swap(char *a, char *b) {
char t = *a;
*a = *b;
*b = t;
}
//сортировка слова по алфавиту
void SortLetters(char *word) {
int i, j, len = strlen(word);
for (i = 0; i < len - 1; i++)
for (j = i + 1; j < len; j++)
if (word[j] < word[i])
Swap(&word[i], &word[j]);
}
//собственно, решение задачи
void FindBros(char **words, int count) {
int i, j;
char **copy = CopyArray(words, count); //создаем копию массива слов
for (i = 0; i < count; i++)
SortLetters(copy[i]); //в каждом слове переставляем все буквы по алфавиту
int *mask = (int*) malloc(count * sizeof(int)); //маска: слово уже было найдено как "двойник по буквам" или нет
for (i = 0; i < count; i++)
mask[i] = 0; //сначала - все 0
for (i = 0; i < count - 1; i++) {
if (!mask[i]) //если i-ое слово еще не было "двойником по буквам"
{
printf("\n%20s: ", words[i]);
for (j = i + 1; j < count; j++)
if (strcmp(copy[i], copy[j]) == 0) //сравниваем i-ую и j-ую копию, т.е. буквенный состав слов words[i] и words[j]
{
printf("%20s ", words[j]); //если буквенный состав совпал - выводим words[j]
mask[j] = 1; //в маске помечаем j-ое слово как уже найденное в качестве "двойника"
}
}
}
DestroyArray(copy, count);
free(mask);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main() {
char str[BUFSIZ];
int len = 20, count = 0;
printf("Your string:\n");
fgets(str, BUFSIZ, stdin);
char **words = CreateArray(str, len, &count);
printf("\n\nYour words:\n");
ShowArray(words, count);
printf("\n\nWords with the same set of letters:\n");
FindBros(words, count);
DestroyArray(words, count);
getchar();
return 0;
}
Объяснение кода листинга программы
- Объявлены функции:
- CreateArray
- ShowArray
- CopyArray
- DestroyArray
- Swap
- SortLetters
- FindBros
- В функции CreateArray создается массив из слов введенной строки.
- В функции ShowArray выводится на экран массив слов.
- В функции CopyArray создается копия массива слов.
- В функции DestroyArray освобождается память, выделенная под массив слов.
- В функции Swap происходит обмен двух букв.
- В функции SortLetters сортируются буквы в слове по алфавиту.
- В функции FindBros осуществляется поиск слов с одинаковым набором букв.
- В функции main происходит ввод строки, разделение ее на слова, вывод списка слов, поиск слов с одинаковым набором букв, освобождение памяти.