How to modify a 2d array passed to a function - c

I know we're able to change a string thanks to a function like this
void c(char *s)
{
int i = 0;
while (s[i])
s[i++] = 's';
}
int main()
{
char str[] = "hello";
c(str);
printf("%s\n", str);
return (0);
}
In this case it will print "sssss".
But how can I modify a 2d array the same way I did for a string ?
I mean without returning the array.
void c(char **s)
{
int i = 0;
int j = 0;
while (s[i])
{
j = 0;
while (s[i][j])
{
s[i][j++] = 's';
}
i++;
}
}
int main()
{
char tab[2][2];
tab[0][0] = 'a';
tab[0][1] = 'b';
tab[1][0] = 'c';
tab[1][1] = 'd';
c(tab);
printf("%c%c\n%c%c", tab[0][0], tab[0][1], tab[1][0], tab[1][1]);
return (0);
}
Here's an idea of how we could do it.
I hope I have been clear enough?

The definition should contain the length. Following will be a good read:
http://www.firmcodes.com/pass-2d-array-parameter-c-2/
void c(char (*s)[length])
#include <stdio.h>
void c(int len, char (*s)[len])
{
int i = 0;
int j = 0;
while (i < len)
{
j = 0;
while (s[i][j])
{
s[i][j++] = 's';
}
i++;
}
}
int main()
{
char tab[2][2];
tab[0][0] = 'a';
tab[0][1] = 'b';
tab[1][0] = 'c';
tab[1][1] = 'd';
c(2, tab);
printf("%c%c\n%c%c", tab[0][0], tab[0][1], tab[1][0], tab[1][1]);
return (0);
}

Sure, its the same. With any dimension count.
void c(char **s, int stringCount)
{
int i = 0, j = 0;
for (j = 0; j < stringCount; ++j)
{
i = 0;
while (s[j][i])
{
s[j][i++] = 's';
}
}
}
int main()
{
char *tab[2] = { "str1", "str2" };
c(tab, 2);
printf("%c%c\n%c%c", tab[0][0], tab[0][1], tab[1][0], tab[1][1]);
printf("%s\n%s", tab[0], tab[1]);
getchar();
return (0);
}

Related

How to check if a string is subset of another string in C

I want to create a function that checks if an array is derived from elements of another array in C. Here is my code. I don't know why it isn't working.
int allDelimiter(char str[81], char delimiters[])
{
int k = 0;
char* pch = strstr(str, delimiters);
if (pch)
{
k++;
}
return k;
}
int main()
{
char string[81] = { ",?',,," };
char delim[] = ", ? ! ''";
int j = 0;
j = allDelimiter(string, delim);
if (j > 0)
{
puts("ALL DELIMITERS");
}
else
{
puts("NOT ALL DELIMITERS");
}
return 0;
}
I want the output to be ALL DELIMITERS i.e all elements of str[] are elements of delim[].
If I understand the question
//returns zero if yes
int containsAll(const char *str, const char *charlist)
{
int result = 0;
while(*str)
{
if(!strchr(charlist, *str++))
{
result = -1;
break;
}
}
return result;
}
int main()
{
char string[81] = { ",?',,," };
char delim[] = ", ? ! ''";
if (!containsAll(string, delim))
{
puts("ALL DELIMITERS");
}
else
{
puts("NOT ALL DELIMITERS");
}
return 0;
}

Runtime error on Leetcode

