How to rotate 2D array of characters - c

I'm trying to rotate this clockwise 90 degrees, but it works not as expected. Must be something to do with pointers which I'm not that familiar.
OUTPUT Before Rotation:
hiivp
nxhxd
tszeg
xdlqo
kwpae
void rotate_right(char **m, int n) {
char **temp = m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
m[i][j] = temp[n-1-j][i];
}
}
}
OUTPUT After Rotation:
kxtnk
wdsdx
plzst
aqsdn
entxk

You're partially overwriting your matrix.
To perform a 90° rotation, let us consider the four corners of the square (in caps):
HiivP
nxhxd
tszeg
xdlqo
WwpaE
You need to put the H in the P place, save the P, and put the P in the E place, then the E in the W place, and finally the W in the H place. These four shift must be done each time saving the overwritten value, that becomes the new running value for the next stage.
Then you can see that each cell is part of such a four-cell shift: the corners are numbered 1, and 1 is the first shift. Then you work cells in position 2, then those in 3, and so on.
12341
45652
36-63
25654
14321
Having an odd side, the central square does not rotate and there is no cycle number 7. After six cycles, each involving four cells, the square is rotated (6*4 = 24, and 24+1 = 25). With a larger square, you can see the "law" linking the x,y coordinates for each cycle.

Building on LSerni's answer, adding an implementation for completeness sake.
Assuming the following matrix:
#define STRING_SIZE (5)
char m[][STRING_SIZE+1] = { "hiivp",
"nxhxd",
"tszeg",
"xdlqo",
"kwpae" };
You can define the rotate function like this:
char override_and_backup(char* dest, char val)
{
char tmp = *dest;
*dest = val;
return tmp;
}
void rotate_right(char m[][STRING_SIZE+1], int size)
{
// rotate layer by layer
for (int layer = 0; layer < (size / 2); ++layer)
{
int current_size = size - (2*layer); // side size of current layer
int ncycles = current_size - 1; // number of cycles to complete rotation
// perform the rotating cycles
for (int cycle = 0; cycle < ncycles; ++cycle)
{
char* first = &m[layer][layer+cycle];
char* second = &m[layer+cycle][layer+current_size-1];
char* third = &m[layer+current_size-1][layer+current_size-cycle-1];
char* fourth = &m[layer+current_size-cycle-1][layer];
char tmp = *fourth;
tmp = override_and_backup(first, tmp);
tmp = override_and_backup(second, tmp);
tmp = override_and_backup(third, tmp);
override_and_backup(fourth, tmp);
}
}
}

Related

Cunit test invalid read/write of size8

Invalid read and write of size 8 happening in modify_tab_size().
what am I doing wrong? Ive tried almost everything, I dont understand it.
// Function being tested.
int erase_repeated(int *nb_words, char **words) {
for (int i = 0; i < *nb_words; ++i) {
if (words[i] != 0) {
for (int b = 0; b < *nb_words; ++b) {
if (strcmp(words[i], words[b]) == 0 && b != i)
modify_tab_size(&b, nb_words, words);
}
}
}
return *nb_mots;
}
void modify_tab_size(int *b, int *nb_words_update, char **words) {
free(words[*b]);
for (int k = *b; k < *nb_words_update; k++) {
words[k] = words[k + 1]; <--------------------------read error
words[*nb_words_update + 1] = 0; <--------------------------write error
}
(*nb_words_update)--;
(*b)--;
}
The problem is k+1 and *nb_words_update + 1 can walk off the array, and it is. Add printf("k:%d, k+1:%d, *nb_words_update + 1: %d\n", k, k+1, *nb_words_update + 1); into the loop to see.
k:1, k+1:2, *nb_words_update + 1: 4
k:2, k+1:3, *nb_words_update + 1: 4
You've only allocated three slots, 3 and 4 walk off the end of the array.
Since nb_words_update starts as the length of the array, words[*nb_words_update + 1] = 0; is always going to be too large. words[*nb_words_update] = 0; is also too large.
What you seem to be trying to do is deleting an element from an array by shifting everything after it to the left.
void delete_element(char **words, int *b, int *size) {
// Free the string to be deleted.
free(words[*b]);
// Only go up to the second to last element to avoid walking off the array.
for (int i = *b; i < *size-1; i++) {
// Shift everything to the left.
words[i] = words[i+1];
}
// Null out the last element.
// Don't use 0 for NULL, it's confusing.
words[*size-1] = NULL;
// Decrement the size of the array.
(*size)--;
// Redo the check with the newly shifted element.
(*b)--;
}
This sort of thing is better done with a linked list.
Note that your code has a bug. The result is an array of two elements, but one of them is blank. In addition to the return value of erase_repeated, also test its side effect which is to modify words. Test that words contains what you think it does.

