C insertion sort with function as parameter - c

I'm trying to implement an insertion sort algorithm and it almost works. My code is the following:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int compare_desc(const char *input1, const char *input2){
char a = (*input1);
char b = (*input2);
if (a == b){
return 0;
}
if (a > b){
return -1;
}
return 1;
}
int compare_ignore_case_asc(const char *input1, const char *input2){
char a = tolower(*input1);
char b = tolower(*input2);
if (a == b) {
return 0;
}
if (a > b) {
return 1;
}
return -1;
}
void insertion_sort(char *array, size_t n, int (*compare)(const char *, const char *))
{
for (size_t i = 1; i < n; i++)
{
for (size_t j = i; j > 0 && compare(&array[j-1], &array[j]); --j){
char temp = array[j-1];
array[j-1] = array[j];
array[j] = temp;
}
}
}
int main(void) {
return EXIT_SUCCESS;
}
This code compares with the two compare functions (they are already correct and tested with test cases).
Am I somehow misunderstanding the point of insertion sort?
The problem I'm facing is the following:
'insertion_sort':
=================
After executing the function 'insertion_sort' the order of the values in the array 'base' is not as expected!
String representation of the contents of the array 'base' after execution:
Expected: "First"
Actual : "iFstr"
The following code snippet led to this error:
char array[] = "rtsFi";
size_t length = 5;
int (*compare)(const char *, const char *) = compare_ignore_case_asc;
insertion_sort(array, length, compare);
Where is my mistake?
I already tried and google and debug but I don't see the mistake I am currently making.

Related

My string assigning correctly into my char array (C)

#include <stdio.h>
#include <string.h>
void mirror(char c[])
{
int l = strlen(c);
char s;
for (int i = 0; i < l/2;i++)
{
s = c[i];
c[i] = c[l-i-1];
c[l-i-1] = s;
}
}
void decimal_to_binary(unsigned int n,char binary_res[]){
char r = n%2;
unsigned int q = (n - r)/2;
int i = 0;
while (q != 0)
{
i++;
r = n%2;
q = (n - r)/2;
n = q;
printf("%d\n",q);
binary_res[i] = r+'0';
}
mirror(binary_res);
}
int main(){
int n = 34; char res[10];
printf("%d\n",n);
decimal_to_binary(n,res);
printf("%s\n",res);
return 0;
}
I wrote this code which is really simple and I wanted it to convert a decimal to a binary through some repeated divisions. But there is a problem I don't understand because if I remove the +'0' when I assign the rest to the ith value in the result array, it displays nothing when I call it printf but when I add the +'0' it adds some weird characters. But I think i cmes from the fact that it is not ascii encording but UTF-8 so 0 hasn't a value of 0 but of 48. But the 0 value is for a null string so '' but when I add it to the r with +'' it shows nothing !
I don't understand what I am doing wrong here but I think there is multiple things I do wrong.
Thanks in advance !
I see three bugs:
You use i++ too soon. You place the first bit at binary_res[1] when it should be placed at binary_res[0].
You don't add a terminating NUL to binary_res.
You don't modify the binary_res at all when the n parameter is zero.
I check this statement '(n%2)' with loop statement and I fill the array, then I use procedure mirror to reverse the string like this:
#include <stdio.h>
#include <string.h>
void mirror(char c[],int l);
void decimal_to_binary(unsigned int n,char binary_res[]);
int main()
{
int n = 40; char res[10];
printf("%d\n",n);
decimal_to_binary(n,res);
printf("The binary form of number %d is %s\n",n,res);
return 0;
}
void mirror(char c[],int l)
{
char s;
for (int i = 0; i < l/2;i++)
{
s = c[i];
c[i] = c[l-i-1];
c[l-i-1] = s;
}
}
void decimal_to_binary(unsigned int n,char binary_res[])
{
int i = 0;
while (n != 0)
{
switch(n%2)
{
case 1:
{
binary_res[i]='1';
i++;
}break;
case 0:
{
binary_res[i]='0';
i++;
}break;
}
n = n/2;
}
binary_res[i]='\0';
mirror(binary_res,i);
}

Create function which sorts 2 given sorted strings

