Check permutations without modifying original string C - c

I am doing a check whether 2 strings are permutations. I sort the strings then compare each character to each other. However, I think my sorting process also changes the original strings (I am very bad with pointers and passing by reference).
Is there a way to check without modifying the original strings?
I also tried using strcpy but I don't really know how to use it.
I tried this in my check() function:
char temp[128];
strcpy(temp, word);
Below is my code. I call the areAnagram function from another function like this:
void check(char *word, struct Entry *en) {
if (areAnagram(en->word, word) == 1) {
//printf("EW:%s W:%s\n", en->word, word);
//For example, this should return something like
// EW:silent W:listen
//But I got
// EW:eilnst W:eilnst
}
}
Structure for Entry:
typedef struct Entry {
char *word;
int len;
struct Entry *next;
} Entry;
Here is the anagram check process:
void quickSort(char *arr, int si, int ei);
int areAnagram(char *str1, char *str2)
{
// Get lenghts of both strings
int n1 = strlen(str1);
int n2 = strlen(str2);
// If lenght of both strings is not same, then they cannot be anagram
if (n1 != n2) {
return 0;
}
// Sort both strings
quickSort (str1, 0, n1 - 1);
quickSort (str2, 0, n2 - 1);
int i;
// Compare sorted strings
for (i = 0; i < n1; i++) {
if (str1[i] != str2[i]) {
return 0;
}
}
return 1;
}
void exchange(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
int partition(char A[], int si, int ei)
{
char x = A[ei];
int i = (si - 1);
int j;
for (j = si; j <= ei - 1; j++) {
if(A[j] <= x) {
i++;
exchange(&A[i], &A[j]);
}
}
exchange (&A[i + 1], &A[ei]);
return (i + 1);
}
void quickSort(char A[], int si, int ei)
{
int pi; /* Partitioning index */
if(si < ei) {
pi = partition(A, si, ei);
quickSort(A, si, pi - 1);
quickSort(A, pi + 1, ei);
}
}

There is a better way of checking whether two strings are anagrams.You can create an array to store the count of each character in first string(increment the ASCII value index in the array). Then traverse second string and decrement the count of each character (ASCII value index in the array). Now check if all elements of array are zero,if yes these are anagrams otherwise not.
int arr[123];
suppose two strings are s1="abba" and s2="baba"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second array arr[97]=0,arr[98]=0;
Now if you traverse the whole array then all elements will be zero.
But if two strings s1="abba" and s2="abac"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second string arr[97]=0,arr[98]=1,arr[99]=-1;
Since all elements of array are not zero so these are not anagrams.
The complexity of above algorithm is O(n).
Hope it helps.

Make a copy using strcpy:
char *copy = malloc(strlen(word) + 1); // can use a temporary buffer, but this allows variable length inputs
strcpy(copy, word);
// use copy as your temporary string
free(copy);

Your title states that you do not want to modify the original string, however your solution uses Quicksort, which modifies the string. Plus, sorting -- even a fast optimized sort -- is an expensive operation and is not needed for the problem you are trying to solve. You could use a lookup table for speed and it would not modify the original string. You simply create a unique number for each letter and sum the values. Equal sums would constitute an anagram.
/* OPTION 1: let the compiler build your table */
static const int A=0x0000001;
static const int B=0x0000002;
static const int C=0x0000004;
/* continue to double for other letters until ... */
static const int Z=0x4000000;
/* OPTION 2: calculate a cheap hash for each letter */
/* Returns 0 for anagram similar to strcmp */
int anagram (const char* word1, const char* word2)
{
/* strings must be equal length */
if (strlen(word1) != strlen(word2))
return -1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
char c;
for (int i = 0 ; word1[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word1[i]);
sum1 += 1 << (c - 'A');
}
for (int i = 0 ; word2[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word2[i]);
sum2 += 1 << (c - 'A');
}
return (int)(sum1 - sum2); /* ignore overflow */
}
The anagram function above is untested and has been written for clarity. You'd need to include the ctype.h to convert the case using toupper().
Finally, you could make a copy of one of the strings, traverse the other string calling strchr() on each character to find the matching character in the copy. If strchr() returns NULL then there is no anagram, otherwise if strchr() returns a valid pointer, use it to modify the copy, e.g. set to char value to 0x01, so that you can sum the chars in the modified copy. In this instance, the strings would be anagrams if the sum of all the chars in the modified copy equal the integer length of the comparison string.

Related

REVERSE_WORD in c using pointers

i have try this code made by me but no output and there's no errors?
#include <stdio.h>
void reverse(char *p,char *v,int size){
for(int i=size-1,j=0;i<0;i--){
*(v+j) = *(p+i);
j++;
}
}
int main(){
char word[6] = {"hello"};
char re_word[6];
re_word[5]='\0';
reverse(word,re_word,6);
printf("%s",re_word);
}
Using pointers it can look like this:
void reverse(char *w, char *revw, int slen) {
revw += slen - 1; // forward to pos. of last letter
revw[1] = '\0'; // one further *(revw+1)
while (*w)
*revw-- = *w++;
}
This is clear and symmetric, once it works, while your i-- and j++ are far apart.
slen is meant to be the number of letters w/o termination. Here the call:
char word[] = {"hello"};
char re_word[sizeof word];
reverse(word, re_word, sizeof word - 1);
strlen() should be used, probably, but these lines show how you can and have to control not just the total size but especially the last byte of the char array.
Without the correct length, reverse() would have to do a strlen() first, because it has to know how far away to put the first letter.
This *(v+j) = *(p+i) is more or less v[j] = p[i] and does not really take advantage of pointers, on the contrary.
(revw
caller) in reverse()
| |
v v
-4 -3 -2 -1 revw +1
o l l e h \0
... revw-- revw[1]
So revw is maybe not the best name inside the function; revw_first_backwards is meant...or fill_start. But before I fill backwards I do the one additional write to the right side to terminate the string: array notation using a pointer: revw[1] = '\0'.
First of all, i < 0 will always be false, given i = size - 1 > 0.
What you want is i >= 0.
Also, given size = 6, size - 1 will be equal to 5, and that is the NULL terminator position since array indexing in C start from 0. Perhaps use a C function such as strlen() to calculate the length rather than hard coding it.
void reverse(char *p, char *v, size_t size)
{
for (int i = size - 1, j = 0; i >= 0; i--)
{
*(v + j) = *(p + i);
j++;
}
}
int main()
{
char word[6] = {"hello"};
char re_word[6];
re_word[5] = '\0';
reverse(word, re_word, 5); /* or reverse(word, re_word, strlen(word)) */
printf("%s", re_word);
}

How to sort strings in an 2D array in C

#include <stdio.h>
int main()
{
int N, i, j, k, z, v, x, c;
printf("Determine the number of your words: \n");
scanf("%d", &N);
char dict[N][50];
char tmp[50];
for(i=0; i<N; i++)
{
printf("Determine your %d. word: \n", i+1);
scanf("%49s", &dict[i]);
}
for(j=1; j<N; j++)
{
k=j;
z=0;
while(dict[j][z]!= '\0')
{
tmp[z]=dict[j][z];
z=z+1;
}
while((dict[j][1]<dict[k-1][1]) && (k>0))
{
v=0;
while(dict[k][v]!= '\0')
{
dict[k][v] = dict[k-1][v];
v= v+1;
}
k=k-1;
}
x=0;
while(dict[k][x]!= '\0')
{
dict[k][x]=tmp[x];
x=x+1;
}
}
for(c=0; c<N; c++)
{
printf("%s \n", dict[c]);
}
return 0;
}
So as a junior CE student our task is to write a C code that sort the strings in a 2D array according to their first characters position in the alphabet by only using the <stdio.h> library and this is the result I get is below(I know the variables are not really bearable but I'm in a little bit of a hurry):
Determine the number of your words:
5
Determine your 1. word:
LION
Determine your 2. word:
FISH
Determine your 3. word:
TIGER
Determine your 4. word:
SNAKE
Determine your 5. word:
SEALION
LION
FISH
TIGER
SEALI
SNAKE
I get no errors just the result is faulty and I do not wish any answers. But I would be glad to be enlightened about the reasons I get this results
Limited to stdio.h
If you are limited to using what is provided in stdio.h, then you simply have to write similar string handling functionality to what you would require from string.h. For sorting, unless you want to use a partitioning sort like quicksort or mergesort, you would be limited to a nested loop sort -- which are simpler to write -- but much much slower. (but for a 1000 or so strings, it doesn't matter, 100,000 - then there will be a perceivable difference)
To compare strings, you can write a simple strcmp() like function that requires no additional header, e.g.
/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
if (!a && !b) return 0;
if ( a && !b) return 1;
if (!a && b) return -1;
for (; *a && *a == *b; a++, b++) {}
return (*a > *b) - (*a < *b);
}
If you are not declaring an additional set of pointers to sort, then you will need to copy strings between the rows (1D arrays) in your 2D array. You can write a simple strcpy() like function that needs no header as:
/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
char *p = dest;
do {
*p++ = *src;
} while (*src++);
return dest;
}
Finally, the only other thing you need is a sort function. (you will not be able to write a quick qsort() replacement) The meager Bubblesort will do. You can write a function to sort your 2D array of strings as:
#define NCHR 50
/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
size_t i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < (n-1); j++) {
if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
char temp[NCHR];
strcpy_nohdr (temp, a[j + 1]);
strcpy_nohdr (a[j + 1], a[j]);
strcpy_nohdr (a[j], temp);
}
}
}
}
If you put those altogether in a short example (the same used before with qsort(), you would have:
#include <stdio.h>
#define NCHR 50
/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
if (!a && !b) return 0;
if ( a && !b) return 1;
if (!a && b) return -1;
for (; *a && *a == *b; a++, b++) {}
return (*a > *b) - (*a < *b);
}
/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
char *p = dest;
do {
*p++ = *src;
} while (*src++);
return dest;
}
/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
size_t i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < (n-1); j++) {
if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
char temp[NCHR];
strcpy_nohdr (temp, a[j + 1]);
strcpy_nohdr (a[j + 1], a[j]);
strcpy_nohdr (a[j], temp);
}
}
}
}
int main (void) {
char strings[][NCHR] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
size_t n = sizeof strings / sizeof *strings;
bubblesort2D (strings, n);
for (size_t i = 0; i < n; i++)
puts (strings[i]);
}
Example Use/Output
The results are the same as before:
$ ./bin/sort_2d_strings_stdio
alligators
frogs
opossums
racoons
zebra
Since I originally wrote the qsort() answer, I'll leave it below as the way you would want to handle sorting (whatever array you are sorting) in practice.
In Practice Use qsort()
C provides qsort() that will sort arrays of any object based on the compare function you write to tell qsort() how elements of the array are to be compares. With strings, you just want to return the result of strcmp(). Each argument to the compare function ia a Pointers to an element of your array. Since it is a void* pointer, you must cast the pointer back to the correct type.
Recall in C that a 2D array is simply an array of 1D arrays. In your case it is a array of 50-character arrays. A pointer to an array of 50-chars has the type char (*)[50], so your qsort() compare function can be written as follows:
int cmpstr50 (const void *a, const void *b)
{
const char *pa = *(char (*)[50])a,
*pb = *(char (*)[50])b;
return strcmp (pa, pb);
}
Where each of the parameters is a pointer to an array of char [50]. Nothing could be easier. Moreover the algorithm used by qsort() will be orders of magnitude faster than what you write with nested loops.
A complete example for your case would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmpstr50 (const void *a, const void *b)
{
const char *pa = *(char (*)[50])a,
*pb = *(char (*)[50])b;
return strcmp (pa, pb);
}
int main (void) {
char strings[][50] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
size_t n = sizeof strings / sizeof *strings;
qsort (strings, n, sizeof *strings, cmpstr50);
for (size_t i = 0; i < n; i++)
puts (strings[i]);
}
Where after writing your compare function, all it takes to sort the array of strings (or array of anything) is a single call to qsort():
qsort (strings, n, sizeof *strings, cmpstr50);
Much simpler than trying to reinvent the wheel.
Example Use/Output
$ ./bin/qsort_2d_strings
alligators
frogs
opossums
racoons
zebra
Let me know if you have further questions.
This comparison is incorrect:
while((dict[j][1]<dict[k-1][1]) && (k>0))
First, if you want to compare the first character of each word, use [0] instead of [1]. This is because array indexes are zero-based in C. Second, put the k>0 comparison first, before you use k-1 as an index to the array. This will take advantage of "short circuiting" to make sure you're not using an invalid index to the array. Result:
while(k > 0 && dict[j][0] < dict[k-1][0])
Another issue is that you are not making sure your strings are null terminated when you copy them. I believe this is the reason your "SEALION" is coming out "SEALI". For example, this loop:
x=0;
while(dict[k][x]!= '\0')
{
dict[k][x]=tmp[x];
x=x+1;
}
You're checking for null on the destination instead of the source. Also, you stop copying at the null character, but you actually need to copy that too, or at least tack a null at the end:
x=0;
while(tmp[x]!= '\0')
{
dict[k][x]=tmp[x];
x=x+1;
}
dict[k][x] = '\0';
Take a close look at each of your string copy loops for such errors.

