Merge two integer arrays in C - c

I am trying to program a function to merge two signed integer arrays. The idea is to get the contents of src, reallocate memory in dest to insert the contents of src after its own contents. If dest is NULL, the function must allocate memory space to store src + 1. If there is an error the function must return NULL. The function must also free the memory space allocated to src after the merge. Integer arrays are terminated by an int called "End Of Buffer" (-1 in my example below).
the problem seems to be related to the realloc function, can you help me to fix it?
Here is the full code that produces the error :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
ssize_t my_put_int(int nbr, int fd)
{
char c = 0;
char negative = '-';
ssize_t len = 0;
if (nbr < 0) {
len += write(fd, &negative, 1);
len += my_put_int(-nbr, fd);
} else if (nbr < 10) {
c = nbr + 48;
len += write(fd, &c, 1);
} else {
len += my_put_int(nbr / 10, fd);
c = nbr % 10 + 48;
len += write(fd, &c, 1);
}
return len;
}
ssize_t my_put_int_arr(int *arr, int eob, int fd)
{
size_t count = 0;
int *ptr = NULL;
if (!arr || fd < 0)
return -1;
ptr = arr;
while (*ptr != eob) {
count += my_put_int(*ptr, fd);
ptr++;
}
return count;
}
size_t my_int_arr_len(int *arr, int eob)
{
size_t count = 0;
if (!arr)
return -1;
while (*arr != eob) {
count++;
arr++;
}
return count;
}
int *my_int_array_concat(int *dest, int *src, int eob)
{
size_t src_size = 0, dest_size = 0;
if (!src) return NULL;
src_size = my_int_arr_len(src, eob);
if (dest == NULL) {
dest = malloc(sizeof(int) * (src_size + 1));
if (dest == NULL) return NULL;
for (size_t i = 0; i < src_size; i++) dest[i] = src[i];
dest[src_size] = eob;
free(src);
return dest;
}
dest_size = my_int_arr_len(dest, eob);
printf("Dest size %ld, src size %ld\n", dest_size, src_size); // Debug
dest = realloc(dest, sizeof(int) * (dest_size + src_size + 1));
printf("New dest size %ld\n", my_int_arr_len(dest, -1)); // Debug
if (!dest) return NULL;
for (size_t i = 0; i < src_size; i++) dest[i] = src[i];
dest[src_size] = eob;
free(src);
return dest;
}
int main() //test main
{
int *src = malloc(sizeof(int) * 2);
src[0] = 3;
src[1] = -1;
int *dest = malloc(sizeof(int) * 3);
dest[0] = 2;
dest[1] = 1;
dest[2] = -1;
dest = my_int_array_concat(dest, src, -1);
my_put_int_arr(dest, -1, 1);
return 0;
}
I get this result :
Dest size 2, src size 1
New dest size 2
3

Use following concat function -
int *my_int_array_concat(int *dest, int *src, int eob)
{
size_t src_size = 0, dest_size = 0;
if (!src) return NULL;
src_size = my_int_arr_len(src, eob);
if (dest == NULL) {
dest = malloc(sizeof(int) * (src_size + 1));
if (dest == NULL) return NULL;
for (size_t i = 0; i < src_size; i++) dest[i] = src[i];
dest[src_size] = eob;
return dest;
}
dest_size = my_int_arr_len(dest, eob);
dest = realloc(dest, sizeof(int) * (dest_size + src_size + 1));
if (!dest) return NULL;
for (size_t i = 0; i < src_size; i++) dest[dest_size+i] = src[i];
dest[dest_size+src_size] = eob;
free(src);
return dest;
}
It should work.

