So given a string of up to 7 letters, I need to find every permutation of that string (with and without all the letters) and then check if any of those permutations can be found in my dictionary.txt file, and print the ones that match. So basically, if the user inputs "try," the permutations would be try, tr, tyr, ty, t, rty, etc., and then check if any of them match words in the txt file. I tried to do this using strncopy and strcmp, but the program doesn't always correctly deduce that two things are equal, it takes forever to run, and there's a bug where it counts having zero letters as a permutation of the original string.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100 /* number of words in dictionary.txt */
#define MAX 7 /* max number of letters in given string */
/* function to swap values at two pointers */
void swap(char *x, char *y){
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* function to find permutations of the string */
void permute(char *letters, int l, int r){
if (l == r){
char *a[SIZE];
FILE *file = fopen("dictionary.txt", "r");
char target[MAX_2];
memset(target, '\0', sizeof(target));
for (int i = 0; i < SIZE; i++){
a[i] = malloc(100000);
fscanf(file, "%s", a[i]);
}
for (int i = 0; i < 10; i++){
for (int j = 0; j < r - 1; j++){
strcpy(target, a[i]);
if (strcmp(target, &letters[i]) == 0){
printf("%s\n", target);
printf("%s\n", letters);
printf("Match\n");
}
/*else if (strcmp(target, &letters[i]) != 0){
printf("%s\n", target);
printf("%s\n", letters);
printf("Not a match\n");
}
*/
}
}
for (int i = 0; i < SIZE; i++){
free (a[i]);
}
fclose(file);
}
else{
for (int i = l; i <= r; i++){
swap((tiles+l), (tiles+i));
permute(tiles, l+1, r);
swap((tiles+l), (tiles+i));
}
}
}
int main(){
/* initializing tile input */
char letters[MAX];
printf("Please enter your letters: ");
scanf("%s", letters);
/* finding size of input */
int size = strlen(letters);
/* finds all the permutation of the input */
/* parameters: string; start of the string; end of the string */
permute(letters, 0, size);
return 0;
}
Any help or suggestions to pinpoint what I'm doing wrong would be greatly appreciated.
As hinted in my comment, you can map all permutations of a string to a single code value, just by using the bits of a big enough unsigned integer as a bit set. Thus, the (same length) permutations of e.g. the word "try" all map to the same value.
As far as I understood your problem, you also want to match words, which start out with a substring of the wanted word. For that to work, you need to generated N such codes, if N is the number of letters, a word contains. I.e. For a three letter word, the code for the first letter, the first 2 letters and the code for all 3 letters.
Since reading from a file is probably not the problem, here the code, showcasing the "code based" string matching idea (which should be reasonably fast):
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_WORD_LENGTH 7
typedef uint32_t WordCode;
typedef struct WordCodes_tag {
size_t count;
WordCode codes[MAX_WORD_LENGTH];
} WordCodes_t;
bool word_to_code(const char* word,
size_t start,
size_t end,
WordCode* code) {
if ((end - start) > MAX_WORD_LENGTH)
return false;
*code = 0;
for (size_t i = start; i < end; i++) {
char c = word[i];
if ((c >= 'a') && (c <= 'z')) {
char bit = c - 'a';
WordCode mask = 1 << bit;
(*code) |= mask;
} else {
return false;
}
}
return true;
}
bool word_to_codes(const char* word, WordCodes_t* codes) {
if (NULL == codes)
return false;
if (NULL == word)
return false;
codes->count = 0;
size_t nchars = strlen(word);
if (nchars > MAX_WORD_LENGTH)
return false;
for (size_t len = nchars; len >= 1; len--) {
WordCode word_code;
if (word_to_code(word, 0, len, &word_code)) {
codes->codes[codes->count] = word_code;
codes->count++;
} else {
return false;
}
}
return true;
}
void show_word_codes(const WordCodes_t* codes) {
if (NULL == codes) return;
printf("(");
for (size_t i = 0; i < codes->count; i++) {
if (i > 0)
printf(", %d", codes->codes[i]);
else
printf("%d", codes->codes[i]);
}
printf(")\n");
}
bool is_match(const WordCodes_t* a, const WordCodes_t* b) {
if ((NULL == a) || (NULL == b))
return false;
if ((0 == a->count) || (0 == b->count))
return false;
const WordCodes_t *temp = NULL;
if (a->count < b->count) {
temp = a;
a = b;
b = temp;
}
size_t a_offset = a->count - b->count;
for (size_t i = a_offset, j = 0; i < a->count; i++, j++) {
if (a->codes[i] == b->codes[j])
return true;
}
return false;
}
int main(int argc, const char* argv[]) {
const char* wanted = "try";
const char* dictionary[] = {
"house", "mouse", "cat", "tree", "try", "yrt", "t"
};
size_t dict_len = sizeof(dictionary) / sizeof(char*);
WordCodes_t wanted_codes;
if (word_to_codes(wanted, &wanted_codes)) {
printf("word codes of the wanted word '%s': ", wanted);
show_word_codes(&wanted_codes);
for (size_t i = 0; i < dict_len; i++) {
WordCodes_t found_codes;
if (word_to_codes(dictionary[i],&found_codes)) {
printf("word codes of dictionary word '%s' (%s): ",
dictionary[i],
is_match(&wanted_codes, &found_codes) ?
"match" : "no match");
show_word_codes(&found_codes);
} else {
printf("word_to_codes(%s) failed!", dictionary[i]);
}
}
} else {
puts("word_to_codes() failed!");
return -1;
}
}
As function is_match() above shows, you need only compare the codes for the respective substring length. Thus, even if you have 2 sets of up to 7 numbers, you need only maximum 7 comparisons.
The output looks like this (which seems to make sense):
./search
word codes of the wanted word 'try': (17432576, 655360, 524288)
word codes of dictionary word 'house' (no match): (1327248, 1327232, 1065088, 16512, 128)
word codes of dictionary word 'mouse' (no match): (1331216, 1331200, 1069056, 20480, 4096)
word codes of dictionary word 'cat' (no match): (524293, 5, 4)
word codes of dictionary word 'tree' (match): (655392, 655376, 655360, 524288)
word codes of dictionary word 'try' (match): (17432576, 655360, 524288)
word codes of dictionary word 'yrt' (match): (17432576, 16908288, 16777216)
word codes of dictionary word 't' (match): (524288)
If you want to match the words in a dictionary against all partial permutations of a search term, you don't have to create all permutations. (The number of permutations n! grows very quickly with the length of the search term, n.)
Instead, it is easier to write a customized search function. You can make use of two strategies here:
A word w is a permutation of the search term s if both words are eaqual if the letters are sorted. For example, "integral" and "triangle" are anagrams of each other, because both sort to "aegilnrt".
You can skip letters in the search term when searching to account for partial anagrams. Because the search term and the word will be sorted, you know which ones to skip: The ones that are lexically "smaller" than the next letter in the word.
So your matching function should sort the words first and then compare the words character by character in such a way that characters from the search term can be skipped.
Here's code that does that:
int char_cmp(const void *pa, const void *pb)
{
const char *a = pa;
const char *b = pb;
return *a - *b;
}
bool partial_anagram(const char *aa, const char *bb)
{
char A[64];
char B[64];
const char *a = strcpy(A, aa);
const char *b = strcpy(B, bb);
qsort(A, strlen(A), 1, char_cmp);
qsort(B, strlen(B), 1, char_cmp);
while (*b) {
while (*a && *a < *b) a++;
if (*a != *b) return false;
a++;
b++;
}
return true;
}
Things to note:
Sorting is done with the function qsort from <stdlib.h>, for which you need a comparator function, in this case char_cmp.
The sorted strings are copies, so that the original strings are not modified. (The code above is unsafe, because it doesn't enforce that the length of the strings is less than 64 characters. Unfortunately, the function strncpy, which can accept a maximum buffer size, is not safe, either, because it can leave the buffer unterminated. A safe way to copy the strings would be snprintf(A, sizeof(A), "%s", aa), but I've kept the strcpy for, er, "simplicity".)
The function partial_anagram takes unsorted strings and sorts them. That makes for a clean interface, but it is inefficient when you want to test against the same search term repeatedly as in your case. You could change the function, so that it expects already sorted strings. This will reduce the function to just the loop and will place the responsibility of sorting to the caller.
If you really have a lot of searches, there is yet more room for optimization. For example, you could insert the sorted dictionary into a trie. Given that you original code read the whole file for each permutation, I guess you're not worried that much about performance. :)
I've put a working example online. The code above works with pointers. If you are more at ease with indices, you can rewrite the function:
bool partial_anagram(const char *aa, const char *bb)
{
char a[64];
char b[64];
unsigned i = 0;
unsigned j = 0;
strcpy(a, aa);
strcpy(b, bb);
qsort(a, strlen(a), 1, char_cmp);
qsort(b, strlen(b), 1, char_cmp);
while (b[j]) {
while (a[i] && a[i] < b[j]) i++;
if (a[i] != b[j]) return false;
i++;
j++;
}
return true;
}
Problem
One is using an algorithm that has exponentially growing run-time with the problem size. There are probably lots of ways to speed this up, but, as suggested by #SparKot, a trie, or prefix tree, is a particularly good fit. One can build a trie from an dictionary array of size n, assuming the length of the strings in your dictionary are bounded, in O(n log n). Looking up angrams in the worst-case, where the letters never run out, (ignoring the arbitrary 7 limit,) is still worst case O(n).
$ bin/trie AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ < Tutte_le_parole_inglesi.txt
build_index warning: duplicate "OUTSOURCING".
build_index warning: duplicate "OUTSOURCINGS".
Loaded 216553 trie entries.
AA
AAH
AAHED
AAHING
...
ZYTHUMS
ZYZZYVA
ZYZZYVAS
211929 words found.
Proposal
The reason a prefix tree is so effective, is it allows you to query prefixes as (even more) efficiently as lookup. With this, one can do a very effective branch-and-bound-style algorithm. That is, the longer the string, the less words it will be a prefix match to; if the string is not a prefix match for any of the words in the dictionary, one can rule out any longer strings and just not test them.
So my idea is, form a histogram with the Scrabble-string of length k in O(k). Then, recursively, add more and more letters, matching, until no dictionary entries are prefix matches of the string. This will run in (*I think) O(n log n + k), assuming a bound on the number of comparisons needed to distinguish words; ie, one's dictionary is not { a, aa, aaa, aaaa, aaaaa, aaaaaa, ... }.
Implementation
I use a PATRiCA tree. It is especially attractive because a lot of data is implicit; one can use a simple array to represent the leaves on a complete binary tree. Specifically, n leaves are already just the list of words in lexicographical order, we want to build an index of n - 1 branches. It requires a stop code; the null-termination in C is perfect. I don't have to create copies of everything and manage them. The below code first sets up a dynamic array, which is useful for input, then sets up a trie, then implements the algorithm.
#include <stdlib.h> /* EXIT malloc free qsort */
#include <stdio.h> /* printf */
#include <string.h> /* memmove memcpy */
#include <assert.h> /* assert */
#include <errno.h> /* errno */
#include <limits.h> /* UINT_MAX */
#include <ctype.h> /* isgraph */
/* Dynamic array. */
#define MIN_ARRAY(name, type) \
struct name##_array { type *data; size_t size, capacity; }; \
static int name##_array_reserve(struct name##_array *const a, \
const size_t min) { \
size_t c0; \
type *data; \
const size_t max_size = (size_t)-1 / sizeof *a->data; \
if(a->data) { \
if(min <= a->capacity) return 1; \
c0 = a->capacity < 7 ? 7 : a->capacity; \
} else { \
if(!min) return 1; \
c0 = 7; \
} \
if(min > max_size) return errno = ERANGE, 0; \
/* `c_n = a1.625^n`, approximation golden ratio `\phi ~ 1.618`. */ \
while(c0 < min) { \
size_t c1 = c0 + (c0 >> 1) + (c0 >> 3); \
if(c0 >= c1) { c0 = max_size; break; } /* Unlikely. */ \
c0 = c1; \
} \
if(!(data = realloc(a->data, sizeof *a->data * c0))) \
{ if(!errno) errno = ERANGE; return 0; } \
a->data = data, a->capacity = c0; \
return 1; \
} \
static type *name##_array_buffer(struct name##_array *const a, \
const size_t n) { \
if(a->size > (size_t)-1 - n) { errno = ERANGE; return 0; } \
return name##_array_reserve(a, a->size + n) \
&& a->data ? a->data + a->size : 0; \
} \
static type *name##_array_append(struct name##_array *const a, \
const size_t n) { \
type *b; \
if(!(b = name##_array_buffer(a, n))) return 0; \
return a->size += n, b; \
} \
static type *name##_array_new(struct name##_array *const a) \
{ return name##_array_append(a, 1); } \
static struct name##_array name##_array(void) \
{ struct name##_array a; a.data = 0, a.capacity = a.size = 0; return a; } \
static void name##_array_(struct name##_array *const a) \
{ if(a) free(a->data), *a = name##_array(); }
MIN_ARRAY(char, char)
/** Append a file, `fp`, to `c`, and add a '\0'.
#return Success. A partial read is failure. #throws[fopen, fread, malloc]
#throws[EISEQ] The text file has embedded nulls.
#throws[ERANGE] If the standard library does not follow POSIX. */
static int append_file(struct char_array *c, FILE *const fp) {
const size_t granularity = 4096;
size_t nread;
char *cursor;
int success = 0;
assert(c && fp);
/* Read entire file in chunks. */
do if(!(cursor = char_array_buffer(c, granularity))
|| (nread = fread(cursor, 1, granularity, fp), ferror(fp))
|| !char_array_append(c, nread)) goto catch;
while(nread == granularity);
/* File to `C` string. */
if(!(cursor = char_array_new(c))) goto catch;
*cursor = '\0';
/* Binary files with embedded '\0' are not allowed. */
if(strchr(c->data, '\0') != cursor) { errno = EILSEQ; goto catch; }
{ success = 1; goto finally; }
catch:
if(!errno) errno = EILSEQ; /* Will never be true on POSIX. */
finally:
if(fp) fclose(fp);
return success;
}
/* Trie is base-2 compact radix tree, described in <Morrison, 1968 PATRICiA>.
Specifically, this is a full binary tree. */
struct branch { unsigned skip, left; };
static const size_t skip_max = UINT_MAX, left_max = UINT_MAX;
MIN_ARRAY(branch, struct branch)
MIN_ARRAY(leaf, char *)
struct trie { struct branch_array branches; struct leaf_array leaves; };
static struct trie trie(void) { struct trie t;
t.branches = branch_array(), t.leaves = leaf_array(); return t; }
static void trie_(struct trie *const t) { if(t) branch_array_(&t->branches),
leaf_array_(&t->leaves), *t = trie(); }
/** From string `a`, extract `bit`, either 0 or 1. */
static int is_bit(const char *const a, const size_t bit) {
const size_t byte = bit >> 3;
const unsigned char mask = 128 >> (bit & 7);
return !!(a[byte] & mask);
}
/** #return Whether `a` and `b` are equal up to the minimum of their lengths'. */
static int is_prefix(const char *a, const char *b) {
for( ; ; a++, b++) {
if(*a == '\0') return 1;
if(*a != *b) return *b == '\0';
}
}
/** [low, high). */
struct range { size_t low, high; };
static int init_branches_r(struct trie *const t, size_t bit,
const struct range range) {
struct range r;
size_t skip = 0, left;
struct branch *branch;
assert(t && t->leaves.size);
assert(t->branches.capacity >= t->leaves.size - 1);
assert(range.low <= range.high && range.high <= t->leaves.size);
if(range.low + 1 >= range.high) return 1; /* Only one, leaf. */
/* Endpoints of sorted range: skip [_1_111...] or [...000_0_] don't care. */
while(is_bit(t->leaves.data[range.low], bit)
|| !is_bit(t->leaves.data[range.high - 1], bit)) {
if(skip == skip_max) return errno = ERANGE, 0;
bit++, skip++;
}
/* Binary search for the rightmost 0 (+1). */
r = range;
while(r.low < r.high) {
size_t m = r.low + (r.high - r.low) / 2;
if(is_bit(t->leaves.data[m], bit)) r.high = m; else r.low = m + 1;
}
if((left = r.low - range.low - 1) > left_max) return errno = ERANGE, 0;
/* Should have space for all branches pre-allocated. */
branch = branch_array_new(&t->branches), assert(branch);
branch->left = (unsigned)left;
branch->skip = (unsigned)skip;
bit++;
return (r.low = range.low, r.high = range.low + left + 1,
init_branches_r(t, bit, r)) && (r.low = r.high, r.high = range.high,
init_branches_r(t, bit, r)) /* && (printf("}\n"), 1) */;
}
/** Orders `a` and `b` by their pointed-to-strings. #implements qsort bsearch */
static int vstrcmp(const void *const a, const void *const b)
{ return strcmp(*(const char *const*)a, *(const char *const*)b); }
/** #param[a] A zero-terminated file containing words. Will be parsed and
modified.
#param[t] An idle tree that is initialized from `a`. Any modification of `a`
invalidates `t`.
#return Whether the tree initialization was entirely successful. */
static int build_trie(struct trie *const t, struct char_array *const a) {
struct range range;
size_t i;
char *cursor, *end, **leaf;
int is_run = 0;
/* Strict for processing ease; this could be made more permissive. */
assert(a && a->size && a->data[a->size - 1] == '\0'
&& t && !t->branches.size && !t->leaves.size);
for(cursor = a->data, end = a->data + a->size; cursor < end; cursor++) {
/* Fixme: 7-bit; mælström would be parsed as "m", "lstr", "m". */
if(!isgraph(*cursor)) {
*cursor = '\0', is_run = 0;
} else if(!is_run) {
if(!(leaf = leaf_array_new(&t->leaves))) return 0;
*leaf = cursor, is_run = 1;
}
}
if(!t->leaves.size) return errno = EILSEQ, 0; /* No parseable info. */
/* Sort and de-duplicate (inefficiently.) Want to treat it as an index. */
qsort(t->leaves.data, t->leaves.size, sizeof *t->leaves.data, &vstrcmp);
for(i = 1; i < t->leaves.size; i++) {
if(strcmp(t->leaves.data[i - 1], t->leaves.data[i]) < 0) continue;
fprintf(stderr, "build_index warning: duplicate \"%s\".\n",
t->leaves.data[i]);
memmove(t->leaves.data + i, t->leaves.data + i + 1,
sizeof *t->leaves.data * (t->leaves.size - i - 1));
t->leaves.size--, i--;
}
range.low = 0, range.high = t->leaves.size;
if(!branch_array_reserve(&t->branches, t->leaves.size - 1)
|| !init_branches_r(t, 0, range)) return 0;
assert(t->branches.size + 1 == t->leaves.size);
return 1;
}
/** #return In `t`, which must be non-empty, given a `prefix`, stores all leaf
prefix matches, only given the index, ignoring don't care bits.
#order \O(`prefix.length`) */
static struct range partial_prefix(const struct trie *const t,
const char *const prefix) {
size_t n0 = 0, n1 = t->branches.size, i = 0, left;
struct branch *branch;
size_t byte, key_byte = 0, bit = 0;
struct range range = { 0, 0 };
assert(t && prefix);
assert(n1 + 1 == t->leaves.size); /* Full binary tree. */
while(n0 < n1) {
branch = t->branches.data + n0;
bit += branch->skip;
/* '\0' is not included for partial match. */
for(byte = bit >> 3; key_byte <= byte; key_byte++)
if(prefix[key_byte] == '\0') goto finally;
left = branch->left;
if(!is_bit(prefix, bit++)) n1 = ++n0 + left;
else n0 += left + 1, i += left + 1;
}
assert(n0 == n1);
finally:
assert(n0 <= n1 && i - n0 + n1 < t->leaves.size);
range.low = i, range.high = i - n0 + n1 + 1;
return range;
}
/* #return Given a `prefix`, what is the range of matched strings in `t`. */
static struct range prefix(const struct trie *const t,
const char *const prefix) {
struct range range;
assert(t && prefix);
if(!t->leaves.size) goto catch;
range = partial_prefix(t, prefix);
if(range.low <= range.high)
if(!is_prefix(prefix, t->leaves.data[range.low])) goto catch;
goto finally;
catch:
range.low = range.high = 0;
finally:
return range;
}
/* Debug graph. */
/** Given a branch `b` in `tr` branches, calculate the right child branches.
#order \O(log `size`) */
static unsigned right_count(const struct trie *const tr,
const unsigned b) {
unsigned left, right, total = (unsigned)tr->branches.size, b0 = 0;
assert(tr && b < tr->branches.size);
for( ; ; ) {
right = total - (left = tr->branches.data[b0].left) - 1;
assert(left < total && right < total);
if(b0 >= b) break;
if(b <= b0 + left) total = left, b0++;
else total = right, b0 += left + 1;
}
assert(b0 == b);
return right;
}
/** #return Follows the branches to `b` in `tr` and returns the leaf. */
static unsigned left_leaf(const struct trie *const tr,
const unsigned b) {
unsigned left, right, total = (unsigned)tr->branches.size, i = 0, b0 = 0;
assert(tr && b < tr->branches.size);
for( ; ; ) {
right = total - (left = tr->branches.data[b0].left) - 1;
assert(left < tr->branches.size && right < tr->branches.size);
if(b0 >= b) break;
if(b <= b0 + left) total = left, b0++;
else total = right, b0 += left + 1, i += left + 1;
}
assert(b0 == b);
return i;
}
static void graph(const struct trie *const tr, const char *const fn) {
unsigned left, right, b, i;
FILE *fp = 0;
assert(tr && fn);
if(!(fp = fopen(fn, "w"))) { perror(fn); return; }
fprintf(fp, "digraph {\n"
"\tgraph [truecolor=true, bgcolor=transparent];\n"
"\tfontface=modern;\n"
"\tnode [shape=none];\n"
"\n");
if(!tr->branches.size) {
assert(!tr->leaves.size);
fprintf(fp, "\tidle;\n");
} else {
assert(tr->branches.size + 1 == tr->leaves.size);
fprintf(fp, "\t// branches\n");
for(b = 0; b < tr->branches.size; b++) { /* Branches. */
const struct branch *branch = tr->branches.data + b;
left = branch->left, right = right_count(tr, b);
fprintf(fp, "\ttree%pbranch%u [label = \"%u\", shape = circle, "
"style = filled, fillcolor = Grey95];\n"
"\ttree%pbranch%u -> ", (const void *)tr, b, branch->skip,
(const void *)tr, b);
if(left) fprintf(fp, "tree%pbranch%u [arrowhead = rnormal];\n",
(const void *)tr, b + 1);
else fprintf(fp,
"tree%pleaf%u [color = Gray85, arrowhead = rnormal];\n",
(const void *)tr, left_leaf(tr, b));
fprintf(fp, "\ttree%pbranch%u -> ", (const void *)tr, b);
if(right) fprintf(fp, "tree%pbranch%u [arrowhead = lnormal];\n",
(const void *)tr, b + left + 1);
else fprintf(fp,
"tree%pleaf%u [color = Gray85, arrowhead = lnormal];\n",
(const void *)tr, left_leaf(tr, b) + left + 1);
}
}
fprintf(fp, "\t// leaves\n");
for(i = 0; i < tr->leaves.size; i++) fprintf(fp,
"\ttree%pleaf%u [label = <%s<FONT COLOR=\"Gray85\">⊔</FONT>>];\n",
(const void *)tr, i, tr->leaves.data[i]);
fprintf(fp, "\n"
"\tnode [color = \"Red\"];\n"
"}\n");
fclose(fp);
}
/* Actual program. */
/* The input argument histogram. Used in <fn:find_r>. (Simple, but questionable
design choice.) */
static unsigned char hist[128];
static const size_t hist_max = UCHAR_MAX,
hist_size = sizeof hist / sizeof *hist;
static size_t words_found;
/** Branch-and-bound recursive function. */
static void find_r(const struct trie *const tr, char *const word) {
struct range r;
size_t len, i;
assert(word);
r = prefix(tr, word);
if(r.low >= r.high) return; /* Found nothing, we can bound this branch. */
if(!strcmp(word, tr->leaves.data[r.low])) { /* Found a match. */
printf("%s\n", word), words_found++;
if(++r.low == r.high) return;
}
len = strlen(word);
for(i = 0; i < hist_size; i++) {
unsigned char *freq;
if(!*(freq = hist + i)) continue;
(*freq)--;
word[len] = (char)i, word[len + 1] = '\0';
find_r(tr, word);
(*freq)++;
}
}
int main(int argc, char *argv[]) {
struct char_array dict = char_array();
struct trie tr = trie();
char *word;
size_t i;
int success = EXIT_FAILURE;
assert(CHAR_BIT == 8); /* C89 this value can change, assumes C99 value. */
if(argc != 2) { errno = EILSEQ;
fprintf(stderr, "Needs argument and dictionary input.\n"); goto catch; }
word = argv[1];
/* Load the dictionary from stdin and index it into a trie. */
if(!append_file(&dict, stdin) || !build_trie(&tr, &dict)) goto catch;
fprintf(stderr, "Loaded %lu trie entries.\n",(unsigned long)tr.leaves.size);
graph(&tr, "dictionary.gv");
/* Histogram the argument. */
for(i = 0; word[i] != '\0'; i++) {
unsigned char *freq;
if(word[i] & 0x80) continue; /* UTF-8 is not supported. :[ */
if(*(freq = hist + word[i]) == hist_max)
{ errno = ERANGE; goto catch; } /* "aaaaaaaaa..." x 5M? */
(*freq)++;
}
/* Might as well re-use the word now that we're finished with it; it's the
right length. */
*word = '\0', find_r(&tr, word);
fprintf(stderr, "%lu words found.\n", (unsigned long)words_found);
{ success = EXIT_SUCCESS; goto finally; }
catch:
perror("word");
finally:
trie_(&tr);
char_array_(&dict);
return success;
}
I can use the strtol function for turning a base36 based value (saved as a string) into a long int:
long int val = strtol("ABCZX123", 0, 36);
Is there a standard function that allows the inversion of this? That is, to convert a long int val variable into a base36 string, to obtain "ABCZX123" again?
There's no standard function for this. You'll need to write your own one.
Usage example: https://godbolt.org/z/MhRcNA
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *reverse(char *str)
{
char *end = str;
char *start = str;
if(!str || !*str) return str;
while(*(end + 1)) end++;
while(end > start)
{
int ch = *end;
*end-- = *start;
*start++ = ch;
}
return str;
}
char *tostring(char *buff, long long num, int base)
{
int sign = num < 0;
char *savedbuff = buff;
if(base < 2 || base >= sizeof(digits)) return NULL;
if(buff)
{
do
{
*buff++ = digits[abs(num % base)];
num /= base;
}while(num);
if(sign)
{
*buff++ = '-';
}
*buff = 0;
reverse(savedbuff);
}
return savedbuff;
}
One of the missing attributes of this "Convert long integer to base 36 string" is string management.
The below suffers from a potential buffer overflow when destination is too small.
char *long_to_string(char *destination, long num, int base);
(Assuming 32-bit long) Consider the overflow of below as the resultant string should be "-10000000000000000000000000000000", which needs 34 bytes to encode the string.
char buffer[33]; // Too small
long_to_string(buffer, LONG_MIN, 2); // Oops!
An alternative would pass in the buffer size and then provide some sort of error signaling when the buffer is too small.
char* longtostr(char *dest, size_t size, long a, int base)
Since C99, code instead could use a compound literal to provide the needed space - without calling code trying to compute the needed size nor explicitly allocate the buffer.
The returned string pointer from TO_BASE(long x, int base) is valid until the end of the block.
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(long)*CHAR_BIT + 2)
// v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
char *my_to_base(char *buf, long a, int base) {
assert(base >= 2 && base <= 36);
long i = a < 0 ? a : -a; // use the negative side - this handle _MIN, _MAX nicely
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(i % base)];
i /= base;
} while (i);
if (a < 0) {
s--;
*s = '-';
}
// Could add memmove here to move the used buffer to the beginning
return s;
}
#include <limits.h>
#include <stdio.h>
int main(void) {
long ip1 = 0x01020304;
long ip2 = 0x05060708;
long ip3 = LONG_MIN;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16), TO_BASE(ip3, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2), TO_BASE(ip3, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
puts(TO_BASE(ip3, 10));
}
Here is another option with no need for source array of charaters, but less portable since not all character encodings have contiguous alphabetic characters, for example EBCDIC. Test HERE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
char get_chars(long long value)
{
if (value >= 0 && value <= 9)
return value + '0';
else
return value - 10 + 'A';
}
void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}
char* convert_to_base(char *res, int base, long long input)
{
bool flag = 0;
int index = 0;
if(input < 0){
input = llabs(input);
flag = 1;
}
else if(input == 0){
res[index++] = '0';
res[index] = '\0';
return res;
}
while(input > 0)
{
res[index++] = get_chars(input % base);
input /= base;
}
if(flag){
res[index++] = '-';
}
res[index] = '\0';
reverse_string(res);
return res;
}
int main() {
long long input = 0;
printf("** Integer to Base-36 **\n ");
printf("Enter a valid number: ");
scanf("%lld", &input);
if(input >= LLONG_MAX && input <= LLONG_MIN){
printf("Invalid number");
return 0;
}
int base = 36;
char res[100];
printf("%lld -> %s\n", input, convert_to_base(res, base, input));
return 0;
}
I made code which will for string "aabbcc" return "abc" but in cases when there is more letters like "aaa" it will return "aa" instead of just one.
Here is the code I made.
void Ponavljanje(char *s, char *p) {
int i, j = 0, k = 0, br = 0, m = 0;
for (i = 0; i < strlen(s) - 1; i++) {
for (j = i + 1; j < strlen(s); j++) {
if (s[i] == s[j]) {
br++;
if (br == 1) {
p[k++] = s[i];
}
}
}
br = 0;
}
p[k] = '\0';
puts(p);
}
For "112233" output should be "123" or for "11122333" it should be also "123".
Avoid repeated calls to strlen(s). A weak compiler may not see that s is unchanged and call strlen(s) many times, each call insuring a cost of n operations - quite inefficient. #arkku.1 Instead simply stop iterating when the null character detected.
Initialize a boolean list of flags for all char to false. When a character occurs, set the flag to prevent subsequent usage. Be careful when indexing that list as char can be negative.
Using a const char *s allows for wider allocation and helps a compiler optimization.
Example:
#include <stdbool.h>
#include <limits.h>
void Ponavljanje(const char *s, char *p) {
const char *p_original = p;
bool occurred[CHAR_MAX - CHAR_MIN + 1] = { 0 }; // all values set to 0 (false)
while (*s) {
if (!occurred[*s - CHAR_MIN]) {
occurred[*s - CHAR_MIN] = true;
*p++ = *s;
}
s++;
}
*p = '\0';
puts(p_original);
}
1 #wrongway4you comments that many compilers may assume the string did not change and optimize out the repeated strlen() call. A compliant compiler cannot do that though without restrict unless it is known that in all calls, s and p do not overlap. A compiler otherwise needs to assume p may affect s and warrant a repeated strlen() call.
does the work with a complexity O(n)
I suppose programming can give rmg
void Ponavljanje(char *s,char *p)
{
char n[256] = {0};
int i = 0;
while (*s) {
switch (n[(unsigned char) *s]) {
case 0:
n[(unsigned char) *s] = 1;
break;
case 1:
p[i++] = *s;
n[(unsigned char) *s] = 2;
}
s += 1;
}
p[i] = 0;
puts(p);
}
While the inner loop checks br to only copy the output on the first repetition, the outer loop still passes over each repetition in s on future iterations. Hence each further occurrence of the same character will run a separate inner loop after br has already been reset.
With aaa as the input, both the first and the second a cause the inner loop to find a repetition, giving you aa. In fact, you always get one occurrence fewer of each character in the output than there is in the input, which means it only works for 1 or 2 occurrences in the input (resulting in 0 and 1 occurrences, respectively, in the output).
If you only want to remove the successive double letters, then this function would be sufficient, and the examples given in the question would fit:
#include <stdio.h>
void Ponavljanje(char *s,char *p)
{
char dd = '\0';
char *r;
if(s == NULL || p == NULL)
return;
r = p;
while(*s){
if(*s != dd){
*r = *s;
dd = *s;
r++;
}
s++;
}
*r = '\0';
puts(p);
}
int main(void)
{
char s[20] = "1111332222";
char p[20];
Ponavljanje(s,p);
}
Here is something that works regardless of order:
#include <stdio.h>
#include <string.h>
void
repeat(char *s, char *p)
{
int slen;
int sidx;
int pidx;
int plen;
int schr;
slen = strlen(s);
plen = 0;
for (sidx = 0; sidx < slen; ++sidx) {
schr = s[sidx];
// look for duplicate char
int dupflg = 0;
for (pidx = 0; pidx < plen; ++pidx) {
if (p[pidx] == schr) {
dupflg = 1;
break;
}
}
// skip duplicate chars
if (dupflg)
continue;
p[plen++] = schr;
}
p[plen] = 0;
puts(p);
}
int
main(void)
{
char p[100];
repeat("112233",p);
repeat("123123",p);
return 0;
}
Note: As others have mentioned, strlen should not be placed in the loop condition clause of the for [because the length of s is invariant]. Save strlen(s) to a separate variable and loop to that limit
Here is a different/faster version that uses a histogram so that only a single loop is required:
#include <stdio.h>
#include <string.h>
void
repeat(char *s, char *p)
{
char dups[256] = { 0 };
int slen;
int sidx;
int pidx;
int plen;
int schr;
slen = strlen(s);
sidx = 0;
plen = 0;
for (sidx = 0; sidx < slen; ++sidx) {
schr = s[sidx] & 0xFF;
// look for duplicate char
if (dups[schr])
continue;
dups[schr] = 1;
p[plen++] = schr;
}
p[plen] = 0;
puts(p);
}
int
main(void)
{
char p[100];
repeat("112233",p);
repeat("123123",p);
return 0;
}
UPDATE #2:
I would suggest iterating until the terminating NUL byte
Okay, here's a full pointer version that is as fast as I know how to make it:
#include <stdio.h>
#include <string.h>
void
repeat(char *s, char *p)
{
char dups[256] = { 0 };
char *pp;
int schr;
pp = p;
for (schr = *s++; schr != 0; schr = *s++) {
schr &= 0xFF;
// look for duplicate char
if (dups[schr])
continue;
dups[schr] = 1;
*pp++ = schr;
}
*pp = 0;
puts(p);
}
int
main(void)
{
char p[100];
repeat("112233",p);
repeat("123123",p);
return 0;
}
I want to sort arrays alphabetically but I want to have upper case letter always first. What I already achieved is a simple sort, which doesn't take to account size of letters. Shall I put a special condition for it?
EDIT:
This is what I want to achieve:
AaaAdDcCFfgGhHI should be sorted like this: AAaaCcDdFfGgHhI
#include <stdio.h>
#include <stdlib.h>
#define N 5
int compare(const void *w1, const void *w2);
int main(void) {
char s1[N][15] = {
{ "azghtdffopAsAfp" },
{ "poiuyjklhgADHTp" },
{ "hgjkFfGgBnVUuKk" },
{ "lokijuhygtfrdek" },
{ "AaaAdDcCFfgGhHI" } };
char *wsk;
int i, j;
wsk = s1;
for (i = 0; i < N; i++) {
for (j = 0; j < 15; j++) {
printf("%c", s1[i][j]);
}
printf("\n");
}
for (i = 0; i < N; i++)
qsort(s1[i], 15, sizeof(char), compare);
printf("\n");
for (i = 0; i < N; i++) {
for (j = 0; j < 15; j++) {
printf("%c", s1[i][j]);
}
printf("\n");
}
return 0;
}
int compare(const void *w1, const void *w2) {
char *a1 = w1;
char *a2 = w2;
while (*a1 && *a2) {
register r = tolower(*a1) - tolower(*a2);
if (r)
return r;
++a1;
++a2;
}
return tolower(*a1) - tolower(*a2);
}
We should start by fixing a few issues in your code. First, you need to add #include <ctype.h>. You have declared char *wsk;, and assigned wsk = s1; for no apparent reason. More importantly, these are incompatible types, since s1 is a pointer to an array of 15 chars. And more important still, s1 should be an array of 16 chars! You have forgotten to include space for the '\0' terminator in your character arrays. So, the declaration of s1 needs to become:
char s1[N][16] = { { "azghtdffopAsAfp" },
{ "poiuyjklhgADHTp" },
{ "hgjkFfGgBnVUuKk" },
{ "lokijuhygtfrdek" },
{ "AaaAdDcCFfgGhHI" } };
The call to qsort() can be improved. Rather than use the magic number 15, it would be better to store the length of the strings in a variable. Also, sizeof(char) is always 1:
for (i = 0; i<N; i++) {
size_t s1_len = strlen(s1[i]);
qsort(s1[i], s1_len, 1, compare);
}
In the compare() function itself, you need to change to:
const unsigned char *a1 = w1;
const unsigned char *a2 = w2;
The cast to const will avoid warnings about discarding const qualifiers. The cast to unsigned avoids undefined behavior since the ctype.h functions expect an int argument that is representable as an unsigned char, or equal to EOF. Also, register is a type qualifier: it needs to qualify a type. So you need register int r = ....
But your function is also relying on a property of the encoding of the execution character set that is not guaranteed by the Standard: that the letters are encoded in alphabetic sequence. You have taken the first step towards portability by using the tolower() function, rather than adding magic numbers to change the case of the characters. By using isupper() and islower() to test the case of characters, and by using strcoll() to test the ordering of characters, we can achieve something approaching maximum portability. strcoll() automatically orders uppercase letters before lowercase if it is appropriate for the locale, but it appears that all uppercase letters precede the lowercase, so an explicit test will be necessary to order two characters that compare equal after conversion to lowercase. One obstacle to overcome is that strcoll() compares strings for lexical ordering. To use it to compare characters we can deploy compound literals:
register int r = strcoll((const char[]){tolower(*c1), '\0'},
(const char[]){tolower(*c2), '\0'});
There is a loop in your compare() function that makes no sense to me. The compare() function should just compare two chars; there is no need to loop through anything, so I have removed this loop.
I wrote a new compare() function that uses strcoll() and compound literals to portably compare two chars. If the two characters compare equal (up to case), then their cases are checked. If the cases differ, the uppercase character is taken to come before the lowercase character.
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // added for strlen() and strcoll()
#include <ctype.h> // must add this
#define N 5
int compare(const void *w1, const void *w2);
int main(void) {
/* Inner dimension should be 16 to include '\0' */
char s1[N][16] = { { "azghtdffopAsAfp" },
{ "poiuyjklhgADHTp" },
{ "hgjkFfGgBnVUuKk" },
{ "lokijuhygtfrdek" },
{ "AaaAdDcCFfgGhHI" } };
// char *wsk; // don't need this
int i, j;
// wsk = s1; // don't need this, also incompatible
for (i = 0; i<N; i++) {
for (j = 0; j<15; j++) {
printf("%c", s1[i][j]);
}
printf("\n");
}
for (i = 0; i<N; i++) {
size_t s1_len = strlen(s1[i]);
qsort(s1[i], s1_len, 1, compare); // improved call to qsort()
}
printf("\n");
for (i = 0; i<N; i++) {
for (j = 0; j<15; j++) {
printf("%c", s1[i][j]);
}
printf("\n");
}
return 0;
}
int compare(const void *a1, const void *a2) {
const unsigned char *c1 = a1;
const unsigned char *c2 = a2;
register int r = strcoll((const char[]){tolower(*c1), '\0'},
(const char[]){tolower(*c2), '\0'});
if (r == 0) {
if (isupper(*c1) && islower(*c2)) {
r = -1;
} else if (islower(*c1) && isupper(*c2)) {
r = 1;
}
}
return r;
}
Program output:
azghtdffopAsAfp
poiuyjklhgADHTp
hgjkFfGgBnVUuKk
lokijuhygtfrdek
AaaAdDcCFfgGhHI
AAadfffghoppstz
ADgHhijkloppTuy
BFfGgghjKkknUuV
defghijkklortuy
AAaaCcDdFfGgHhI
It is horribly unclear whether you want to sort all the characters in each ROW, or you want to sort the array of strings in the array, (or both). Both can be accomplished, but both have slightly different compare requirements.
Presuming you want to sort the array of arrays (easier if you make them strings), you would expect output like:
$ ./bin/sortcapsfirst
azghtdffopAsAfp
poiuyjklhgADHTp
hgjkFfGgBnVUuKk
lokijuhygtfrdek
AaaAdDcCFfgGhHI
AaaAdDcCFfgGhHI
azghtdffopAsAfp
hgjkFfGgBnVUuKk
lokijuhygtfrdek
poiuyjklhgADHTp
Otherwise, you would need to sort each row first (sorting each upper-case, before the same lower-case), then sort the array. That would result in output as follows:
$ ./bin/sortcapsfirst
azghtdffopAsAfp
poiuyjklhgADHTp
hgjkFfGgBnVUuKk
lokijuhygtfrdek
AaaAdDcCFfgGhHI
AAaaCcDdFfGgHhI
AAadfffghoppstz
ADgHhijkloppTuy
BFfGgghjKkknUuV
defghijkklortuy
You may be making things a bit harder on yourself than it needs to be. Generally, the natural string sort for your LOCALE will sort Caps first by default. In the case of sorting the array s1 ordering the rows so that capitals sort before lower-case, you need only make your number of columns 16 (to provide space for a nul-terminating character) and then call strcmp in your compare routine, e.g.:
int compare(const void *w1, const void *w2) {
const char *a1 = w1;
const char *a2 = w2;
return strcmp (a1, a2);
}
Putting it all together in an example, and properly terminating each j loop when the nul-terminating char is encountered, you could do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 5
#define R 16
int compare(const void *w1, const void *w2);
int main(void) {
char s1[][R] = {{ "azghtdffopAsAfp" },
{ "poiuyjklhgADHTp" },
{ "hgjkFfGgBnVUuKk" },
{ "lokijuhygtfrdek" },
{ "AaaAdDcCFfgGhHI" }};
int i, j;
for (i = 0; i<N; i++) {
for (j = 0; s1[i][j] && j<R; j++) {
putchar(s1[i][j]); /* don't use printf to print a single-char */
}
putchar('\n');
}
qsort (s1, N, sizeof *s1, compare); /* sort array (rows) */
putchar('\n');
for (i = 0; i<N; i++) {
for (j = 0; s1[i][j] && j<R; j++) {
putchar(s1[i][j]);
}
putchar('\n');
}
return 0;
}
int compare(const void *w1, const void *w2) {
const char *a1 = w1;
const char *a2 = w2;
return strcmp (a1, a2);
}
For the second case where you sort the upper-case in each row before the equivalent lower-case and then sort the array, you simply add a second qsort compare function and call that as you are, before calling qsort on the entire array. e.g. (to sort each upper-case before the corresponding lower-case):
int compare (const void *w1, const void *w2) {
const char *a1 = w1;
const char *a2 = w2;
while (*a1 && *a2)
{
int r = tolower(*a1) - tolower(*a2);
if (!r) {
if (*a1 - *a2)
return *a1 - *a2 > 0 ? 1 : -1;
}
else
break;
++a1;
++a2;
}
// return *a1 - *a2; /* to sort ALLcapsfirst */
return tolower(*a1) - tolower(*a2);
}
Then call qsort as done in the first example to sort the rows in the array:
int comparestr (const void *w1, const void *w2) {
const char *a1 = w1;
const char *a2 = w2;
return strcmp (a1, a2);
}
Putting that together in the same example (with nul-terminated rows), you could do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 5
#define R 16
int compare (const void *w1, const void *w2);
int comparestr (const void *w1, const void *w2);
int main (void) {
char s1[][R] = {{"azghtdffopAsAfp"},
{"poiuyjklhgADHTp"},
{"hgjkFfGgBnVUuKk"},
{"lokijuhygtfrdek"},
{"AaaAdDcCFfgGhHI"}};
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; s1[i][j] && j < R; j++)
putchar(s1[i][j]);
putchar('\n');
}
for (i = 0; i < N; i++) /* sort arrays */
qsort (s1[i], R - 1, sizeof *(s1[i]), compare);
qsort (s1, N, sizeof *s1, comparestr); /* sort array */
putchar('\n');
for (i = 0; i < N; i++) {
for (j = 0; s1[i][j] && j < R; j++)
putchar(s1[i][j]);
putchar('\n');
}
return 0;
}
int compare (const void *w1, const void *w2)
{
const char *a1 = w1;
const char *a2 = w2;
while (*a1 && *a2) {
int r = tolower (*a1) - tolower (*a2);
if (!r) {
if (*a1 - *a2)
return *a1 - *a2 > 0 ? 1 : -1;
} else
break;
++a1;
++a2;
}
// return *a1 - *a2; /* to sort ALLcapsfirst */
return tolower (*a1) - tolower (*a2);
}
int comparestr (const void *w1, const void *w2)
{
const char *a1 = w1;
const char *a2 = w2;
return strcmp (a1, a2);
}
Finally, as noted above, if you want to sort ALLCapsfirst, then simply return the difference between *a1 - *a2 instead of tolower (*a1) - tolower (*a2). e.g. using return *a1 - *a2; the sort would be:
AACDFGHIaacdfgh
AAadfffghoppstz
ADHTghijkloppuy
BFGKUVfgghjkknu
defghijkklortuy
Look things over. I could have misunderstood your goal completely. If so, drop a note and I can help further in a bit.
Instead of comparing the lowercase values, check the values ASCII values. In the table capital letters come first, then the lowercase ones:
http://www.asciitable.com/
UPDATE: If you need a bit more platform and character set independent code, just add an extra if, and check the letter case with isupper() and/or islower():
https://www.tutorialspoint.com/c_standard_library/c_function_islower.htm
https://www.tutorialspoint.com/c_standard_library/c_function_isupper.htm
if you want such that upper case lower case distiction is made per character, so you would sort like "A", "Aa", "AB", "aa", "B", "b", compare could look like that
int compare(const void *w1, const void *w2) {
char *a1 = w1;
char *a2 = w2;
while (*a1 && *a2)
{
register r = tolower(*a1) - tolower(*a2);
if (r)
return r;
// this is the new part
else if( isupper( *a1 ) && !isupper( *a2 ) ) {
// w1 < w2
return -1;
} else if( !isupper( *a1 ) && isupper( *a2 ) ) {
// w1 > w2
return 1;
}
++a1;
++a2;
}
return tolower(*a1) - tolower(*a2);
}
If you want "aa" to be sorted before "AB" it could look like:
int compare(const void *w1, const void *w2) {
char *a1 = w1;
char *a2 = w2;
register r;
int caseDifference = 0;
while (*a1 && *a2)
{
r = tolower(*a1) - tolower(*a2);
if (r)
return r;
// this is the new part
else if( caseDifference == 0 && ( isupper( *a1 ) && !isupper( *a2 ) ) ) {
// w1 < w2
caseDifference = -1;
} else if( caseDifference == 0 && ( !isupper( *a1 ) && isupper( *a2 ) ) ) {
// w1 > w2
caseDifference = 1;
}
++a1;
++a2;
}
r = tolower(*a1) - tolower(*a2);
if( r != 0 )
return r;
else
return caseDifference;
}
Your comparison function is incorrect: it compares multiple characters instead of just the ones pointed to by the arguments.
If you can assume ASCII, here is a much simpler comparison function that solves the problem:
int compare(const void *w1, const void *w2) {
int c1 = *(const unsigned char *)w1;
int c2 = *(const unsigned char *)w2;
int l1 = tolower(c1);
int l2 = tolower(c2);
/* sort first by alphabetical character, then by case */
return l1 != l2 ? l1 - l2 : c1 - c2;
}
Also note that the main() function can be simplified too:
#include <stdio.h>
#include <stdlib.h>
#define N 5
int compare(const void *w1, const void *w2);
int main(void) {
char s1[N][15] = {
{ "azghtdffopAsAfp" },
{ "poiuyjklhgADHTp" },
{ "hgjkFfGgBnVUuKk" },
{ "lokijuhygtfrdek" },
{ "AaaAdDcCFfgGhHI" } };
for (int i = 0; i < N; i++) {
printf("%.15s\n", s1[i]);
}
for (int i = 0; i < N; i++) {
qsort(s1[i], 15, sizeof(char), compare);
}
printf("\n");
for (int i = 0; i < N; i++) {
printf("%.15s\n", s1[i]);
}
return 0;
}