Create function which sorts 2 given sorted strings - c

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

Related

C insertion sort with function as parameter

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.

Returning a whole array in C

Hi I am pretty new to C and was wondering how to return an entire array. For example I have this function here.
char* foo(int x)
{
char *num = (char*)malloc(x*sizeof(int));
num[0] = '1';
num[1] = '2';
num[2] = '3';
num[3] = '4';
return num;
}
I realized that when I return num it only returns the first index of num. But is there any way to return the whole array, 1234? Any help will be greatly appreciated!
Since the foo() function returns a pointer, you can see that all values are printed when you use the %s format specifier. The display() function prints the data in the memory area pointed to by the pointer as characters.
#include <stdio.h>
#include <stdlib.h>
char* foo(int x)
{
char* num = (char*) malloc((x + 1) * sizeof(char));
for(size_t i = 0 ; i < x ; ++i)
num[i] = i + 1 + '0';
num[x] = '\0';
return num;
}
void display(char *array, size_t size)
{
for(size_t i = 0 ; i < size && array[i] != '\0' ; ++i)
printf("array[%ld]: %c\n", i, array[i]);
}
int main()
{
const size_t size = 4;
char *result = foo(size);
printf("%s\n", result);
display(result, size);
return 0;
}
Output:
1234
array[0]: 1
array[1]: 2
array[2]: 3
array[3]: 4
See if you are new to C, then learn it first do some googling and research. If you don't find anything then read some theory of a similar topic for examples (How to return an array in C?). After that some error is happening in your code then you can ask it on stackoverflow.
By the way your should be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *foo(int x); // fix prototype errors
char *foo(int x)
{
char *num = (char *)calloc(x + 1, sizeof(char)); // we added +1 to append the null terminating character in `num`
for (size_t i = 0; i < x; i++)
num[i] = (char)(i + 48);
return num;
}
/* #returns no. of character written on stdout */
int print_foo(const char *num); // fix prototype errors
int print_foo(const char *num)
{
if (num)
{
size_t z = 0;
for (size_t i = 0; i < num[i] != '\0'; i++)
z += fprintf(stdout, "num[%lu] = %c\n", i, num[i]);
return z;
}
return -1;
}
int main(void)
{
char *num = foo(10);
print_foo((const char *)num);
free(num); // free any heap allocated resources before exiting the application
return 0;
}

anagram in c with runtime error

Why do I get a runtime error?
Output Format
Print a single integer denoting the number of characters you must delete to make the two strings anagrams of each other.
We consider two strings to be anagrams of each other if the first string's letters can be rearranged to form the second string. In other words, both strings must contain the same exact letters in the same exact frequency
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int cmpfunc (const void * a, const void * b){
return ( *(int*)a - *(int*)b );
}
char* concat(const char *s1, const char *s2){
char *result = malloc(strlen(s1)+strlen(s2)+1);//+1 for the zero-terminator
strcpy(result, s1);
strcat(result, s2);
return result;
}
int main(){
char* a = (char *)malloc(512000 * sizeof(char));
scanf("%s",a);
char* b = (char *)malloc(512000 * sizeof(char));
scanf("%s",b);
int l1 = strlen(a);
int l2 = strlen(b);
if(l1 != l2){
printf("String lengths do not match, exiting\n");
exit(1);
}
char * s;
for (int i = 0; i < l1; i++){
s = concat(a, b);
}
qsort(s, l1, sizeof(int), cmpfunc);
int range[26]={0};
for(int i=0;i<l1;i++){
int t = s[i] - 'a';
range[t]++;
}
int count = 0;
for(int i=0;i<=l1;i++){
count++;
}
printf("%d\n", count);
free(s);
free(a);
free(b);
return 0;
}

What is wrong with my c code?