Here is another (not tested) variant of the function :
int* my_int_array_concat( int* dst, int* src, int eob )
{
int* result;
int dst_size;
int src_size;
int elements_count;
src_size = my_int_arr_len( src, eob );
if( src_size == -1 )
src_size = 0;
dst_size = my_int_arr_len( dst, eob );
if( dst_size == -1 )
dst_size = 0;
elements_count = src_size + dst_size;
result = realloc( dst, sizeof(int) * (elements_count + 1) );
if( result == NULL )
return NULL;
if( src_size )
memcpy( result + dst_size, src, sizeof(int) * src_size );
result[elements_count] = eob;
if( src )
free( src );
return result;
}

Related

Converting a string into 2d array in c

hi i have been trying to convert a string map to an 2d array but the more i change the more i get confused. now it does not compile and complains its = NUL (edited i added malloc and seems that and gives segmentation fault).
#include <unistd.h>
#include <stdlib.h>
char **stoa(char *str)
{
int i;
int j;
int k;
char **map;
//int len = ft_strlen_line(str);
//int row = ft_strlen(str);
i = 0;
j = 0;
k = 0;
//arow = row/len;
//map = malloc(j * k sizeof(char*));
map = malloc(j * sizeof(k));
while(str[i])
{
if (str[i] == '\n')
{
k = 0;
j++;
}
map[j][k] = str[i];
k++;
i++;
}
free(map);
return (map);
if (!(map = malloc(j * k * sizeof(char))))
return NULL;
}
int main(void)
{
char row12[] = "ABABABABAB\nABABABABAB\nABABABABAB\n\0";
char **map;
map = stoa(row12);
return (0);
}
Not tested.
char **stoa(char *str)
size_t nlines = 0;
size_t pos = 0;
char **array = NULL;
char **tmp;
while(*str)
{
while(*str && str[pos++] != '\n');
nlines++;
tmp = realloc(array, (nlines + 1) * sizeof(*array));
if(tmp) array = tmp;
else break;
array[nlines] = NULL;
if(array[nlines - 1] = malloc(pos + 2));
if(array[nlines - 1])
{
memcpy(array[nlines - 1], str, pos);
array[nlines - 1][pos] = 0;
str = str + pos;
if(str == '\n') str++;
pos = 0;
}
else break;
}
return array;
}

I can not use free() on char pointer returned from a function

I cannot clear the str variable that is allocated in the ft_itoa_base() function.
Error pointer being freed was not allocated.
void work_ptr_accuracy(t_args *args, char **return_str, \
va_list *arg)
{
int size_accuracy;
char *str_tmp;
char *str;
unsigned long long int n;
str_tmp = NULL;
str = NULL;
if (args->accuracy != -1)
{
size_accuracy = args->accuracy;
n = va_arg(*arg, unsigned long long int);
str = ft_itoa_base(n, 16, LOWERCASE);
*return_str = ft_substr(str, 0, size_accuracy);
free(str);
str_tmp = ft_strjoin("0x", *return_str);
free(*return_str);
*return_str = str_tmp;
}
}
this is ft_itoa_base()
char *ft_itoa_base(unsigned long long int value, \
unsigned long long int base, int regist)
{
int len;
unsigned long long int digit;
char *return_str;
char *base_tmp;
base_tmp = get_register(regist);
if (value == 0)
return ("0");
len = 0;
digit = value;
ft_baselen(digit, base, &len);
if (!(return_str = (char *)malloc(sizeof(char) * (len + 1))))
return (NULL);
return_str[len] = '\0';
while (digit)
{
return_str[--len] = base_tmp[digit % base];
digit /= base;
}
if (value < 0 && base == 10)
return_str[0] = '-';
return (return_str);
}
this is my ft_substr()
/*
** Function: char *ft_substr
**
** Description: Allocates (with malloc(3)) and returns a substring
** from the string ’s’.
** The substring begins at index ’start’ and is of
** maximum size ’len’.
*/
char *ft_substr(const char *s, unsigned int start, size_t len)
{
unsigned int i;
unsigned int j;
char *str;
i = 0;
j = 0;
if (!s)
return (NULL);
if (start >= ft_strlen(s))
{
if (!(str = (char *)malloc(1)))
return (NULL);
str[0] = '\0';
return (str);
}
while (s[i] != s[start])
i++;
if (!(str = (char *)malloc((len * sizeof(char)) + 1)))
return (NULL);
while (j < len && s[i])
str[j++] = s[i++];
str[j] = '\0';
return (str);
}
Bad design of ft_itoa_base. return ("0") returns a pointer to statically allocated array consisting of two chars ( '0' and '\0'). That one cannot be free-ed.
Compare to this implementation by lwang <marvin#42.fr>
#include <stdlib.h>
#include <stdio.h>
int ft_abs(int nb)
{
if (nb < 0)
nb = -nb;
return (nb);
}
char *ft_itoa_base(int value, int base)
{
char *str;
int size;
char *tab;
int flag;
int tmp;
flag = 0;
size = 0;
tab = "0123456789ABCDEF";
if (base < 2 || base > 16)
return (0);
if (value < 0 && base == 10)
flag = 1;
tmp = value;
while (tmp /= base)
size++;
size = size + flag + 1;
str = (char *)malloc(sizeof(char) * size + 1);
str[size] = '\0';
if (flag == 1)
str[0] = '-';
while (size > flag)
{
str[size - 1] = tab[ft_abs(value % base)];
size--;
value /=base;
}
return (str);
}