Segfault after refactoring nested loops

I have some MATLAB code from a digital audio course that I've ported to C. Given an array of numeric data (for example, PCM audio encoded as double-precision floating-point), produce an array of data segments of a specified width and which overlap each other by a specified amount. Here's the relevant code.
typedef struct AudioFramesDouble {
const size_t n, // number of elements in each frame
num_frames;
double* frames[];
} AudioFramesDouble;
/*
* Produce a doubly-indexed array of overlapping substrings (a.k.a windows, frames,
* segments ...) from a given array of data.
*
* x: array of (i.e., pointer to) data
* sz: number of data elements to consider
* n: number of elements in each frame
* overlap: each frame overlaps the next by a factor of 1 - 1/overlap.
*/
AudioFramesDouble* audio_frames_double(register const double x[], const size_t sz, const unsigned n, const unsigned overlap) {
// Graceful exit on nullptr
if (!x) return (void*) x;
const double hop_d = ((double) n) / ((double) overlap); // Lets us "hop" to the start of the next frame.
const unsigned hop = (unsigned) ceil(hop_d);
const unsigned remainder = (unsigned) sz % hop;
const double num_frames_d = ((double) sz) / hop_d;
const size_t num_frames = (size_t) (remainder == 0
? floor(num_frames_d) // paranoia about floating point errors
: ceil(num_frames_d)); // room for zero-padding
const size_t total_samples = (size_t) n * num_frames;
AudioFramesDouble af = {.n = n, .num_frames = num_frames};
// We want afp->frames to appear as (double*)[num_frames].
AudioFramesDouble* afp = malloc((sizeof *afp) + (sizeof (double*) * num_frames));
if (!afp) return afp;
memcpy(afp, &af, sizeof af);
for (size_t i = 0; i < num_frames; ++i) {
/* Allocate zero-initialized space at the start of each frame. If this
fails, free up the memory and vomit a null pointer. */
afp->frames[i] = calloc(n, sizeof(double));
if (!afp->frames[i]) {
double* p = afp->frames[i];
for (long ii = ((long)i) - 1; 0 <= ii; ii--) {
free(afp->frames[--i]);
}
free(afp);
return (void*) p;
}
for (size_t j = 0, k; j < n; ++j) {
if (sz <= (k = (i*hop) + j)) break;
afp->frames[i][j] = x[k];
}
}
return afp;
}
This performs as expected. I wanted to optimize the nested FOR to the following
for (size_t i = 0, j = 0, k; i < num_frames; (j == n - 1) ? (j = 0,i++) : ++j) {
// If we've reached the end of the frame, reset j to zero.
// Then allocate the next frame and check for null.
if (j == 0 && !!(afp->frames[i] = calloc(n, sizeof(double)))) {
double* p = afp->frames[i];
for (long ii = ((long)i) - 1; 0 <= ii; ii--) {
free(afp->frames[--i]);
}
free(afp);
return (void*) p;
}
if (sz <= (k = (i*hop) + j)) break;
afp->frames[i][j] = x[k];
}
This actually compiles and runs just fine; but in my testing, when I try to access the last frame as in
xFrames->frames[xFrames->num_frames-1],
I get a segmentation fault. What's going on here? Am I neglecting an edge case in my loop? I've been looking over the code for awhile, but I might need a second set of eyes. Sorry if the answer is glaringly obvious; I'm a bit of a C novice.
P.S. I'm a fan of branchless programming, so if anyone has tips for cutting out those IFs, I'm all ears. I was using ternary operators before, but reverted to IFs for readability in debugging.
Remember that the logical operator && and || does short-circuit evaluation.
That means if j != 0 then you won't actually call calloc, and you'll have an invalid pointer in afp->frames[i].

Concatenating arrays in place

