C: Trying to insert a struct into a struct array - c

in my code I have student profiles with name, age, and GPA. I also have an array with each profile. I'm trying to create an insert function that inserts another student profile into the array and display an error if the index is not valid. I'm trying to do so by moving adding another space in the array for the new student, then moving over the places of students occupying the wrong space by one space to the right.
Ex. If I want to put a student in index 2, the function would move the student occupying that space to 3, and the student in 3 would be moved to space 4.
Here's what I have so far, but I'm getting an error on array[i+1] = isaying "incompatible types when assigning to type Student from type type int." I tried changing i to type Student, I got several more errors all over the loop saying that it was an invalid initializer and that I couldn't use >=, and that i was the "wrong type to decrement

For starters it is unclear why the parameter index has the signed type int instead of the unsigned type size_t. The unsigned type allows to avoid this redundant check
if (index < 0 || index > *size) {
^^^^^^^^^
Also if the value of index is greater than the current value of *size then it is enough just to append the passed item to the array.
So in general this check
if (index < 0 || index > *size) {
is redundant.
The function declaration is too complicated. There is no need to return pointer to the first element of the passed array. The function declaration will look more simpler if to write it like
size_t insert( Student a[], size_t n, size_t i, const Student *student );
That is the function returns the new size of the updated array.
This statement
array[i+1] = i;
does not make any sense because the left operand has the type Student while the right operand has the type int. Moreover it has a logical error because instead of the index i + 1 you have to use the index i.
And instead of the manually written loop you could use the standard C function memmove.
Here is a demonstrative program that shows how the function can be defined.
#include <stdio.h>
#include <string.h>
#define MAX_LEN 10
typedef struct Student
{
char name[MAX_LEN];
unsigned int age;
} Student;
size_t insert( Student a[], size_t n, size_t i, const Student *student )
{
if ( n < i ) i = n;
if ( i < n )
{
memmove( a + i + 1, a + i, ( n - i ) * ( sizeof( Student ) ) );
}
a[i] = *student;
return ++n;
}
int main(void)
{
enum { N = 10 };
Student a[N] = { 0 };
Student student = { "A", 20 };
size_t n = insert( a, 0, 0, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
strcpy( student.name, "B" );
++student.age;
n = insert( a, n, 0, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
strcpy( student.name, "C" );
++student.age;
n = insert( a, n, 2, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
strcpy( student.name, "E" );
++student.age;
n = insert( a, n, 1, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
return 0;
}
The program output is
{ A, 20 }
{ B, 21 } { A, 20 }
{ B, 21 } { A, 20 } { C, 22 }
{ B, 21 } { E, 23 } { A, 20 } { C, 22 }

The used indentation style makes it difficult to easily see if the parenthesis are correctly closed. Please use an automatic formatter, example: clang-format
Your function is not very safe. It should take another parameter max_size so the assigned memory is known
If a return is used in if branch, the else branch does not have to be explicitly declared.
A for loop already has a condition, if the only functionality in the loop is an if, it can be hoisted up into that condition.
To move students from a place in an array a "copy" of the student has to be made to the new location - not just it's index.
Fixed:
Student* insert(Student* array, int max_size, int* size, int index, Student s)
{
//error message and return NULL if space is - or > array size
if (index < 0 || index > *size || *size + 1 > max_size)
{
printf("ERROR\n");
array = NULL;
return array;
}
for (int i = *size; i > index && i > 0; --i)
{
//move students at index or > over to make open space
array[i] = array[i - 1];
}
//put new student in correct location
array[index] = s;
*size += 1;
return array;
}

Related

Remove negatives works for some cases, but behaves strange for case 3

Im creating a code in C to remove all the negatives when given a double pointer array with some values, as well as a constant int size. My code behaves strange for the 3rd case, but works for the others. Can someone help point me in the right direction?
short remove_negatives(long** array, const int size){
if (!*array || !array || !**array){
printf("Error(remove_negatives): invalid array\n");
return -1;
}
if (size <= 0){
printf("Error(remove_negatives): invalid size\n");
return -1;
}
short count = 0;
int i;
for (i=0;i<size;i++){
if (*(*array+i) < 0){
*(*array + i) = *(*array + i + 1);
count += 1;
}
}
return count;
}
the output:
------------------------------
Start: Testing remove_negatives:
Case 1:
Before: {10,20,-10,30,40}
after: {10,20,30,30}
# removed items = 1
Case 2:
Before: {-10,20,-30,40,50,60,70}
after: {20,20,40,40,50}
# removed items = 2
Case 3:
Before: {10,-20,-30,-40,50}
after: {10,-30}
# removed items = 3
Case 4:
Before: {10,-20,-30,-40}
after: {10}
# removed items = 3
Case 5:
Before: {-10,-20,-30}
after: {}
# removed items = 3
Case 6:
Error(remove_negatives): invalid size
It is entirely unclear why the first function parameter has the type long ** array
short remove_negatives(long** array, const int size){
instead of long *array or long array[].
Also this if statement
if (!*array || !array || !**array){
does not make a sense. Why may not for example **array be equal to 0? And at least the first expression in the if statement must be !array.
Nevertheless the function is incorrect at least due to this for loop
for (i=0;i<size;i++){
if (*(*array+i) < 0){
*(*array + i) = *(*array + i + 1);
count += 1;
}
}
If a negative element is encountered then it is replaced by the value of the next element.
*(*array + i) = *(*array + i + 1);
As a result if the next element is not negative then the two adjacent elements will have the same value. And this test case
Case 1:
Before: {10,20,-10,30,40}
after: {10,20,30,30}
# removed items = 1
demonstrates that.
Instead you need to move to the left all elements one position.
Moreover the for loop can invoke undefined behavior because the expression
*array + i + 1
can access memory beyond the array when i is equal to size - 1.
Below there is a demonstration program that shows how your function can be implemented.
#include <stdio.h>
size_t remove_negatives( int **a, size_t n )
{
size_t k = 0;
for ( int *p = *a, *q = *a; p != *a + n; ++p )
{
if ( *p < 0 )
{
++k;
}
else
{
if ( p != q ) *q = *p;
++q;
}
}
return k;
}
int main( void )
{
while ( 1 )
{
size_t n;
printf( "Enter the size of the array (0 - exit): " );
if ( scanf( "%zu", &n ) != 1 || n == 0 ) break;
int a[n];
printf( "Enter %zu values: ", n );
for ( size_t i = 0; i < n; i++ )
{
scanf( "%d", &a[i] );
}
printf( "Before: {" );
for ( size_t i = 0; i < n; i++ )
{
printf( " %d", a[i] );
}
puts( " }" );
int *p = a;
size_t k = remove_negatives( &p, n );
printf( "After: {" );
for ( size_t i = 0; i < n - k; i++ )
{
printf( " %d", a[i] );
}
puts( " }" );
printf( "# removed items = %zu\n ", k );
}
}
For example if to enter data as in the test case #2 then the output of the array will look like
Before: { -10 20 -30 40 50 60 70 }
After: { 20 40 50 60 70 }
# removed items = 2

Print all elements in an array just once in C?

I have created an array in C and I know how to print every element in an array but couldn't figure it out how to not print repeated elements, or to be more precise, like I ask in the title, how can I print all elements just once?
For example my array is: [a b c d a a b d c c]
I want to print it like this: [a b c d]
I think that I should use for or while loop, but I don't know how. I have been thinking about this for hours and did some research but couldn't find anything valuable.
Here you are.
#include <stdio.h>
int main(void)
{
char a[] = { 'a', 'b', 'c', 'd', 'a', 'a', 'b', 'd', 'c', 'c' };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
size_t j = 0;
while ( j != i && a[j] != a[i] ) ++j;
if ( j == i ) printf( "%c ", a[i] );
}
putchar ( '\n' );
return 0;
}
The program output is
a b c d
Or for example if you have a character array that contains a string then the same approach can be implemented the following way.
#include <stdio.h>
int main(void)
{
char s[] = { "abcdaabdcc" };
for (const char *p = s; *p != '\0'; ++p )
{
const char *prev = s;
while ( prev != p && *prev != *p ) ++prev;
if ( prev == p ) printf( "%c ", *p );
}
putchar ( '\n' );
return 0;
}
The program output is the same as shown above that is
a b c d
As the array is an array of char containing lower case letters, there are pretty few different values. Consequently, you can make a table (aka another array) to track the already printed values.
Like:
#define MAX ('z' - 'a' + 1) // Calculate the number of unique elements
int already_printed[MAX] = { 0 }; // Mark all chars as "not printed"
for (i = 0; i < SIZE_OFF_ARRAY; ++i)
{
if (already_printed[array[i] - 'a'] == 0) // If NOT printed yet
{
printf("%c\n", array[i]); // Print it and
already_printed[array[i] - 'a'] = 1; // mark it as printed
}
}
This gives you a simple O(N) solution. Having a O(N) solution is important for performance when handling large arrays.
Notice: This solution assumes that all array element are between 'a' and 'z' (both included) but can easilly be extended to support more a wider range.
I'm not sure what the type of the elements in the array is, but let's assume it's some type that C can "natively" compare. Then the conceptually simple solution is to sort the array, and the print it skipping duplicates. Sorting will ensure that the duplicates are adjacent. This approach will perform well in most circumstances.
First, let's set up some helper functions specific to the element type. You could remove the assign function if you only want to deal with char type, but it'll be inlined by the compiler anyway.
#include <stdlib.h>
#include <stdio.h>
// You can adapt the element type per your requirements
typedef char ElementType;
// This function assigns the source value to the destination:
// it does what *dst = *src would do.
static inline void assign(void *dst, const void *src)
{
*(ElementType*)dst = *(const ElementType*)src;
}
// This is the "spaceship" comparison operator (<=> in C++) that
// merges less-than, equal, and more-than comparisons into one.
int compare(const void *l, const void *r)
{
const ElementType *L = l;
const ElementType *R = r;
if (*L < *R) return -1;
if (*L > *R) return 1;
return 0;
}
void print_element(const ElementType *el) { printf("%c", *el); }
Since we plan to sort the array, we need to copy it first - after all, a "printer" for an array shouldn't be modifying it. Such modifications are OK in tiny programs, but are just a bad habit, since if you look at the name of the function like print_unique, nothing hints you that it would modify the data it's supposed to print: that's not how printing normally acts. It'd be unexpected and very error prone.
The copy operation could be skipped if it's OK to modify the source array: its elements would need to be non-const then, and the print_unique function name would need to be changed to something like sort_and_print_unique.
ElementType *copy_array(const ElementType *src, const int count)
{
ElementType *copy = malloc(sizeof(ElementType) * count);
if (!copy) abort;
for (int i = 0; i < count; ++i)
assign(copy + i, src + i);
return copy;
}
And now the unique element printer, and a test with the data you provided:
void print_unique(const ElementType *data, int const count)
{
ElementType *copy = copy_array(data, count);
qsort(copy, count, sizeof(ElementType), compare);
printf("[");
for (int i = 0; i < count; ++i) {
if (i == 0 || compare(copy+i, copy+i-1) != 0) {
if (i != 0) printf(" ");
print_element(copy+i);
}
}
printf("]\n");
}
int main() {
const char array[] = "abcdaabdcc";
print_unique(array, sizeof(array)/sizeof(*array) - 1);
}
Output: [a b c d]
The alternate, modifying implementation I mentioned above would be:
void sort_and_print_unique(ElementType *data, int const count)
{
qsort(data, count, sizeof(ElementType), compare);
printf("[");
for (int i = 0; i < count; ++i) {
if (i == 0 || compare(data+i, data+i-1) != 0) {
if (i != 0) printf(" ");
print_element(data+i);
}
}
printf("]\n");
}
int main() {
char array[] = "abcdaabdcc"; // note absence of const!
sort_and_print_unique(array, sizeof(array)/sizeof(*array) - 1);
}
A simple way:
#include <stdio.h>
int main() {
int ascii[128] = { 0 };
char input[] = "abcdaabdcc";
for(int i = 0; input[i]; i++) {
++ascii[(int)input[i]];
}
for(int i = 0; i < 128; i++) {
if( ascii[i] ) printf("%c ", i);
}
return 0;
}
The array ascii is used to keep track of the frequency of each of the 128 ascii characters with a non negative value (for example 'a' is 97 and '0' is 48). And then if the frequency of a character is not 0, you print the character.
First, sort the array (use qsort(3) for example), then all the equal elements will be together. Then go in a one pass on the array saving the last element printed... if the one to be printed now is the same as the one printed last, just skip it and continue; to the next.

odd or even number using pointer in C

I have an array, the elements inside this array should be assigned randomly
then I create two more arrays one for odd and one for even numbers
using pointers I want to put the odd numbers inside the odd array, and the even numbers in the even one.
how can I assign it using pointers?
I came up with this:
int main()
{
int array[10];
int *arrayPtr = &array;
int arrayEven[10];
int *pEven = &arrayEven;
int arrayOdd[10];
int * pOdd = &arrayOdd;
int i, j;
for(i=0; i<10; i++)
{
array[i] =rand()%100 ;
if(array[i] %2 ==0)
{
printf("%d\n", array[i]);
printf("Even number");
}
else
{
printf("%d\n", array[i]);
printf("Odd number");
}
}
These declarations of pointers
int *arrayPtr = &array;
int *pEven = &arrayEven;
int * pOdd = &arrayOdd;
are incorrect. The initializers have the type int( * )[10] according to the declarations of the arrays as for example of the variable array
int array[10];
while the declared pointers has incompatible type int *.
What you need is declarations like this
int *arrayPtr = array;
There is no great sense to define arrays of the same size as the source array because for example the source array can have no odd or even numbers. You should deal with arrays depending on the number of odd and even numbers in the source array. If your compiler supports variable length arrays then you can use them. Or you should dynamically allocate arrays.
Here is a demonstrative program that shows how the assignment can be done using variable length arrays and pointers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void copy_if( const int a1[], size_t n, int *a2, int *a3, int predicate( int ) )
{
for ( const int *p = a1; p != a1 + n; ++p )
{
if ( predicate( *p ) )
{
*a2++ = *p;
}
else
{
*a3++ = *p;
}
}
}
size_t count_if( const int a[], size_t n, int predicate( int ) )
{
size_t cnt = 0;
for ( const int *p = a; p != a + n; ++p )
{
if ( predicate( *p ) ) ++cnt;
}
return cnt;
}
int is_even( int x )
{
return x % 2 == 0;
}
int main(void)
{
enum { N = 10 };
int a1[N];
srand( ( unsigned int )time( NULL ) );
for ( int *p = a1; p != a1 + N; ++p )
{
*p = rand() % N;
}
for ( const int *p = a1; p != a1 + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
size_t cnt = count_if( a1, N, is_even );
if ( cnt != 0 && cnt != N )
{
int a2[cnt];
int a3[N-cnt];
copy_if( a1, N, a2, a3, is_even );
for ( const int *p = a2; p != a2 + cnt; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
for ( const int *p = a3; p != a3 + N - cnt; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
}
return 0;
}
The program output might look like
6 3 3 8 3 0 5 5 3 2
6 8 0 2
3 3 3 5 5 3
If to use your straightforward approach then the program can look the following way
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
enum { N = 10 };
int array[N];
int *arrayPtr = array;
srand( ( unsigned int )time( NULL ) );
for ( int *p = arrayPtr; p != arrayPtr + N; ++p )
{
*p = rand() % N;
}
for ( const int *p = arrayPtr; p != arrayPtr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
int arrayEven[10];
int *pEven = arrayEven;
int arrayOdd[10];
int *pOdd = arrayOdd;
int *pEvenEnd = pEven;
int *pOddEnd = pOdd;
for ( const int *p = array; p != arrayPtr + N; ++p )
{
if ( *p % 2 == 0 )
{
*pEvenEnd++ = *p;
}
else
{
*pOddEnd++ = *p;
}
}
for ( const int *p = pEven; p != pEvenEnd; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
for ( const int *p = pOdd; p != pOddEnd; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
Its output might look for example like
1 0 0 3 4 5 2 1 9 5
0 0 4 2
1 3 5 1 9 5
For it to work you need two additional coutner variables
int oddCount, evenCount;
these need to be initialized to be 0 (i.e. how many odd/even number you have inserted so far). Then while iterating your first array you increment the respective coutner if you encounter an even/odd number. Also you can just use these variables to know where you need to put the next even/odd number in their respective array.
You can use binary comparison since all odd finish by 1 in binary mode :
If( a & 1)
//Odd
Else
//Even

Q: Arrays and Functions Homework

To put it bluntly, as it stands, I am not very good at coding at this current time. I am really trying to get these functions completed, I am just having trouble with the execution on some of them.
Basically, there are 10 functions ( 6 of which I have finished? ) that need to be created.
There is an int main() but, besides a string that needs to be fixed, the int main() does not need to be touched.
I will post the program (mostly so you can see my work) in addition to the int main() so that if someone wants to check the intent, they can see it. Even though I have posted the whole program, the only ones that I really want to focus on are the makeUpper, and the functions that have nothing in them because I really don't understand how to copy and edit a string into another array.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
void makeUpper( char orig[], char result[] )
{
/*
int i = 0;
while ( str[i] != '\0' )
{
if ( str[i] >= 'a' && str[i] <= 'z' )
str[i] = str[i] - 32;
k++;
}
*/
}
int countDigit( char str[] )
{
int i;
int count = 0;
int len;
len = strlen(str);
for ( i = 0; i < len; i++ )
{
if ( i >= '0' && i <= '9' )
count++;
}
return count;
}
int onlyLetters( char orig[], char letters[] )
{
}
int countOdd( int A[], int N )
{
int i;
int odd = 0;
for ( i = 0; i < N; i++ );
{
if ( A[i] % 2 != 0 )
odd++;
}
return odd;
}
int sumList( int A[], int N )
{
int i;
int sum = 0;
for ( i = 0; i < N; i++ );
sum = sum + A[i];
return sum;
}
void addToEach( int A[], int N, int val )
{
int i;
for ( i = 0; i < N; i++ )
A[i] + val;
printf("%d", A[i]);
}
void copyNumList( int orig[], int N, int result[] )
{
}
// populate list A with N items, random in range L to H
void fillNumList( int A[], int N, int L, int H )
{
}
// print the list, 10 items per line
void printList( int A[], int N )
{
int i;
for ( i = 0; i < N; i++ )
printf("%d ", A[i]);
printf("\n");
}
void rept( int n, char c )
{
int i;
for ( i = 0; i < n; i++ )
printf("%c", c);
printf("\n");
}
int main()
{
char line[100], other[100];
int i, len;
printf("Phrase: ");
fgets( line, 100, stdin );
// fix the string....
// ...
// really, do this
// ...
rept(10,'-');
printf("Orig: ##%s##\n", line);
rept(10,'-');
makeUpper( line, other );
printf("toupper: %s\n", other);
rept(10,'-');
i = countDigit( line );
printf("%d digits\n", i);
rept(10,'-');
len = onlyLetters( line, other );
printf("only letters: %s\n", other );
printf(" new len %d\n", len);
int nums[30], vals[30];
int many = 19;
rept(5, '-');
fillNumList( nums, many, 3, 11 );
printList( nums, many );
rept(5, '-');
i = countOdd( nums, many );
printf("%d odd values\n", i);
rept(5, '-');
i = sumList( nums, many );
printf("%d is sum\n", i);
rept(5, '-');
copyNumList( nums, many, vals );
printf("Copy\n");
printList( vals, many );
rept(5, '-');
addToEach( vals, many, 4 );
printf("Add 4\n");
printList( vals, many );
rept(5, '-');
printf("Orig\n");
printList( nums, many );
rept(5, '-');
return 0;
}
To answer the one almost-well-defined question (regarding makeUpper):
First, str is not a variable. You have orig and result, and haven't declared str anywhere.
Now, if str were orig, you'd be correctly uppercasing the characters in the original string. However, the task is to leave the original string alone and make an uppercased copy. The former is called "destructive operation" (as the original contents are not preserved); the latter, a "non-destructive operation" (for obvious reasons). Here are the changes needed to make your function non-destructive:
void makeUpper( char orig[], char result[] )
{
int k = 0;
do
{
if ( orig[k] >= 'a' && orig[k] <= 'z' )
result[k] = orig[k] - 32;
else
result[k] = orig[k];
} while ( orig[k++] != '\0' );
}
Notice that I iterate and test on orig, but assign to result.
onlyLetters should be similar; but you will need two index variables, not just k, since you will want to progress through orig and result at different pace (you'll only want to copy a character when it's a letter, and you'll only want to progress through result when you do a copy - as opposed to orig, which you'll always consume one character per loop).
As you have not stated what your misunderstanding is about copyNumList and fillNumList, I cannot give you any help there.
EDIT: I forgot about the terminator (and didn't test it); thanks Tom Karzes! Because the zero also needs to be copied, your loop is changed from while (condition) { ... } to do { ... } while (condition) - instead of testing whether we're at end and then doing things if we're not, we'll do the thing first, and only afterwards ask if we're done. This also requires the increment to be done after the test, so k++ got moved. If this is too weird for you, you can get the same effect like this, by explicitly adding the terminator after the loop is done:
void makeUpper( char orig[], char result[] )
{
int k = 0;
while ( orig[k] != '\0' )
{
if ( orig[k] >= 'a' && orig[k] <= 'z' )
result[k] = orig[k] - 32;
else
result[k] = orig[k];
k++;
}
result[k] = '\0';
}

Copying strings between vectors of strings in C

I have an array of char pointers (string array), which contains some duplicate values. I've found an algorithm that truncates the array by removing its duplicate values.
Here is a code sample :
int i, j , k;
int n = 10;
char *teams[n];
for(i=0;i<n;i++){
for(j=i+1;j<n;){
if(*(team[j]==*(team[i])){
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
n--;
}else{
j++;
}
}
}
I've read that the only way to copy strings between string arrays is to use strcpy(s1, s2). But in my case I can't use it, because strcpy function permits to copy s2 into s1 only if s2 has a lenght equal or bigger than the lenght of s1. So how can I implement this algorithm if I can't put the string pointed by the pointer team[k+1] in team[k] ?
It seems you need to remove duplicated string representations instead of duplicated addresses to strings.
If so then this if statement (if to add missed closed parenthesis)
if( *(team[j] ) ==*( team[i] ) ){
compares only first characters of strings instead of comparing strings pointed to by the pointers.
In this loop
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
each time when a duplicates string is found there is copied the whole array of pointers. Moreover there is an attempt to access memory beyond the array in this statement when k is equal to n-1
team[k] = team[k+1];
^^^^
You can write a separate function that will "remove" duplicates. The function can for example return pointer after the last unique element in the modified array.
#include <stdio.h>
#include <string.h>
char ** unique( char *s[], size_t n )
{
size_t i = 0;
for ( size_t j = 0; j < n; j++ )
{
size_t k = 0;
while ( k < i && strcmp( s[k], s[j] ) != 0 ) ++k;
if ( k == i )
{
if ( i != j ) s[i] = s[j];
++i;
}
}
return s + i;
}
int main(void)
{
char * s[] = { "A", "B", "A", "C", "A" };
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ ) printf( "%s ", s[i] );
printf( "\n" );
char **p = unique( s, N );
size_t n = p - s;
for ( size_t i = 0; i < n; i++ ) printf( "%s ", s[i] );
printf( "\n" );
return 0;
}
The program output is
A B A C A
A B C
#include <stdio.h>
#include <string.h>
unsigned dedup(char **arr, unsigned count)
{
unsigned this, that ;
for(this=0;this<count;this++){
for(that=this+1;that<count;){
if( strcmp(arr[that], arr[this])) {that++; continue; }
#if PRESERVE_ORDER
memmove(arr+that, arr+that+1, (--count - that) * sizeof arr[that] );
#else
arr[that] = arr[--count];
#endif
}
}
return count; /* the count after deduplication */
}
char *array[] = { "one", "two", "three", "two", "one", "four", "five", "two" };
int main(void)
{
unsigned count, index;
count = dedup(array, 8);
for (index = 0; index < count; index++) {
printf("%s\n", array[index] );
}
return 0;
}
[UPDATED]: I added the PRESERVE_ORDER version

Resources