Given two sorted strings, I need to merge these strings to one string, and make it sorted.
sort by the ASCII value. for example:
acdty, berz => abcdertyz
My code:
#include <stdio.h>
#include <stdlib.h>
char* PairSortedArrays(char a[], char b[]) {
char* c = (char*)malloc((sizeof(a) + sizeof(b)) * sizeof(char));
int i, aPos = 0, bPos = 0;
for (i = 0; i < sizeof(*c); i++) {
if ((int)(a[aPos]) <= (int)(b[bPos])) {
c[i] = a[aPos];
aPos++;
}
else {
c[i] = b[bPos];
bPos++;
}
}
return c;
}
int main()
{
printf("%s", PairSortedArrays("acdty", "berz"));
return 0;
}
The first problem is with sizeof(a). if I code: printf("%d", sizeof(a)); it prints 8, while I expect it to print 5.
The expression i < sizeof(*c) controling the for loop is the main culprit. The corrected version of your program could be: (I edited the code a bit)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* PairSortedArrays(const char a[], const char b[])
{
size_t i;
const size_t total_len = strlen(a)+strlen(b);
char *c = malloc(total_len + 1);
size_t aPos = 0, bPos = 0;
for (i = 0; i < total_len; i++) {
if (a[aPos] == '\0') {
strcpy(c + i, b + bPos);
break;
}
if (b[bPos] == '\0') {
strcpy(c + i, a + aPos);
break;
}
c[i] = a[aPos] < b[bPos] ? a[aPos++] : b[bPos++];
}
return c;
}
int main()
{
printf("%s\n", PairSortedArrays("acdty", "berz"));
printf("%s\n", PairSortedArrays("az", "ks"));
return 0;
}
The return value of malloc must be checked against NULL in a real program. Also there is a memory leak (easy to fix).
When working with strings in C, you will want to be using strlen() to see how long they are, not sizeof (which merely tells you what the size of a pointer is).
Also note that sizeof(char) is 1 by definition, so there's no need to say "* sizeof(char)" in your malloc
sizeof(a) will return the size of a pointer in this case which will be 8 bytes if you compile for 64 architecture.
you have to either pass the size of each string or loop the string characters until you reach the '\0' if the string is null-terminated.
You should consider using qsort:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare_chars(const void *p1, const void *p2)
{
return *(const char *)p1 - *(const char *)p2;
}
char *PairSortedArrays(char *a, char *b)
{
char *c = malloc(strlen(a)+strlen(b)+1);
strcpy(c, a);
strcat(c, b);
qsort(c, strlen(c), sizeof(char), compare_chars);
return c;
}
int main()
{
printf("%s", PairSortedArrays("acdty", "berz"));
return 0;
}

Sort array alphabetically, upper letter always first

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;
}

What's wrong with my Heap's Algorithm code?

My homework requires me to write a program that takes a string from the terminal (argc and argv) and print every possible permutation. I have tried to use Heap's Algorithm, but it doesn't seem to be working out. Below is my function.
char **getPermutation(char * in)
{
//n is the size of the input string.
int n = strlen(in);
int count[n];
int counter= 0;
char copy[n];
char **permutations = malloc(sizeof(char*)*(factorial(n)));
permutations[0] = in;
strcpy(in, copy);
counter++;
for( int i = 1; i < n;)
{
if (count[i] < i){
if (i%2==0){
swap(&in[0],&in[i]);
}
else
{
swap(&in[count[i]],&in[i]);
}
permutations[counter] = in;
strcpy(in, copy);
counter++;
count[i]++;
i = 1;
}
else
{
count[i] = 0;
i++;
}
}
return permutations;
}
The function must return the pointer to the character pointer as specified by the instructions. That's also why there are so many variables (although, I'm not really sure what to do with the copy of the string. I'm fairly sure I need it). Testing shows that the program will loop, often too much and eventually hit a seg fault. It doesn't seem like the swapped strings make it into the returned array on top of that.
Below is a rework of your code with cleaned up memory allocation and it addresses some problems mentioned in the above comments. Additionally, you have a bug in your algorithm, this statement strcpy(in, copy); keeps you from getting all the permutations (causes repeats instead.) This code works but isn't finished, it can use more error checking and other finishing touches:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned int factorial(unsigned int n)
{
/* ... */
}
void swap(char *a, char *b)
{
/* ... */
}
char **getPermutations(const char *input)
{
char *string = strdup(input);
size_t length = strlen(string);
char **permutations = calloc(factorial(length), sizeof(char *));
int *counts = calloc(length, sizeof(int)); // point to array of ints all initialized to 0
int counter = 0;
permutations[counter++] = strdup(string);
for (size_t i = 1; i < length;)
{
if (counts[i] < i)
{
if (i % 2 == 0)
{
swap(&string[0], &string[i]);
}
else
{
swap(&string[counts[i]], &string[i]);
}
permutations[counter++] = strdup(string);
counts[i]++;
i = 1;
}
else
{
counts[i++] = 0;
}
}
free(counts);
free(string);
return permutations;
}
int main(int argc, char *argv[])
{
char *string = argv[1];
char **permutations = getPermutations(string);
unsigned int total = factorial(strlen(string));
for (unsigned int i = 0; i < total; i++)
{
printf("%s\n", permutations[i]);
}
free(permutations);
return 0;
}
OUTPUT
> ./a.out abc
abc
bac
cab
acb
bca
cba
>