I ran into an issue while implementing a circular buffer that must occasionally be aligned.
Say I have two arrays, leftArr and rightArr. I want to move the right array to byteArr and the left array to byteArr + the length of the right array. Both leftArr and rightArr are greater than byteArr, and rightArr is greater than leftArr. (this is not quite the same as rotating a circular buffer because the left array does not need to start at byteArr) Although the left and right arrays do not overlap, the combined array stored at byteArr may overlap with the current arrays, stored at leftArr and rightArr. All memory from byteArr to rightArr + rightArrLen can be safely written to. One possible implementation is:
void align(char* byteArr, char* leftArr, int leftArrLen, char* rightArr, int rightArrLen) {
char *t = malloc(rightArrLen + leftArrLen);
// form concatenated data
memcpy(t, right, rightArrLen);
memcpy(t + rightArrLen, left, leftArrLen);
// now replace
memcpy(byteArr, t, rightArrLen + leftArrLen);
free(t);
}
However, I must accomplish this with constant memory complexity.
What I have so far looks like this:
void align(char* byteArr, char* leftArr, int leftArrLen, char* rightArr, int rightArrLen)
{
// first I check to see if some combination of memmove and memcpy will suffice, if not:
unsigned int lStart = leftArr - byteArr;
unsigned int lEnd = lStart + leftArrLen;
unsigned int rStart = rightArr - byteArr;
unsigned int rEnd = rStart + rightArrLen;
unsigned int lShift = rEnd - rStart - lStart;
unsigned int rShift = -rStart;
char temp1;
char temp2;
unsigned int nextIndex;
bool alreadyMoved;
// move the right array
for( unsigned int i = 0; i < rEnd - rStart; i++ )
{
alreadyMoved = false;
for( unsigned int j = i; j < rEnd - rStart; j-= rShift )
{
if( lStart <= j + rStart - lShift
&& j + rStart - lShift < lEnd
&& lStart <= (j + rStart) % lShift
&& (j + rStart) % lShift < lEnd
&& (j + rStart) % lShift < i )
{
alreadyMoved = true;
}
}
if(alreadyMoved)
{
// byte has already been moved
continue;
}
nextIndex = i - rShift;
temp1 = byteArr[nextIndex];
while( rStart <= nextIndex && nextIndex < rEnd )
{
nextIndex += rShift;
temp2 = byteArr[nextIndex];
byteArr[nextIndex] = temp1;
temp1 = temp2;
while( lStart <= nextIndex && nextIndex < lEnd )
{
nextIndex += lShift;
temp2 = byteArr[nextIndex];
byteArr[nextIndex] = temp1;
temp1 = temp2;
}
if( nextIndex <= i - rShift )
{
// byte has already been moved
break;
}
}
}
// move the left array
for( unsigned int i = lStart; i < lShift && i < lEnd; i++ )
{
if( i >= rEnd - rStart )
{
nextIndex = i + lShift;
temp1 = byteArr[nextIndex];
byteArr[nextIndex] = byteArr[i];
while( nextIndex < lEnd )
{
nextIndex += lShift;
temp2 = byteArr[nextIndex];
byteArr[nextIndex] = temp1;
temp1 = temp2;
}
}
}
}
This code works in the case lStart = 0, lLength = 11, rStart = 26, rLength = 70 but fails in the case lStart = 0, lLength = 46, rStart = 47, rLength = 53. The solution that I can see is to add logic to determine when a byte from the right array has already been moved. While this would be possible for me to do, I was wondering if there's a simpler solution to this problem that runs with constant memory complexity and without extra reads and writes?
Here's a program to test an implementation:
bool testAlign(int lStart, int lLength, int rStart, int rLength)
{
char* byteArr = (char*) malloc(100 * sizeof(char));
char* leftArr = byteArr + lStart;
char* rightArr = byteArr + rStart;
for(int i = 0; i < rLength; i++)
{
rightArr[i] = i;
}
for(int i = 0; i < lLength; i++)
{
leftArr[i] = i + rLength;
}
align(byteArr, leftArr, lLength, rightArr, rLength);
for(int i = 0; i < lLength + rLength; i++)
{
if(byteArr[i] != i) return false;
}
return true;
}
Imagine dividing byteArr into regions (not necessarily to scale):
X1 Left X2 Right
|---|--------|---|------|
The X1 and X2 are gaps in byteArr before the start of the left array and between the two arrays. In the general case, any or all of those four regions may have zero length.
You can then proceed like this:
Start by partially or wholly filling in the leading space in byteArr
If Left has zero length then move Right to the front (if necessary) via memmove(). Done.
Else if X1 is the same length as the Right array or larger then move the right array into that space via memcpy() and, possibly, move up the left array to abut it via memmove(). Done.
Else, move the lead portion of the Right array into that space, producing the below layout. If X1 had zero length then R1 also has zero length, X2' == X2, and R2 == Right.
R1 Left X2' R2
|---|--------|------|---|
There are now two alternatives
If R2 is the same length as Left or longer, then swap Left with the initial portion of R2 to produce (still not to scale):
R1' X2'' Left R2'
|------|-----|-------|--|
Otherwise, swap the initial portion of Left with all of R2 to produce (still not to scale):
R1' L2 X2'' L1
|------|---|-------|----|
Now recognize that in either case, you have a strictly smaller problem of the same form as the original, where the new byteArr is the tail of the original starting immediately after region R1'. In the first case the new leftArr is the (final) Left region and the new rightArr is region R2'. In the other case, the new leftArr is region L2, and the new rightArr is region L1. Reset parameters to reflect this new problem, and loop back to step (1).
Note that I say to loop back to step 1. You could, of course, implement this algorithm (tail-)recursively, but then to achieve constant space usage you would need to rely on your compiler to optimize out the tail recursion, which otherwise consumes auxiliary space proportional to the length ratio of the larger of the two sub-arrays to the smaller.