I get a breakpoint after the realloc. Why? And how can I make it right?

The point of the program is to replace every succession of 2 or more vocals with my name.
How can I make that reallocation successful?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
char vocale[] = "AEIOUaeiou",
sir[] = "Aana are muaulte meiree.";
char *src = (char*)malloc(strlen(sir) + 1);
src = sir;
char name[] = "Marian";
int count = 0,
i = 0;
while (i < strlen(src)) {
if (strchr(vocale, src[i])) {
count++;
i++;
}
else {
if (count >= 2) {
src = (char*)realloc(src, strlen(src) + strlen(name) + 1);
insereaza(src, count, name, i);
i = i + strlen(name);
count = 0;
}
else {
count = 0;
i++;
}
}
}
puts(src);
_getch();
}
here is a proposal with some changes, it is difficult because I don't know what insereaza does
void main() {
const char * vocale = "AEIOUaeiou";
char * src = strdup("Aana are muaulte meiree."); /* must be in the heap for realloc */
const char * name = "Marian";
int srcLen = strlen(src);
int nameLen = strlen(name);
int count = 0, i = 0;
while (i < srcLen) {
if (strchr(vocale, src[i])) {
count++;
i++;
}
else {
if (count >= 2) {
src = (char*) realloc(src, srcLen + nameLen + 1); /* perhaps too large */
insereaza(src, count, name, i);
srcLen += nameLen; /* or srcLen += nameLen - count + 1 ? */
i += nameLen; /* or i += nameLen - count + 1 ? */
}
else {
i++;
}
count = 0;
}
}
puts(src);
_getch();
}

file size exceeds buffer size