When I submit my code to Leetcode, it reported runtime error as:
Line 43: member access within null pointer of type 'struct bucket_item'.
I tested that case in my local, it works fine. I thought it maybe causeed by the platform and compiler are different. I then tried to test it on Leetcode Playground. It also worked very well. The Leetcode problem is: https://leetcode.com/problems/substring-with-concatenation-of-all-words/description/
Very appreciated if anyone could let me know what's wrong with my code.
typedef struct bucket_item {
char *str;
int count;
int ori_count;
} bucket_item;
typedef struct bucket {
int hashIndex;
int itemsCount;
bucket_item *items;
} bucket;
bucket *hash_init(const int bucket_count)
{
bucket *buckets = malloc(sizeof(bucket) * bucket_count);
for (int i = 0; i < bucket_count; ++i)
{
buckets[i].items = NULL;
buckets[i].itemsCount = 0;
}
return buckets;
}
int get_hash(char *str, const int bucket_count) {
const int str_len = strlen(str);
int base = 0;
int i = 0;
while (str[i] != '\0')
{
base += str[i];
i++;
}
return ((base >> 3) * 2654435761) % bucket_count;
}
bucket_item *hash_lookup(bucket *buckets, char *str, const int bucket_count)
{
const int hash_index = get_hash(str, bucket_count);
bucket *bucket = buckets + hash_index;
for (int i = 0; i < bucket->itemsCount; ++i)
{
if (strcmp(str, bucket->items[i].str) == 0) return bucket->items + i;
}
return NULL;
}
void hash_add(bucket *buckets, char *str, const int bucket_count)
{
bucket_item *item = hash_lookup(buckets, str, bucket_count);
if (item)
{
item->count++;
item->ori_count = item->count;
}
else {
const int hash_index = get_hash(str, bucket_count);
bucket *bucket = buckets + hash_index;
bucket->itemsCount++;
bucket->items = (bucket_item *)realloc(bucket->items, sizeof(bucket_item) * bucket->itemsCount);
bucket->items[bucket->itemsCount - 1].str = str;
bucket->items[bucket->itemsCount - 1].count = 1;
bucket->items[bucket->itemsCount - 1].ori_count = 1;
}
}
void hash_free(bucket *buckets, const int bucket_count)
{
for (int i = 0; i < bucket_count; ++i)
{
free(buckets[i].items);
buckets[i].items = NULL;
}
free(buckets);
buckets = NULL;
}
bool is_match(char* str, bucket *hashmap, int bucket_count, char **words, int word_len, int word_size)
{
bool found = true;
char *subStr = malloc(sizeof(char) * (word_len + 1));
subStr[word_len] = '\0';
for (int i = 0; i < word_size; ++i)
{
memcpy(subStr, str + i * word_len, word_len);
bucket_item *item = hash_lookup(hashmap, subStr, bucket_count);
if (item)
{
item->count--;
}
else
{
found = false;
}
}
free(subStr);
subStr = NULL;
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
if (item->count != 0) {
found = false;
}
}
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
item->count = item->ori_count;
}
return found;
}
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
int* findSubstring(char* s, char** words, int wordsSize, int* returnSize) {
if (wordsSize == 0) return NULL;
const int word_len = strlen(words[0]);
// prepare hashmap
bucket *hashmap = hash_init(wordsSize);
for (int i = 0; i < wordsSize; ++i)
{
hash_add(hashmap, words[i], wordsSize);
}
// loop long string.
int *ret = malloc(sizeof(int) * 1000);
*returnSize = 0;
const int s_len = strlen(s);
const int sub_strlen = word_len * wordsSize;
for (int i = 0; i < s_len; ++i)
{
const bool found = is_match(s + i, hashmap, wordsSize, words, word_len, wordsSize);
if (found)
{
ret[*returnSize] = i;
(*returnSize)++;
}
}
hash_free(hashmap, wordsSize);
ret = (int*)realloc(ret, sizeof(int) * (*returnSize));
return ret;
}
The case that report error is below:
int main() {
char *str = "ababaab";
char **words[] = { "ab", "ba", "ba" };
int returnSize = 0;
int *result = findSubstring(str, words, 3, &returnSize);
return 0;
}
When you call the hash_lookup function, it could return NULL in some cases. So when you use item->count in the next line, you may access a NULL pointer.
You should ensure that item isn't NULL first, and than use item->count, like so:
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
if (item != NULL && item->count != 0) {
found = false;
}
}
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
if (item != NULL) {
item->count = item->ori_count;
}
}