I am getting segmentation fault for the code below. To compile I typed gcc -std=c99 -g alphacode.c. This is a problem I am solving from here, and I am not sure what the problem is.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int catchar(char a, char b) {
char a1[2];
a1[1] = a;
a1[0] = b;
return atoi(a1);
}
int processNumber(char *num) {
int size = strlen(num);
int p[size];
if (num[size-1] != 0)
p[size-1] = 1;
else
p[size-1] = 0;
int i;
for (i = size-2; i>=0; i--)
{
if (catchar(num[i], num[i-1]) > 26 ||
catchar(num[i] , num[i-1]) <1 || num[i] == 0)
p[i] = p[i-1];
else
p[i] = p[i-1] + p[i-2];
}
return p[0];
}
int main() {
int bytes_read;
int nbytes = 5000;
char *number;
bytes_read = getline (&number, &nbytes, stdin);
while (bytes_read != -1) {
int out = processNumber(number);
printf("%d\n", out);
bytes_read = getline (&number, &nbytes, stdin);
}
return 0;
}
int catchar(char a, char b) {
char a1[2];
a1[1] = a;
a1[0] = b;
return atoi(a1);
}
atoi() expects a string, and a string must have a '\0' terminator, without it - atoi() will just keep looking until it find '\0', and you might get garbage or segfault - if you are out of your allocated memory.
You should declare your array of size 3, and put '\0' at index 2.
String needs to be null(0) terminated, thus you need array of 3 ( [a][b][\0]).
int catchar(char a, char b)
{
char concat[3] = { a,b,NULL};
return atoi(concat);
}

Is the strrev() function not available in Linux?

I tried to write code using strrev(). I included <string.h> but still I'm getting an "undefined reference to strrev" error.
I found that strrev() doesn't have man page at all. Why?
Doesn't Linux support strrev()?
Correct. Use one of the alternative implementations available:
#include <string.h>
char *strrev(char *str)
{
char *p1, *p2;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
#include <string.h>
char *strrev(char *str)
{
if (!str || ! *str)
return str;
int i = strlen(str) - 1, j = 0;
char ch;
while (i > j)
{
ch = str[i];
str[i] = str[j];
str[j] = ch;
i--;
j++;
}
return str;
}
To accurately answer your question,
Is strrev() not available on Linux?
The functions strrev() available in the string.h library. Functions strrev() including some other string functions such as like strupr(), strlwr(), strrev(), which are only available in ANSI C (Turbo C/C++) and are not available in the standard C-GCC compiler.
It’s not about the system. It is about the C compiler you are using.
References:
https://discuss.codechef.com/t/is-strrev-function-not-available-in-standard-gcc-compiler/2449
https://www.csestack.org/undefined-reference-to-strrev/
Unfortunately, strrev seems to be absent from glibc's string.h.
Obviously, I'm late to the here's-some-code party, but I like this implementation.
#define MAX_CHARS 10000
// safe_usub -- perform safe unsigned subtraction
size_t safe_usub (size_t x, size_t y) {
return x > y ? x - y : y - x ;
}
char* str_reverse (const char* const str) {
if (!str) { return NULL; }
size_t len = strnlen(str, MAX_CHARS);
char* new = malloc( sizeof(char) * len );
size_t i;
for (i = 0; i < len; i++) {
new[i] = str[ safe_usub(i + 1, len) ];
}
new[i] = 0;
return new;
}
How about this:
#include <string.h>
char *strrev(char *s)
{
if (s && *s) {
char *b = s, *e = s + strlen(s) - 1;
while (b < e) {
char t = *b;
*b++ = *e;
*e-- = t;
}
}
return s;
}
There is no string library function to reverse a string.
strrev() Is not present in GCC compiler in Linux.
Make your own reverse function:
reverse.c:
/*
* C program to reverse a string using recursion
*/
#include <stdio.h>
#include <string.h>
void reverse(char [], int, int);
int main()
{
char str1[20];
int size;
printf("Enter a string to reverse: ");
scanf("%s", str1);
size = strlen(str1);
reverse(str1, 0, size - 1);
printf("The string after reversing is: %s\n", str1);
return 0;
}
void reverse(char str1[], int index, int size)
{
char temp;
temp = str1[index];
str1[index] = str1[size - index];
str1[size - index] = temp;
if (index == size / 2)
{
return;
}
reverse(str1, index + 1, size);
}

Resources