I want to compare 2 files for identical lines: mytab2411.txt(15,017,210 bytes in size) and shadow.txt (569 bytes in size) but when I compiled this code and ran the program, I get a segmentation fault. I know that it's because the "mytab2411.txt" file exceeds the size of "char buf" but how do I go about solving this problem without overflowing the buffer?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
int cmp(const void * s1, const void * s2)
{
return strcasecmp(*(char **)s1, *(char **)s2);
}
int cmp_half(const char * s1, const char * s2)
{
int i;
for (i = 0; i < 3; i++)
{
int res = strncasecmp((char *)s1+i*3, (char *)s2+i*3, 2);
if (res != 0) return res;
}
return 0;
}
char * line[1024];
int n = 0;
int search(const char * s)
{
int first, last, middle;
first = 0;
last = n - 1;
middle = (first+last)/2;
while( first <= last )
{
int res = cmp_half(s, line[middle]);
if (res == 0) return middle;
if (res > 0)
first = middle + 1;
else
last = middle - 1;
middle = (first + last)/2;
}
return -1;
}
int main()
{
FILE * f1, * f2;
char * s;
char buf[1024*1024], text[1024];
f1 = fopen("shadow.txt", "rt");
f2 = fopen("mytab2411.txt", "rt");
s = buf;
while (fgets(s, 1024, f2) != NULL)
{
line[n] = s;
s = s+strlen(s)+1;
n++;
}
qsort(line, n, sizeof(char *), cmp);
while (fgets(text, 1024, f1) != NULL)
{
text[strlen(text)-1] = 0;
int idx = search(text);
if (idx >= 0)
{
printf("%s matched %s\n", text, line[idx]);
}
else
{
printf("%s not matched\n", text);
}
}
return 0;
}
Your method assumes that each line in the file is 1024 bytes long. In practice the lines can be up to 1024 bytes, but most lines are much shorter. Use strdup or malloc to allocate memory for each line based on line's length.
Store the lines in dynamically allocated arrays. This is about 15 MB of data and it should not be a problem unless there are resource limitations.
int main(void)
{
char buf[1024];
char **arr1 = NULL;
char **arr2 = NULL;
int size1 = 0;
int size2 = 0;
FILE * f1, *f2;
f1 = fopen("shadow.txt", "r");
f2 = fopen("mytab2411.txt", "r");
while(fgets(buf, 1024, f1))
{
size1++;
arr1 = realloc(arr1, sizeof(char*) * size1);
arr1[size1 - 1] = strdup(buf);
}
while(fgets(buf, 1024, f2))
{
size2++;
arr2 = realloc(arr2, sizeof(char*) * size2);
arr2[size2 - 1] = strdup(buf);
}
for(int i = 0; i < size1; i++)
for(int j = 0; j < size2; j++)
{
if(strcmp(arr1[i], arr2[j]) == 0)
printf("match %s\n", arr1[i]);
}
return 0;
}

Three level indirection char pointer in C causes a segment fault

I got a segment fault error at the line with the comments that contains lots of equals signs below.
The function below str_spit, I wrote it because I want to split a string using a specific char, like a comma etc.
Please help.
int str_split(char *a_str, const char delim, char *** result)
{
int word_length = 0;
int cur_cursor = 0;
int last_cursor = -1;
int e_count = 0;
*result = (char **)malloc(6 * sizeof(char *));
char *char_element_pos = a_str;
while (*char_element_pos != '\0') {
if (*char_element_pos == delim) {
char *temp_word = malloc((word_length + 1) * sizeof(char));
int i = 0;
for (i = 0; i < word_length; i++) {
temp_word[i] = a_str[last_cursor + 1 + i];
}
temp_word[word_length] = '\0';
//
*result[e_count] = temp_word;//==============this line goes wrong :(
e_count++;
last_cursor = cur_cursor;
word_length = 0;
}
else {
word_length++;
}
cur_cursor++;
char_element_pos++;
}
char *temp_word = (char *) malloc((word_length + 1) * sizeof(char));
int i = 0;
for (i = 0; i < word_length; i++) {
temp_word[i] = a_str[last_cursor + 1 + i];
}
temp_word[word_length] = '\0';
*result[e_count] = temp_word;
return e_count + 1;
}
//this is my caller function====================
int teststr_split() {
char delim = ',';
char *testStr;
testStr = (char *) "abc,cde,fgh,klj,asdfasd,3234,adfk,ad9";
char **result;
int length = str_split(testStr, delim, &result);
if (length < 0) {
printf("allocate memroy failed ,error code is:%d", length);
exit(-1);
}
free(result);
return 0;
}
I think you mean
( *result )[e_count] = temp_word;//
instead of
*result[e_count] = temp_word;//
These two expressions are equivalent only when e_count is equal to 0.:)
[] has a higher precedence than *, so probably parentheses will solve THIS problem:
(*result)[e_count] = temp_word;
I didn't check for more problems in the code. Hint: strtok() might do your job just fine.

Resources