Sorting an array of coordinates by their distance from origin

The code should take an array of coordinates from the user, then sort that array, putting the coordinates in order of their distance from the origin. I believe my problem lies in the sorting function (I have used a quicksort).
I am trying to write the function myself to get a better understanding of it, which is why I'm not using qsort().
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_SIZE 64
typedef struct
{
double x, y;
}POINT;
double distance(POINT p1, POINT p2);
void sortpoints(double distances[MAX_SIZE], int firstindex, int lastindex, POINT data[MAX_SIZE]);
void printpoints(POINT data[], int n_points);
int main()
{
int n_points, i;
POINT data[MAX_SIZE], origin = { 0, 0 };
double distances[MAX_SIZE];
printf("How many values would you like to enter?\n");
scanf("%d", &n_points);
printf("enter your coordinates\n");
for (i = 0; i < n_points; i++)
{
scanf("%lf %lf", &data[i].x, &data[i].y);
distances[i] = distance(data[i], origin); //data and distances is linked by their index number in both arrays
}
sortpoints(distances, 0, i, data);
return 0;
}
double distance(POINT p1, POINT p2)
{
return sqrt(pow((p1.x - p2.x), 2) + pow((p1.y - p2.y), 2));
}
void printpoints(POINT *data, int n_points)
{
int i;
printf("Sorted points (according to distance from the origin):\n");
for (i = 0; i < n_points; i++)
{
printf("%.2lf %.2lf\n", data[i].x, data[i].y);
}
}
//quicksort
void sortpoints(double distances[MAX_SIZE], int firstindex, int lastindex, POINT data[MAX_SIZE])
{
int indexleft = firstindex;
int indexright = lastindex;
int indexpivot = (int)((lastindex + 1) / 2);
int n_points = lastindex + 1;
double left = distances[indexleft];
double right = distances[indexright];
double pivot = distances[indexpivot];
POINT temp;
if (firstindex < lastindex) //this will halt the recursion of the sorting function once all the arrays are 1-size
{
while (indexleft < indexpivot || indexright > indexpivot) //this will stop the sorting once both selectors reach the pivot position
{
//reset the values of left and right for the iterations of this loop
left = distances[indexleft];
right = distances[indexright];
while (left < pivot)
{
indexleft++;
left = distances[indexleft];
}
while (right > pivot)
{
indexright--;
right = distances[indexright];
}
distances[indexright] = left;
distances[indexleft] = right;
temp = data[indexleft];
data[indexleft] = data[indexright];
data[indexright] = temp;
}
//recursive sorting to sort the sublists
sortpoints(distances, firstindex, indexpivot - 1, data);
sortpoints(distances, indexpivot + 1, lastindex, data);
}
printpoints(data, n_points);
}
Thanks for your help, I have been trying to debug this for hours, even using a debugger.
Ouch! You call sortpoints() with i as argument. That argument, according to your prototype and code, should be the last index, and i is not the last index, but the last index + 1.
int indexleft = firstindex;
int indexright = lastindex; // indexright is pointing to a non-existent element.
int indexpivot = (int)((lastindex + 1) / 2);
int n_points = lastindex + 1;
double left = distances[indexleft];
double right = distances[indexright]; // now right is an undefined value, or segfault.
To fix that, call your sortpoints() function as:
sortpoints (0, n_points-1, data);
The problem is in your sortpoints function. The first while loop is looping infinitely. To test that is it an infinite loop or not place a printf statement
printf("Testing first while loop\n");
in your first while loop. You have to fix that.
There are quite a number of problems, but one of them is:
int indexpivot = (int)((lastindex + 1) / 2);
The cast is unnecessary, but that's trivia. Much more fundamental is that if you are sorting a segment from, say, 48..63, you will be pivoting on element 32, which is not in the range you are supposed to be working on. You need to use:
int indexpivot = (lastindex + firstindex) / 2;
or perhaps:
int indexpivot = (lastindex + firstindex + 1) / 2;
For the example range, these will pivot on element 55 or 56, which is at least within the range.
I strongly recommend:
Creating a print function similar to printpoints() but with the following differences:
Takes a 'tag' string to identify what it is printing.
Takes and prints the distance array too.
Takes the arrays and a pair of offsets.
Use this function inside the sort function before recursing.
Use this function inside the sort function before returning.
Use this function in the main function after you've read the data.
Use this function in the main function after the data is sorted.
Print key values — the pivot distance, the pivot index, at appropriate points.
This allows you to check that your partitioning is working correctly (it isn't at the moment).
Then, when you've got the code working, you can remove or disable (comment out) the printing code in the sort function.

Removing Duplicates in an array in C

The question is a little complex. The problem here is to get rid of duplicates and save the unique elements of array into another array with their original sequence.
For example :
If the input is entered b a c a d t
The result should be : b a c d t in the exact state that the input entered.
So, for sorting the array then checking couldn't work since I lost the original sequence. I was advised to use array of indices but I don't know how to do. So what is your advise to do that?
For those who are willing to answer the question I wanted to add some specific information.
char** finduni(char *words[100],int limit)
{
//
//Methods here
//
}
is the my function. The array whose duplicates should be removed and stored in a different array is words[100]. So, the process will be done on this. I firstly thought about getting all the elements of words into another array and sort that array but that doesn't work after some tests. Just a reminder for solvers :).
Well, here is a version for char types. Note it doesn't scale.
#include "stdio.h"
#include "string.h"
void removeDuplicates(unsigned char *string)
{
unsigned char allCharacters [256] = { 0 };
int lookAt;
int writeTo = 0;
for(lookAt = 0; lookAt < strlen(string); lookAt++)
{
if(allCharacters[ string[lookAt] ] == 0)
{
allCharacters[ string[lookAt] ] = 1; // mark it seen
string[writeTo++] = string[lookAt]; // copy it
}
}
string[writeTo] = '\0';
}
int main()
{
char word[] = "abbbcdefbbbghasdddaiouasdf";
removeDuplicates(word);
printf("Word is now [%s]\n", word);
return 0;
}
The following is the output:
Word is now [abcdefghsiou]
Is that something like what you want? You can modify the method if there are spaces between the letters, but if you use int, float, double or char * as the types, this method won't scale at all.
EDIT
I posted and then saw your clarification, where it's an array of char *. I'll update the method.
I hope this isn't too much code. I adapted this QuickSort algorithm and basically added index memory to it. The algorithm is O(n log n), as the 3 steps below are additive and that is the worst case complexity of 2 of them.
Sort the array of strings, but every swap should be reflected in the index array as well. After this stage, the i'th element of originalIndices holds the original index of the i'th element of the sorted array.
Remove duplicate elements in the sorted array by setting them to NULL, and setting the index value to elements, which is the highest any can be.
Sort the array of original indices, and make sure every swap is reflected in the array of strings. This gives us back the original array of strings, except the duplicates are at the end and they are all NULL.
For good measure, I return the new count of elements.
Code:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
void sortArrayAndSetCriteria(char **arr, int elements, int *originalIndices)
{
#define MAX_LEVELS 1000
char *piv;
int beg[MAX_LEVELS], end[MAX_LEVELS], i=0, L, R;
int idx, cidx;
for(idx = 0; idx < elements; idx++)
originalIndices[idx] = idx;
beg[0] = 0;
end[0] = elements;
while (i>=0)
{
L = beg[i];
R = end[i] - 1;
if (L<R)
{
piv = arr[L];
cidx = originalIndices[L];
if (i==MAX_LEVELS-1)
return;
while (L < R)
{
while (strcmp(arr[R], piv) >= 0 && L < R) R--;
if (L < R)
{
arr[L] = arr[R];
originalIndices[L++] = originalIndices[R];
}
while (strcmp(arr[L], piv) <= 0 && L < R) L++;
if (L < R)
{
arr[R] = arr[L];
originalIndices[R--] = originalIndices[L];
}
}
arr[L] = piv;
originalIndices[L] = cidx;
beg[i + 1] = L + 1;
end[i + 1] = end[i];
end[i++] = L;
}
else
{
i--;
}
}
}
int removeDuplicatesFromBoth(char **arr, int elements, int *originalIndices)
{
// now remove duplicates
int i = 1, newLimit = 1;
char *curr = arr[0];
while (i < elements)
{
if(strcmp(curr, arr[i]) == 0)
{
arr[i] = NULL; // free this if it was malloc'd
originalIndices[i] = elements; // place it at the end
}
else
{
curr = arr[i];
newLimit++;
}
i++;
}
return newLimit;
}
void sortArrayBasedOnCriteria(char **arr, int elements, int *originalIndices)
{
#define MAX_LEVELS 1000
int piv;
int beg[MAX_LEVELS], end[MAX_LEVELS], i=0, L, R;
int idx;
char *cidx;
beg[0] = 0;
end[0] = elements;
while (i>=0)
{
L = beg[i];
R = end[i] - 1;
if (L<R)
{
piv = originalIndices[L];
cidx = arr[L];
if (i==MAX_LEVELS-1)
return;
while (L < R)
{
while (originalIndices[R] >= piv && L < R) R--;
if (L < R)
{
arr[L] = arr[R];
originalIndices[L++] = originalIndices[R];
}
while (originalIndices[L] <= piv && L < R) L++;
if (L < R)
{
arr[R] = arr[L];
originalIndices[R--] = originalIndices[L];
}
}
arr[L] = cidx;
originalIndices[L] = piv;
beg[i + 1] = L + 1;
end[i + 1] = end[i];
end[i++] = L;
}
else
{
i--;
}
}
}
int removeDuplicateStrings(char *words[], int limit)
{
int *indices = (int *)malloc(limit * sizeof(int));
int newLimit;
sortArrayAndSetCriteria(words, limit, indices);
newLimit = removeDuplicatesFromBoth(words, limit, indices);
sortArrayBasedOnCriteria(words, limit, indices);
free(indices);
return newLimit;
}
int main()
{
char *words[] = { "abc", "def", "bad", "hello", "captain", "def", "abc", "goodbye" };
int newLimit = removeDuplicateStrings(words, 8);
int i = 0;
for(i = 0; i < newLimit; i++) printf(" Word # %d = %s\n", i, words[i]);
return 0;
}
Traverse through the items in the array - O(n) operation
For each item, add it to another sorted-array
Before adding it to the sorted array, check if the entry already exists - O(log n) operation
Finally, O(n log n) operation
i think that in C you can create a second array. then you copy the element from the original array only if this element is not already in the send array.
this also preserve the order of the element.
if you read the element one by one you can discard the element before insert in the original array, this could speedup the process.
As Thomas suggested in a comment, if each element of the array is guaranteed to be from a limited set of values (such as a char) you can achieve this in O(n) time.
Keep an array of 256 bool (or int if your compiler doesn't support bool) or however many different discrete values could possibly be in the array. Initialize all the values to false.
Scan the input array one-by-one.
For each element, if the corresponding value in the bool array is false, add it to the output array and set the bool array value to true. Otherwise, do nothing.
You know how to do it for char type, right?
You can do same thing with strings, but instead of using array of bools (which is technically an implementation of "set" object), you'll have to simulate the "set"(or array of bools) with a linear array of strings you already encountered. I.e. you have an array of strings you already saw, for each new string you check if it is in array of "seen" strings, if it is, then you ignore it (not unique), if it is not in array, you add it to both array of seen strings and output. If you have a small number of different strings (below 1000), you could ignore performance optimizations, and simply compare each new string with everything you already saw before.
With large number of strings (few thousands), however, you'll need to optimize things a bit:
1) Every time you add a new string to an array of strings you already saw, sort the array with insertion sort algorithm. Don't use quickSort, because insertion sort tends to be faster when data is almost sorted.
2) When checking if string is in array, use binary search.
If number of different strings is reasonable (i.e. you don't have billions of unique strings), this approach should be fast enough.

Resources