Largest Palindrome in C

Really need help!
This code should find a largest palindrome in a string. Which means if there are "abcdcba" and "cdc" in the same string, it should print "abcdcba" out since the length is longer. The function takes a string str and 2 points i and j and determines whether the string from i to j is a palindrome. If it is a palindrome, returns the length of the palindrome and if it is not, returns -1.
int palindromelength(char *str, int i, int j){
int *first = &i, *last = &j;
int len;
while (first < last){
if (toupper(*first) != toupper(*last))
return -1;
first++;
last--;
}
len = last - first;
return (len);
}
int main() {
int length, i, j;
char str;
scanf("%s", &str);
length = strlen(str);
printf("Length = %d\n", palindromelength(str, i, j));
//should print out largest palindrome.
return 0;
}
What you describe and what the function is supposed to do are inconsistent:
"The function takes a string str and 2 points i and j and determines whether the string from i to j is a palindrome. If it is a palindrome, returns the length of the palindrome and if it is not, returns -1"
Therefore the function should returen either j - i or -1
char str;
scanf("%s", &str);
This is not how you should declare then initialize a string. Use instead:
char str[512];
scanf ("%s", str);
Also note that you'll need to ask the user to input the length of that string, and you'll need to pass that length as argument in the "palindromelength" function
You access the (i+1)th entry of your string like this:
str[i]
but before, you need to check that i is strictly lower than the length of your string. And don't forget to initialize i and j in your main() function
Before starting to code, write an algorithm in pseudocode which can solve your problem and evaluate its complexity. In this case, the comlpexity of the most obvious algorithm would be O(n^2), where n is the length of the string. This most obvious solution would be to check every substring, but maybe there are better algorithms: en.wikipedia.org/wiki/Longest_palindromic_substring
You send your function a string and two indexes, then immediately take the address of two indexes and proceeded to increment/decrement the indexes without any relation or regard to your string. That will never get you anywhere.
While it is fine to try and do all comparisons with indexes as integers, it is probably a bit easier to approach finding palindromes operating on strings and characters instead. You use the indexes to set the start and end position within the string. The indexes by themselves are just numbers. Your first and last should not hold the address to the intergers, they should hold the address of the first and last characters of your search string.
Below is a quick example of using the indexes to locate the start and end characters for your search. Note: I use p (pointer) for first and ep (end pointer) for your last. Look over the logic and let me know if you have questions. The program takes 3 arguments, the string, start and end indexes within the string (0 based indexes):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXP 128
int get_palindrome (char *s, size_t i, size_t j);
int main (int argc, char **argv) {
if (argc < 4 ) {
fprintf (stderr, "error: insufficient input, usage: %s str i j\n", argv[0]);
return 1;
}
size_t i = atoi (argv[2]);
size_t j = atoi (argv[3]);
char palindrome[MAXP] = {0};
int len = get_palindrome (argv[1], i, j);
if (len > 0)
{
strncpy (palindrome, argv[1] + i, len);
printf ("\n palindrome: %s (%d chars)\n\n",
palindrome, len);
}
else
printf ("\n no palindrome for for given indexes.\n\n");
return 0;
}
int get_palindrome (char *s, size_t i, size_t j)
{
if (!s || *s == 0) return -1;
int len = 0;
char *p = s + i; /* set start/end pointers */
char *ep = s + j + 1;
char *sp = NULL;
int c = *ep; /* save char from string */
*ep = 0; /* null-terminate at end */
char *s2 = strdup (p); /* copy string to s2 */
*ep = c; /* replace original char */
p = s2; /* set s2 start/end ponters */
ep = s2 + j - i;
while (ep > p) /* check for palindrome */
{
if (toupper(*ep) != toupper(*p))
{
*ep = 0;
sp = NULL;
}
else if (!sp)
sp = p;
p++, ep--;
}
len = sp ? (int) strlen (sp) : -1; /* get length */
if (s2) free (s2); /* free copy of string */
return len; /* return len or -1 */
}
Output
$ ./bin/palindrome 1234abcdcba 4 10
palindrome: abcdcba (7 chars)
Note the use of size_t type instead of int for i & j. i & j are indexes and will not be negative for the purpose of this problem. Try to always choose your data type to best fit your data. It will help identify and prevent problems in your code.
Also note, you should make a copy of the string in the function (if you are concerned about preserving the original). Inserting null-terminating characters locating palindromes will alter the original string otherwise.
There is an easy to understand solution to find out longest palindrome in a string.
Key Concept: at the center of a palindrome, characters are always of the form
"....x y x...." or "......x x......"
step1: scan the string from start to end for the xyx or xx patterns and store the center indices in an auxiliary array.
step2: now around each center try to expand the string in both direction and store the lengths.
step3: return the max length.
This approach takes O(N2) order time.

