Pass String array and indexes using Struct to a thread in C - c

I am trying to pass a string array and indexes from where to start end searching in the array, I am unable to solve it from the last two days. I am sending to the pthread_create a struct data thread_data, here i am able to send the int and long data, but not the string array, can someone help me, how to pass these.
struct data{
int tid;
unsigned long start;
unsigned long end;
char * word;
char * str;
};
struct data thread_data[NUM_THREADS];
void *searchString(void *passeddata)
{
struct data *t_data;
int tid1;
char * str[3];
t_data=(struct data *) passeddata;
tid1=t_data->tid;
str=t_data->str;
.....
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
...
char work[]={"First Line","Second line","Third line"};
...
while(fgets(arr[index],120, fp)!=NULL){
index=index+1;
thread_data[index].tid=index;
thread_data[index].str=work;
...
rc=pthread_create(&threads[index],NULL,searchString,(void *)&thread_data[index]);
...
}
pthread_exit(NULL);
}

To hold the multiple strings you need 2D array.
const char *work[]={"First Line","Second line","Third line", "Fourth Line"};
You need to use pointer to pointer in struct data to hold the above array.
struct data{
.....
const char **str;
size_t lenOfStr;
};
And pass the length of array explicitly to thread function from main function.
Your sample code may look like below.
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
struct data{
int tid;
unsigned long start;
unsigned long end;
char * word;
const char **str;
size_t lenOfStr;
};
struct data thread_data[3];
void *searchString(void *passeddata)
{
struct data *t_data;
int tid1;
const char **str = NULL;
t_data=(struct data *) passeddata;
tid1=t_data->tid;
str=t_data->str;
int i = 0;
for (i = 0;i<t_data->lenOfStr;i++)
printf("%s\n", str[i]);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
const char *work[]={"First Line","Second line","Third line", "Fourth Line"};
int index = 0;
pthread_t threadid=0;
thread_data[index].tid=index;
thread_data[index].str=work;
thread_data[index].lenOfStr = sizeof(work)/sizeof(*work); // Calculate the size of work here
int rc=pthread_create(&threadid,NULL,searchString,&thread_data[index]);
pthread_exit(NULL);
}

Related

Run function from structure variable

I try to run a function with a structure, because I work with a module who send callback so I want to execute the fuction to anwser to the callback.
typedef void (*bgs2_e_rx_callback)(unsigned char reason, unsigned short int n, char * data);
void bgs_callbacktest(char* data);
/*void test(int* ptest);
void test_tab(char* data,char* ptaille);
char* concat(const char *s1, const char *s2);
static void parse_numeric_rsp(char nb_values, char * data, unsigned long data_len,unsigned long * result);*/
struct teststruct{
short int i ;
bgs2_e_rx_callback callback;
void* param;
};
struct teststruct leteststruct ;
int main(){
printf("test for function in structure\n");
char txt[]="i'm a text";
leteststruct.param = txt;
leteststruct.callback = &bgs_callbacktest;
}
void bgs_callbacktest(char* data){
printf("your text: %s\n",leteststruct.param);
}
Compilation works good, but I don't see the message of the callback function.
You never call it! Edit your main like this:
int main(){
printf("test for function in structure\n");
char txt[]="i'm a text";
leteststruct.param = txt;
leteststruct.callback = bgs_callbacktest;
// Change the dummy parameters below with yours
leteststruct.callback(0x7f, 512, txt);
}
Then you will have it.

Programming in C: Changing member value of struct gives segfault