char array input with space

my program works fine if i give hard code value to char *w="ls -l" but i am trying to take input form user not working help my code:: using input error occur
i don't understand the concept of fgets using fgets its gives the garbig value to execv
#include<stdio.h>
#include<sys/wait.h>
#include<stdbool.h>
void func(char **arr, char *w)
{
int i = 0, j = 0, k = 0;
char temp[100];
for (i = 0; i < 100; i++)
{
if (w[i] == '')
{
arr[k] = temp;
arr[k+1] = NULL;
break;
}
if (w[i] == ' ')
{
arr[k] = temp;
k++;
j = 0;
}
else
{
temp[j] = w[i];
j++;
}
}
}
int main()
{
char *n = "/bin/ls";
char *arr[10] = {''};
char p[100] = {''};
char *w = "ls -l";
int i = 0;
//printf("bilal-hassan-qadri $ >>");
//fgets(p, 100, stdin);
arr[2] = NULL;
bool found = false;
for (i = 0; i < sizeof(w); i++)
{
if (w[i] == ' ')
{
found=true;
func(arr,w);
break;
}
}
if (!found)
arr[0] = w;
int status;
int id = fork();
if (id == 0)
{
if (execv(n,arr) < 0)
{
printf("invalid commandn");
}
else
{
printf("ninvalid command");
}
}
else
{
wait(&status);
}
}
In the function func, You have to copy the string to elements of arr
instead of just passing the address of temp, which will vanish on leaving the function.
You can use strdup instead of copy_string if your system supports it.
You have to terminate the string in temp before copying it.
Empty string constant '' seems invalid. You shouldn't use it.
fgets stores new-line character \n if it exists. Check for it and remove if it isn't wanted.
Fixed code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<stdbool.h>
char *copy_string(const char *str) {
char *s = malloc(strlen(str) + 1);
if (s) strcpy(s, str); else {perror("malloc"); exit(1);}
return s;
}
void func(char **arr, char *w)
{
int i = 0, j = 0, k = 0;
char temp[100];
for (i = 0; i < 100; i++)
{
if (w[i] == '\0' || w[i] == '\n')
{
temp[j] = '\0';
arr[k] = copy_string(temp);
arr[k+1] = NULL;
break;
}
if (w[i] == ' ')
{
temp[j] = '\0';
arr[k] = copy_string(temp);
k++;
j = 0;
}
else
{
temp[j] = w[i];
j++;
}
}
}
int main(void)
{
char *n = "/bin/ls";
char *arr[10] = {NULL};
char p[100] = {0};
char *w = "ls -l";
int i = 0;
//printf("bilal-hassan-qadri $ >>");
fgets(p, 100, stdin);
w = p;
arr[2] = NULL;
bool found = false;
for (i = 0; w[i] != '\0'; i++)
{
if (w[i] == ' ')
{
found=true;
func(arr,w);
break;
}
}
if (!found)
arr[0] = w;
int status;
int id = fork();
if (id == 0)
{
if (execv(n,arr) < 0)
{
printf("invalid commandn");
}
else
{
printf("ninvalid command");
}
}
else
{
wait(&status);
for (i = 0; arr[i] != NULL; i++) free(arr[i]);
}
return 0;
}

How to remove item from array in C?