memcmp C implementation - any logical errors with this one

memcmp C implementation - any logical errors with this one?
I was going looking for an implementation of memcmp(), I found this code snippet, but it is clearly marked that there is 1 logical error with the code snippet. Could you help me find the logical error.
Basically, I tested this code against the string.h library implementation of memcmp() with different inputs, but the expected output is always the same as the library version of the function.
Here is the code snippet:
#include <stdio.h>
#include <string.h>
int memcmp_test(const char *cs, const char *ct, size_t n)
{
size_t i;
for (i = 0; i < n; i++, cs++, ct++)
{
if (*cs < *ct)
{
return -1;
}
else if (*cs > *ct)
{
return 1;
}
else
{
return 0;
}
}
}
int main()
{
int ret_val = 20; //initialize with non-zero value
char *string1 = "china";
char *string2 = "korea";
ret_val = memcmp_test(string1,string2,5);
printf ("ret_val is = %d",ret_val);
getchar();
return 0;
}
I ran the program with the two example strings and the program would return just after the comparison of the first characters of the two strings. ret_val is -1 in the above case.
The definition of memcmp() which the above code snippet should conform to is:
The definition of the ā€˜Cā€™ Library function memcmp is
int memcmp(const char *cs, const char *ct, size_t n)
Compare the first n characters of cs with the first n characters of ct.
Return < 0 if cs < ct.
Return > 0 if cs > ct.
Return 0 if cs == ct.
There is definitely on LOGICAL error, could you help me find it.
As it's written now, this code will only test the first byte of the inputs. The else return 0 needs to be moved out of the loop, leaving return 0 at the end:
for (i = 0; i < n; i++, cs++, ct++)
{
if (*cs < *ct)
{
return -1;
}
else if (*cs > *ct)
{
return 1;
}
}
return 0;
}
I guess since char signedness is implementation defined, you could make your comparison unsigned:
int memcmp_test(const char *cs_in, const char *ct_in, size_t n)
{
size_t i;
const unsigned char * cs = (const unsigned char*) cs_in;
const unsigned char * ct = (const unsigned char*) ct_in;
for (i = 0; i < n; i++, cs++, ct++)
{
if (*cs < *ct)
{
return -1;
}
else if (*cs > *ct)
{
return 1;
}
}
return 0;
}
Look at your for loop. It's only examining one character.
Strictly speaking the signature is wrong. The correct one is:
int memcmp(const void *s1, const void *s2, size_t n);
Your code compares c and k and on finding that c is less than k dutifully returns a -1. However, if these two were equal you would get an incorrect result since you are returning early.
If you read the documentation you'd find:
The sign of a non-zero return value shall be determined by the sign of the difference between the values of the first pair of bytes (both interpreted as type unsigned char) that differ in the objects being compared
Which basically means you are doing the right thing by returning something that preserves the sign of ('c' - 'k').
A simpler implementation can be found here.
The return 0; occurs after only comparing the first character. It should be placed outside of the loop.
This snippet works perfect for me!!
#include <stdio.h>
#include <string.h>
int memcmp_test(const char *cs, const char *ct, size_t n)
{
size_t i;
for (i = 0; i < n; i++, cs++, ct++)
{
if (*cs < *ct)
{
return -1;
}
else if (*cs > *ct)
{
return 1;
}
}
return 0;
}
int main()
{
int ret_val = 20; //initialize with non-zero value
const char *string1 = "DWgaOtP12df0";
const char *string2 = "DWGAOTP12DF0";
ret_val = memcmp_test(string1,string2,5);
printf ("ret_val is = %d",ret_val);
getchar();
return 0;
}

Resources