There are quite a few topics on this subject but I haven't been able to find a solution that's worked for me; I am getting a segmentation fault whenever I try to change student_t.member->name. Below is the typedef structure that I am required to use:
typedef struct degree_t degree_t;
typedef struct student_t student_t;
struct degree_t {
student_t* member;
int course_id;
}
struct student_t {
char* name;
int age;
}
int main(int argc, char* argv[]) {
student_t *students = malloc(sizeof(student_t) * 3);
degree_t *degrees = malloc(sizeof(degree_t));
for (int i=0; i<3; i++) {
degrees[i].course_id = 1;
degrees[i].member->name = "Bob";
}
return 0;
}
I can change degrees[i].course_id perfectly fine, but whenever I try to change degrees[i].member -> name, I get a segmentation fault.
GDB indicates that this is a result of the line degrees[i].member->name = "Bob", but I'm don't understand why, and I don't know how to effectively change the value of degrees[i].member->name
Oops, you managed to place four errors in that small program.
The signature of main() should be main(int argc, char *argv[]). argv is an array of strings found on the command line.
You allocate memory for one degree, but in the for-loop you initialize three of them. This leads to a heap corruption.
You don't initialize degrees->member, but use it.
You allocate memory for three students, but don't use it.
Try this:
struct degree_t {
student_t* member;
int course_id;
}
struct student_t {
const char* name;
int age;
}
int main(int argc, char* argv[]) {
degree_t *degrees = malloc(3 * sizeof(degree_t));
for (int i=0; i<3; i++) {
degrees[i].course_id = 1;
degrees[i].member = malloc(sizeof(student_t));
degrees[i].member->name = "Bob";
degrees[i].member->age = 23;
}
return 0;
}

How to assign an array to a struct in C