I want to remove element from b->array as shown in below code:removeItem function
I have tried to remove 12.12 from the b->array = {11.11,12.12,13.13}but it leads to segmentation fault instead of printing {11.11,13.13}. can anybody help to get rid of it?
typedef struct
{
float val;
}data;
typedef struct
{
data **array;
int size;
}bag;
int main(int argc,char* argv[])
{
bag *str = createBag();
#ifdef DEBUG
printf("Inital values: %p %d\n",str->array,str->size);
#endif
data *iptr = createData(10.10);
data *iptr1 = createData(11.11);
data *iptr2 = createData(12.12);
data *iptr3 = createData(13.13);
data *iptr4 = createData(14.14);
#ifdef DEBUG
printf("%f\n",iptr->val);
#endif
addData(str,iptr);
addData(str,iptr1);
addData(str,iptr2);
addData(str,iptr3);
addData(str,iptr4);
printBag(str);
data *ptr = getData(str,4);
printf("Data item 4 is:%f\n",ptr->val);
int b = getBagSize(str);
printf("Size of bag: %d\n",b);
removeBack(str);
printBag(str);
removeFront(str);
printBag(str);
//cleanBag(str);
int s = searchBag(str,10.10);
printf("%d\n",s);
removeItem(str,12.12);
printBag(str);
return 0;
}
bag* createBag()
{
bag *str = (bag*)malloc(sizeof(bag));
str->array = NULL;
str->size = 0;
return str;
}
data* createData(float v)
{
data *iptr = (data*)malloc(sizeof(data));
iptr->val = v;
return iptr;
}
void addData(bag* b, data* d)
{
b->size++;
data** array1 = (data**)malloc(sizeof(data*)* b->size);
if(b->array!= NULL)
{
int i;
for(i = 0; i<b->size;i++)
{
array1[i] = b->array[i];
}
}
free(b->array);
array1[b->size-1] = d;
b->array = array1;
}
void printBag(bag *b)
{
int i;
for(i=0; i<b->size;i++)
{
printf("%f\n",b->array[i]->val);
}
}
data* getData(bag *b, int pos)
{
if(pos>5)
{
printf("change array position\n");
}
return b->array[pos];
}
int getBagSize(bag *b)
{
return b->size;
}
void removeBack(bag *b)
{
b->size--;
free(b->array[b->size]);
data **array2 = (data**)malloc(sizeof(data*)* b->size);
if(b->array!= NULL)
{
int i;
for(i = 0; i<b->size;i++)
{
array2[i] = b->array[i];
#ifdef DEBUG
printf("%f\n",array2[i]->val);
#endif
}
free(b->array);
b->array = array2;
}
}
void removeFront(bag *b)
{
b->size--;
free(b->array[0]);
data **array2 = (data**)malloc(sizeof(data*)* b->size);
if(b->array!= NULL)
{
int i;
for(i = 0; i<b->size;i++)
{
array2[i] = b->array[i+1];
#ifdef DEBUG
printf("%f\n",array2[i]->val);
#endif
}
free(b->array);
b->array = array2;
}
}
/*void cleanBag(bag *b)
{
int i;
for(i=0;i<b->size;i++)
{
free(b->array[i]);
}
free(b->array);
free(b);
}*/
int searchBag(bag *b,float v)
{
int i;
for(i=0;i<b->size;i++)
{
if(b->array[i]->val==v)
{
return (i+1);
}
}
return -1;
}
void removeItem(bag *b, float v)
{
int flag = 0,i = 0;
flag = searchBag(b,v);
if(flag != -1)
{
data **array2 = (data**)malloc(sizeof(data*)*(b->size-1));
for(i = 0; i < (b->size); i++)
{
if(i == (flag-1))
{
i = i + 1;
continue;
}
array2[i] = b->array[i];
}
free(b->array);
b->size--;
b->array = array2;
}
else
{
printf("Element is not found\n");
}
}
There are two mistakes in your code.
searchBag returns 0, if the float value is not found in the bag.
However, the function removeItem test for if(flag != -1). It should test for if(flag != 0) instead.
The reason for the seg. fault you encountered also lies in the removeItem function.
Note how the memory allocated for array2 is for b->size-1 elements only. Valid array indices for this array are in the range of 0 ... b->size-2.
Now, look at the for loop, and you will note that the index variable i will run from 0 to b->size-1. Exactly in the last iteration i will become b->size-1, so the code tries to write at the location array2[b->size-1] which is beyond the allocated memory of array2.
A possible fix of the removeItem function could look like this:
void removeItem(bag *b, float v)
{
int flag = 0;
int oldArrayIndex = 0;
int newArrayIndex = 0;
flag = searchBag(b,v);
if(flag != 0)
{
data **array2 = (data**) malloc(sizeof(data*)*(b->size-1));
for(oldArrayIndex = 0; oldArrayIndex < (b->size); oldArrayIndex++)
{
if(oldArrayIndex != (flag-1))
{
array2[newArrayIndex] = b->array[oldArrayIndex];
newArrayIndex++;
}
}
free(b->array);
b->size--;
b->array = array2;
}
else
{
printf("Element is not found\n");
}
}