Combining two strings by removing duplicate substrings

I have two strings that I would like to combine, removing duplicate substrings. Note that every two consecutive numbers constitute a substring. Consider string str1 and str2:
str1 = "#100#123#100#678"
str2 = "#100#678#100#56"
I would like to produce a combined string as:
comboStr = "#100#123#100#678#100#56" (i.e. I removed the duplicate #100#678)
What's the easiest way to do this? Is there a way I can achieve this using regular expressions?
I don't think regular expressions are a good way to solve this problem. Regexes might be useful in finding the #123 tokens, but the problem needs to backtrack on its own string in a way regex's back references are not desiged for.
I also don't think that there is an easy way (as in three lines of code) to solve this.
I assume that the strings always follow the pattern (#\d+)* and that the pair created at the seam when joining two strings is not trated as special, i.e. the resulting pair might be considered as duplicate. This means we can separate concatenation from pair removal.
Convert your string to a list of integers, operate on these lists and then join them back. That's some work, but it makes the actual code to strip duplicates easier - it's complicated enough - and might also come in handy when you need to operate on similar strings often.
#include <stdlib.h>
#include <stdio.h>
/*
* Convert a string to a list of at most max integers. The
* return value is the number of integers in the list (which
* max be greater than max!) or -1 if the string is invalid.
*/
int ilist_split(int *ilist, int max, const char *str)
{
const char *p = str;
int n = 0;
while (*p) {
int x;
int pos;
if (sscanf(p, "#%d %n", &x, &pos) < 1) return -1;
if (n < max) ilist[n] = x;
n++;
p += pos;
}
return n;
}
/*
* Convert a list of integers back to a string. The string
* is at most nbuf - 1 characters long and is assured to be
* zero-terminated if nbuf isn't 0. It is legal to pass NULL
* as char buffer if nbuf is 0. Returns the number of characters
* that would have been written ha dthe buffer been long enough,
* snprintf-style.
*/
int ilist_join(const int *ilist, int n, char *buf, int nbuf)
{
int len = 0;
int i;
for (i = 0; i < n; i++) {
len += snprintf(buf + len,
nbuf > len ? nbuf - len : 0, "#%d", ilist[i]);
}
return len;
}
/*
* Auxliary function to find a pair in an inteher list.
*/
int ilist_find_pair(int *ilist, int n, int a1, int a2)
{
int i;
for (i = 1; i < n; i++) {
if (ilist[i - 1] == a1 && ilist[i] == a2) return i - 1;
}
return -1;
}
/*
* Remove duplicate pairs from an integer list. The first
* pair is kept, subsequent pairs are deleted. Returns the
* new length of the array.
*/
int ilist_remove_dup_pairs(int *ilist, int n)
{
int i, j;
j = 1;
for (i = 1; i < n; i++) {
int a1 = ilist[i - 1];
int a2 = ilist[i];
if (ilist_find_pair(ilist, i - 1, a1, a2) < 0) {
ilist[j++] = ilist[i];
} else {
i++;
}
}
return j;
}
#define MAX 40
int main()
{
const char *str1 = "#100#123#100#678";
const char *str2 = "#100#678#100#56";
char res[80];
int ilist[MAX];
int nlist;
/* convert str1 */
nlist = ilist_split(ilist, MAX, str1);
if (nlist > MAX) nlist = MAX;
/* convert and concatenate str2 */
nlist += ilist_split(ilist + nlist, MAX - nlist, str2);
if (nlist > MAX) nlist = MAX;
/* remove duplicate pairs */
nlist = ilist_remove_dup_pairs(ilist, nlist);
/* convert back to string */
ilist_join(ilist, nlist, res, sizeof(res));
printf("%s\n", res);
return 0;
}

Find Every Position of a Given Char Within an Array

I made a small function that fills an allocated block of memory containing every position of a given char within a given string and returns a pointer to the memory block.
The only problem with this function is that there is no way to check the size of the memory block; so I also made a function that counts the occurrence of a given char within a string.
Here is an example of use:
/*count occurences of char within a given string*/
size_t strchroc(const char *str, const char ch)
{
int c = 0;
while(*str) if(*(str++) == ch) c++;
return c;
}
/*build array of positions of given char occurences within a given string*/
int *chrpos(const char *str, const char ch)
{
int *array, *tmp, c = 0, i = 0;
if(!(array = malloc(strlen(str) * sizeof(int)))) return 0x00;
while(str[c])
{
if(str[c] == ch) array[i++] = c;
c++;
}
if(!(tmp = realloc(array, i * sizeof(int)))) return 0x00;
array = tmp;
return array;
}
int main(void)
{
char *str = "foobar foobar"; //'o' occurs at str[1], str[2], str[8], and str[9]
int *array, b = 0, d;
if(!(array = chrpos(str, 'o'))) exit(1); //array[0] = 1, array[1] = 2, array[2] = 8, array[3] = 9
/*
* This is okay since I know that 'o'
* only occures 4 times in str. There
* may however be cases where I do not
* know how many times a given char
* occurs so I figure that out before
* utilizing the contents of array.
* I do this with my function strchroc.
* Below is a sample of how I would
* utilize the data contained within
* array. This simply prints out str
* and on a new line prints the given
* char's location within the str
* array
*/
puts(str);
while(b < (int) strchroc(str, 'o')) //loop once for each 'o'
{
for(d = 0; d < (b == 0 ? array[b] : array[b] - array[b - 1] - 1); d++) putc((int) ' ', stdout);
printf("%d", array[b]);
b++;
}
}
Output:
foobar foobar
12 89
My only concern is that if one of these two functions fail, there is no way for the data to be used correctly. I was thinking about making the number of occurrences of char within the string an argument for chrpos but even then I would still have to call both functions.
I was wondering if anybody had any suggestions for a way to do this so that I only need one function to build the array.
The only way I can think of is by storing the number of char occurrences into array[0] and having array[1] through array[char_occurences] holding the positions of char.
If anybody has a better idea I would greatly appreciate it.
As stated in my comment the first thing is to save up the data anyway, in case you can't shrink the allocated memory :
if (!(tmp = realloc(array, i * sizeof(int))))
return array;
return (tmp); //array = tmp; is useless
If you want to protect a bit more your strchroc function add a if (!str) return 0; at the beginning.
You can change your function so that it also "returns" the number of occurrences found. While we cannot actually return multiple values from a function in C, we can pass a pointer as a parameter and have the function write down a value using that pointer:
int *chrpos(const char *str, char ch, int *found) {
/*
...
*/
*found = i;
return array;
}
Note that you don't need the const modifier for ch.

Resources