Say I have a simple struct, such as this one:
struct myStruct {
uint8_t arr[10];
};
All I want to be able to do is to modify the contents of that array. However, it seems that I cannot assign the array directly (ie, I can't do something like pointerToThisStruct->arr = anArrayofSizeTen).
So here is my main method:
int main(int argc, char **argv) {
uint8_t test[10] = {0};
myStruct *struc;
struc->arr = test; //can't do this
memcpy(struc->arr, test, sizeof(test));
}
Now, I understand that direct copying over won't work, but why is memcpy also giving me a segfault? How exactly am I supposed to modify the struct array?
You need to declare an actual myStruct. Not a pointer to one. Declaring a pointer to one doesn't actually allocate any memory for the struct.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
struct myStruct {
uint8_t arr[10];
};
int main(int argc, char **argv) {
int i;
uint8_t test[10] = {0,1,2,3,4,5,6,7,8,9};
struct myStruct struc;
memcpy(struc.arr, test, sizeof(struc.arr));
printf("struc.arr[] = ");
for( i=0; i < sizeof(test); i++ )
{
printf("%d ", struc.arr[i]);
}
printf("\n");
return( 0 );
}
You are getting a segmentation fault because you didn't allocate your struct pointer.
int main(int argc, char **argv) {
uint8_t test[10] = {0};
struct myStruct *struct = malloc(sizeof(struct myStruct));
if (!struc)
return -1;
memcpy(struc->arr, test, sizeof(test));
free(struc);
return 0;
}
But, as #Chimera mentioned, you perfectly can not use a point and directly a heap-allocated structure, and access to its inner fields with the . operator

Passing an argument to function pointer

I just can't figure out how to pass an Argument like in the following scenario:
#include<stdio.h>
void quit(const char*);
int main(void){
const char *exit = "GoodBye";
void (*fptr)(const char*) = quit;
(*fptr)(exit);
return 0;
}
void quit(const char *s){
printf("\n\t%s\n",s);
}
This is how my program should work and it does, but when I make a text menu i just can't figure out how to do it:
#include<stdio.h>
#include<stdlib.h>
int update(void);
int upgrade(void);
int quit(void);
void show(const char *question, const char **options, int (**actions)(void), int length);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])(void) = {update,upgrade,quit};
show(question,options,actions,3);
return 0;
}
int update(void){
printf("\n\tUpdating...\n");
return 1;
}
int upgrade(void){
printf("\n\tUpgrade...\n");
return 1;
}
int quit(void){
printf("\n\tQuit...\n");
return 0;
}
void show(const char *question, const char **options, int (**actions)(void), int length){
int choose = 0, repeat = 1;
int (*act)(void);
do{
printf("\n\t %s \n",question);
for(int i=0;i<length;i++){
printf("%d. %s\n",(i+1),options[i]);
}
printf("\nPlease choose an Option: ");
if((scanf("%d",&choose)) != 1){
printf("Error\n");
}
act = actions[choose-1];
repeat = act();
if(act==0){
repeat = 0;
}
}while(repeat == 1);
}
Here I need to change the quit function (int quit(void); to int quit(char *s){};) like in the First example and call it with an argument like const char *exit = "GoodBye"; ==>> (*fptr)(exit);
I know that at this point my program takes only void as argument, but I done it only to illustrate the problem.
I'm very confused about this.
EDIT:
this int (*actions[3])(void) I think is an Array of Function pointers and all 3 function pointers takes void as argument, but I need to know if i can use one pointer to take an argument or i have to re-code the whole program.
Since you have an array of function pointers, all the functions need to be of the same type. So at the very least each function should take a const char * (not all functions need to use it) and the array type should be changed to match.
If you want something more flexible, you can have the functions accept a single void * so each function can be passed a different parameter which it then casts to the appropriate type. This is how pthreads passes parameters to functions which start a new thread. You will lose some compile-time type checking with this, so be careful if you go this route.
EDIT:
An example of the latter:
#include<stdio.h>
#include<stdlib.h>
int update(void *);
int upgrade(void *);
int quit(void *);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])(void *) = {update,upgrade,quit};
show(question,options,actions,3);
return 0;
}
int update(void *unused){
printf("\n\tUpdating...\n");
return 1;
}
int upgrade(void *unused){
printf("\n\tUpgrade...\n");
return 1;
}
int quit(void *message){
printf("\n\tQuit...%s\n", (char *)message);
return 0;
}
void show(const char *question, const char **options, int (**actions)(void *), int length){
...
if (act == quit) {
repeat = act("GoodBye");
} else {
repeat = act(NULL);
}
...
}
Since you are using a an array of function pointers, you don't know which ones to take which arguments. But have You can avoid re-coding it by making the functions to take "unspecified number of arguments". i.e. Remove the void from as the parameter from function definitions and prototypes from of the function pointers and from the quit() function.
int quit(const char*);
void show(const char *question, const char **options, int (**actions)(), int length);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])() = {update,upgrade,quit};
...
}
int quit(const char *msg){
printf("\n\tQuit...%s\n", msg);
return 0;
}
void show(const char *question, const char **options, int (**actions)(), int length){
....
int (*act)();
....
}
This works because C allows a function with no explicit parameters to take "unspecified number of arguments". Otherwise, you need to make all functions have similar signatures.

Why updated structure variable not printing

This is my code in which if student marks is greater than 85,scholarship status will be changed to sanctioned, but after updating it is not printing
#include<stdio.h>
#include<string.h>
struct scholor
{
char name[25];
int sem;
int marks;
char status;
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",&s1.name,&s1.sem,&s1.marks,&s1.status);
sanction(s1.marks,&s1.status);
printf("%s",s1.status);
}
status is a single char but you are storing a string into it, effectively doing out of bounds access (undefined behaviour). Change it to an array and then you'll be able to copy.
struct scholor
{
char name[25];
int sem;
int marks;
char status[128];
};
and adjust the calls and passing (since status is an array now -- its name gets converted into a pointer t its first element when passed to functions):
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
Other suggestions:
1. Use a standard prototype for main such as: int main(void)
2. You could usr strcpy to copy the string as opposed to doing it yourself.
Your struct should have status as a character array not a character .Moreover when you scanf an array dont write & before because the name itself points to the assdress of the first element.Your corrected program is :
struct scholor
{
char name[25];
int sem;
int marks;
char status[16];
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
}

Resources