how to implement next() PHP function in C

I am tried to implement next() PHP function in C. if I have
The different to my implementation is I want to do this work with more one points. For example:
if I have two char * like:
char * a = "ac\0";
char * b = "bd\0";
and I call:
printf("%c", cgetnext(a));
printf("%c", cgetnext(b));
printf("%c", cgetnext(a));
printf("%c", cgetnext(b));
gets an output like: abcd
but I get abab
here is my code:
`#include <string.h>
#include <stdlib.h>
typedef struct
{
int pLocation;
int myindex;
int lastIndex;
} POINTERINFORMATION;
int __myIndex = 0;
int pointersLocationsLength = 0;
char * temparr = NULL;
POINTERINFORMATION pointersLocations[256];
int
plAdd (int p)
{
if (pointersLocationsLength >= sizeof(pointersLocations)) {
return -1;
} else {
pointersLocations[pointersLocationsLength].pLocation = p;
pointersLocations[pointersLocationsLength].lastIndex = 0;
pointersLocationsLength ++;
return pointersLocationsLength;
}
}
int
getPointer (int p, POINTERINFORMATION * out)
{
int i;
for (i = 0; i < pointersLocationsLength; i++)
{
if(pointersLocations[pointersLocationsLength].pLocation == p)
{
pointersLocations[i].myindex = i;
*out = pointersLocations[i];
return 1;
}
}
return 0;
}
void
getPointerIndex(char ** variable, int * val)
{
char * buf = malloc(256);
if(sprintf(buf,"%p", &variable) > 0){
*val = strtol(buf, NULL, 16 );
} else {
*val = -1;
}
}
int
inArrayOfPointers (int pointer)
{
POINTERINFORMATION pi;
return getPointer(pointer, &pi);
}
char
cgetnext(char * arr)
{
char * myarr;
const size_t size = sizeof(char *) + 1;
int pof;
myarr = malloc(size);
getPointerIndex (&arr, &pof);
if (inArrayOfPointers(pof)){
POINTERINFORMATION pi;
if (getPointer(pof, &pi))
{
myarr = (char *)*(int *)pi.pLocation;
__myIndex = pi.lastIndex;
++pointersLocations[pi.myindex].myindex;
} else {
return 0;
}
} else {
if (plAdd(pof) == -1) {
printf(" CANNOT ADD ELEMENT TO ARRAY\n");
exit(0);
} else {
myarr = arr;
__myIndex = 0;
}
}
if (strlen(myarr) == __myIndex) {
return 0;
} else {
temparr = malloc(size);
temparr = strdup(myarr);
return myarr[__myIndex];
}
}`
how to fix this? differents solutions for solve it are very apreciated! Thanks in advance.
If you are specifically interested in char* "arrays", then a simple solution might be to just increment the pointer. Note that if using dynamically allocated memory, you need to save the original pointer to free it. The same idea could be used for other data types as well.
This is an example of what I mean. cgetnext here just returns the character at the current position in the array and increments pointer (that is passed by address).
char cgetnext( char **p )
{
assert( p != NULL );
// check for end of string
if ( **p == '\0' )
return '\0';
return *(*p)++;
}
int main( int argc, char* argv[] )
{
char *a = "ac";
char *b = "bd";
printf( "%c", cgetnext(&a));
printf( "%c", cgetnext(&b));
printf( "%c", cgetnext(&a));
printf( "%c", cgetnext(&b));
}

Resources