Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <semaphore.h>
int file_index = 0; // index for array[500];
struct webData {
char web_names [255];
};
void *thread(void *wData_element)
{
struct webData *temp = wData_element;
FILE *fp;
char line[255]=""; // hold each line;
fp = fopen(temp->web_names, "r");
if(fp == NULL)
{
perror("Error: File open failure.");
}
else
{
fgets(line,255, fp);
printf("%s\n", line);
}
fclose(fp);
return NULL;
}
int main(int argc, char const* argv[])
{
DIR * dir_pointer; // define a dir pointer;
struct dirent * entry; // entry under dir;
//char *dir = "./data/";
dir_pointer = opendir("./data/"); // assign dir location into dir pointer
// declare the struct wData array for each file.
struct webData wData[500];
// declare the threads array.
pthread_t tid_array[500];
while( (entry = readdir(dir_pointer)) != NULL)
{
if(entry->d_type == DT_REG) // avoid the . and .. dir;
{
char full_path[255];
full_path[0] = '\0'; // initilize the string;
strcat(full_path, "./data/"); // concatenate file directory;
strcat(full_path, entry->d_name); // concatenate filename;
strcpy(wData[file_index].web_names, full_path); // store file name into web_names array;
pthread_create(&tid_array[file_index], NULL, thread, &wData[file_index]);
file_index++; // increase the file index for next file.
}
}
for(int i=0; i<500; i++)
{
pthread_join(tid_array[i], NULL);
}
return 0;
}
For this program:
There are 500 files in the data folder.
For each file, I create a thread to do some action on the file.
After I iterate all 500 files. I join all the threads.
My question is:
How can I create 10 threads, and each thread does some action on exact 50 files?
How can I make sure each thread only handle 50 files since they are running concurrently?
For example:
thread 1 handles files number from 1-50
thread 2 handles files number from 51-100
.
.
.
Thanks a lot for any related source or example.
First you declare a parameter-struct for the threads
typedef struct thread_param_s {
// each thread will get an array of webData-files
struct webData* data;
// number of elements
int n;
} thread_param_t;
You create this param-struct for each thread, fill it accordingly and pass it in pthread_create instead of the wData*
Now you adjust your current code
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <semaphore.h>
int file_index = 0; // index for array[500];
struct webData {
char web_names [255];
};
void *thread(void *param)
{
thread_param_t* thread_param = (thread_param_t*)param;
int i;
// iterate through all files
for (i = 0; i < thread_param->n; i++) {
struct webData *temp = thread_param->data + i;
FILE *fp;
char line[255]=""; // hold each line;
fp = fopen(temp->web_names, "r");
if(fp == NULL)
{
perror("Error: File open failure.");
}
else
{
fgets(line,255, fp);
printf("%s\n", line);
}
}
return NULL;
}
int main(int argc, char const* argv[])
{
DIR * dir_pointer; // define a dir pointer;
struct dirent * entry; // entry under dir;
//char *dir = "./data/";
dir_pointer = opendir("./data/"); // assign dir location into dir pointer
// declare the struct wData array for each file.
struct webData wData[500];
// declare the threads array.
while( (entry = readdir(dir_pointer)) != NULL)
{
if(entry->d_type == DT_REG) // avoid the . and .. dir;
{
char full_path[255];
full_path[0] = '\0'; // initilize the string;
strcat(full_path, "./data/"); // concatenate file directory;
strcat(full_path, entry->d_name); // concatenate filename;
strcpy(wData[file_index].web_names, full_path); // store file name into web_names array;
file_index++; // increase the file index for next file.
// just fill wData here
}
}
pthread_t tid_array[10];
thread_param_t thread_param[10];
int thread_counter = 0;
// number of files for each thread
int step = file_index / 10;
int i;
// create all threads
for(i = 0; i < 9; i++)
{
thread_param[i].n = step;
thread_param[i].data = wData + step * i;
pthread_create(&tid_array[i], NULL, thread, thread_param + i);
}
// the last thread may get more data, because of integer rounding
thread_param[i].n = file_index - step * i;
thread_param[i].data = wData + step * i;
pthread_create(&tid_array[i], NULL, thread, thread_param + i);
for(int i=0; i<10; i++)
{
pthread_join(tid_array[i], NULL);
}
return 0;
}
Related
I am trying to write a program that implements somehow the "dir" command that you can use in the Unix shell but I have encountered the following problem. I managed to read the current directory as I will show in the code but I don't know exactly how I am supposed to sort it in order to make it like the dir function which sorts the files from the directory
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
void dirfunction()
{
DIR* directory=opendir(".");
if(directory==NULL)
{
perror("Directory does not exist");
exit(1);
}
struct dirent* p;
p=readdir(directory);
int i=0;
while(p!=NULL)
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
printf("%s ",p->d_name);
i++;
}
p=readdir(directory);
}
printf("\n");
closedir(directory);
}
int main(int argc,char** argv[])
{
dirfunction();
}
Should I basically do the normal sorting for an array of character, like adding all file names in an array of string and sort it with selection sort or another sort method? I don't really get how dir command sorts the files before printing them to the terminal.
Because readdir reuses the same buffer for the returned entry, we need a dynamic [growing] array to save/store the struct dirent entries.
Then, we need to sort the stored entries (e.g. use qsort).
Side note: int main(int argc,char **argv[]) is incorrect. It should be: int main(int argc,char **argv) There was one too many levels of indirection.
Below is the updated code with some enhancements. It is annotated:
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
// dynamic array of dirent structs
struct dirlist {
size_t count; // number of entries
struct dirent *base; // pointer to list start
};
// dirload -- load up directory
// RETURNS: directory list
struct dirlist *
dirload(const char *path)
{
size_t capacity = 0;
struct dirlist *list = calloc(1,sizeof(*list));
DIR *directory = opendir(path);
if (directory == NULL) {
perror("Directory does not exist");
exit(1);
}
struct dirent *p;
while (1) {
// get next entry
// this is overwritten, so we need to copy/save it below
p = readdir(directory);
if (p == NULL)
break;
// skip over "." and ".."
if (p->d_name[0] == '.') {
if (p->d_name[1] == 0)
continue;
if ((p->d_name[1] == '.') && (p->d_name[2] == 0))
continue;
}
// enlarge array
if (list->count >= capacity) {
capacity += 10;
list->base = realloc(list->base,sizeof(*list->base) * capacity);
if (list->base == NULL) {
perror("realloc");
exit(1);
}
}
// save dirent entry
list->base[list->count++] = *p;
}
closedir(directory);
// trim list to actual size
list->base = realloc(list->base,sizeof(*list->base) * list->count);
if (list->base == NULL) {
perror("realloc");
exit(1);
}
return list;
}
// dircmp -- compare dirent structs
int
dircmp(const void *lhsp,const void *rhsp)
{
const struct dirent *lhs = lhsp;
const struct dirent *rhs = rhsp;
int cmp;
cmp = strcmp(lhs->d_name,rhs->d_name);
return cmp;
}
// dirsort -- sort directory list
void
dirsort(struct dirlist *list)
{
if (list->count > 0)
qsort(list->base,list->count,sizeof(*list->base),dircmp);
}
// dirprint -- print directory list
void
dirprint(const struct dirlist *list)
{
const struct dirent *p = list->base;
for (size_t idx = 0; idx < list->count; ++idx, ++p)
printf("%s\n",p->d_name);
}
// dirdestroy -- destroy directory list
void
dirdestroy(struct dirlist *list)
{
if (list != NULL)
free(list->base);
free(list);
}
int
main(int argc, char **argv)
{
--argc;
++argv;
const char *dir;
if (argc > 0)
dir = *argv;
else
dir = ".";
struct dirlist *list = dirload(dir);
// sort the list
dirsort(list);
// print the list
dirprint(list);
// destroy the list
dirdestroy(list);
return 0;
}
I have currently made this much of the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#define STRSIZE 21
struct PInven{
int count;
struct PItem{
char name[STRSIZE];
int amount;
}Pitem;
}Pinven;//this needs to be an output file
int ReadInProduce (){
//read in file and check to see if the file exist or not.
FILE * PinFile = fopen("produce.txt","r");
if (PinFile == NULL){
printf("ERROR: WRONG FILE");
}
else{
printf("I did it!!\n");
}
//assigning the value gotten into the struct variable(but need to maybe change this since it needs to be an output)
fscanf(PinFile,"%d",&Pinven.count);
printf("%d\n", Pinven.count);
int i;
for(i =0; i <Pinven.count; i++){
fscanf(PinFile,"%20s %d",Pinven.Pitem.name, &Pinven.Pitem.amount);
printf("%s %d\n",Pinven.Pitem.name, Pinven.Pitem.amount);
}
//making an array to hold the variables
//FILE * PoutFile = fopen("produce_update.txt","w");
fclose(PinFile);
return 0;
}
From there I want to get the file that is read to the structs to be printed out into an array so that later on I can make a function that will be able to compare to the to it.
Basically a store management system. Where the file of the inventory is read in and compared to the file that is store and return a new value for the amount of produce now either left or gained.
10 //number of items that will be stored in the store
apple 19
banana 31
broccoli 9
...
In general, it's a really bad idea to include header information in the file about the number of entries in the file. You want to be able to do stream processing, and that will be more difficult if you need that meta-data. More importantly, it is important to understand how to write the code so that you don't need it. It's not really that difficult, but for some reason people avoid it. One simple approach is just to grow the array for each entry. This is horribly inefficient, but for the sake of simplicity, here's an example that expects the file not not include that first line:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <limits.h>
#define STRSIZE 128
struct PItem{
char name[STRSIZE];
int amount;
};
struct PInven{
int count;
struct PItem *PItem;
};
static void
grow(struct PInven *p)
{
p->PItem = realloc(p->PItem, ++p->count * sizeof *p->PItem);
if( p->PItem == NULL ){
perror("out of memory");
exit(1);
}
}
int
ReadInProduce(struct PInven *P, const char *path)
{
FILE * PinFile = fopen(path, "r");
if( PinFile == NULL ){
perror(path);
exit(1);
}
char fmt[64];
int max_len;
max_len = snprintf(fmt, 0, "%d", INT_MAX);
snprintf(fmt, sizeof fmt, "%%%ds %%%dd", STRSIZE - 1, max_len - 1);
grow(P);
struct PItem *i = P->PItem;
while( fscanf(PinFile, fmt, i->name, &i->amount) == 2 ){
i += 1;
grow(P);
}
P->count -= 1;
fclose(PinFile); /* Should check for error here! */
return P->count;
}
int
main(int argc, char **argv)
{
struct PInven P = {0};
char *input = argc > 1 ? argv[1] : "produce.txt";
ReadInProduce(&P, input);
struct PItem *t = P.PItem;
for( int i = 0; i < P.count; i++, t++ ){
printf("%10d: %s\n", t->amount, t->name);
}
}
As an exercise for the reader, you should add some error handling. At the moment, this code simply stops reading the input file if there is bad input. Also, it would be a useful exercise to do fewer reallocations.
you should change Structure of PInven to it can save a dynamic array of Pitem with a Pitem pointer.
tested :
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define STRSIZE 21
typedef struct {
char name[STRSIZE];
int amount;
} Pitem;
struct PInven {
int count;
Pitem *pitem;
} Pinven; // this needs to be an output file
int main() {
// read in file and check to see if the file exist or not.
FILE *PinFile = fopen("produce.txt", "r");
if (PinFile == NULL) {
printf("ERROR: WRONG FILE");
} else {
printf("I did it!!\n");
}
// assigning the value gotten into the struct variable(but need to maybe
// change this since it needs to be an output)
fscanf(PinFile, "%d", &Pinven.count);
Pinven.pitem = (Pitem *)malloc(sizeof(Pitem) * Pinven.count);
printf("%d\n", Pinven.count);
int i;
for (i = 0; i < Pinven.count; i++) {
fscanf(PinFile, "%20s %d", Pinven.pitem[i].name,
&Pinven.pitem[i].amount);
// printf("%s %d\n",Pinven.pitem[i].name, Pinven.pitem[i].amount);
}
for (i = 0; i < Pinven.count; i++) {
printf("%s %d\n", Pinven.pitem[i].name, Pinven.pitem[i].amount);
}
// making an array to hold the variables
// FILE * PoutFile = fopen("produce_update.txt","w");
fclose(PinFile);
// remember free
free(Pinven.pitem);
return 0;
}
I am creating a struct called Job and I want to create an array of struct Job. The name of my array is jobQueue I populate the array using commandline args. The instructor has it set up to where **args is being used. After the user inputs the name of the job and the execution time it gets added to the array. However, when I try to print jobQueue[0].name using the list() funct I have written, the name does not get printed. I'm trying to get my code set up to where I can print the name. I have provided a minimal version of my overall project that just focuses on the specific problem I am encountering and should compile and run fine.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <sys/wait.h>
#include <stdint.h>
#define EINVAL 1
#define E2BIG 2
#define MAXMENUARGS 7
//structure job initialize
struct Job {
//initializing name variable
char *name;
int executionTime;
};
//init the array
struct Job jobQueue[5] = {0};
//cmd function provided by intructor
int cmd_run(int nargs, char **args) {
int execT;
sscanf(args[2], "%d", &execT);
run(args[1], execT);
return 0;
}
//cmd function provided by intructor
void cmd_list() {
list();
}
//cmd function provided by intructor
static struct {
const char *name;
int (*func)(int nargs, char **args);
} cmdtable[] = {
/* commands: single command must end with \n */
{ "r", cmd_run},
{ "run", cmd_run},
{ "list\n", cmd_list}
};
//cmd function provided by intructor
//this is the function that handles the arguments entered by the user
//provided it just in case someone needs to see how arguments are being
//processed
int cmd_dispatch(char *cmd) {
time_t beforesecs, aftersecs, secs;
u_int32_t beforensecs, afternsecs, nsecs;
char *args[MAXMENUARGS];
int nargs = 0;
char *word;
char *context;
int i, result;
void *Dispatcher(void *arg);
for (word = strtok_r(cmd, " ", &context);
word != NULL;
word = strtok_r(NULL, " ", &context)) {
if (nargs >= MAXMENUARGS) {
printf("Command line has too many words\n");
return E2BIG;
}
args[nargs++] = word;
}
if (nargs == 0) {
return 0;
}
for (i = 0; cmdtable[i].name; i++) {
if (*cmdtable[i].name && !strcmp(args[0], cmdtable[i].name)) {
assert(cmdtable[i].func != NULL);
/* Call function through the cmd_table */
result = cmdtable[i].func(nargs, args);
return result;
}
}
printf("%s: Command not found\n", args[0]);
return EINVAL;
}
//adds job to the array using user arguments
void run(char name[], int executionTime) {
//creates a job using the arguments specified by user
struct Job job = {name, executionTime};
jobQueue[0] = job;
printf("\nJob added to queue now please type 'list'\n");
}
//name will not print here
void list() {
printf("\nSee how the name will not print below?\n");
char executionTimeStr[5];
for (int c = 0; c < sizeof (jobQueue) / sizeof (jobQueue[0]); c++) {
//prints job info formatted
if (jobQueue[c].name != NULL) {
sprintf(executionTimeStr, "%d", jobQueue[c].executionTime);
//job name will not print here, output is just left blank
printf("%s %20.8s", "Name", "ExecTime");
printf("%-10.15s %11.3s\n",
jobQueue[c].name,
executionTimeStr
);
}
}
}
int main(int argc, char *argv[]) {
printf("Welcome to our batch job scheduler\n");
printf("Please enter the following exactly: 'run job1 10' \n");
//ignore this, it handles my commandline parser
char *buffer;
size_t bufsize = 64;
buffer = (char*) malloc(bufsize * sizeof (char));
if (buffer == NULL) {
perror("Unable to malloc buffer");
exit(1);
}
while (1) {
printf("User Input: ");
getline(&buffer, &bufsize, stdin);
cmd_dispatch(buffer);
}
//ignore this, it handles my commandline parser
return 0;
}
I am working on a project and have hit a snag that I have spent hours trying to figure out. I'm fairly certain its very close to correct but obviously something is wrong in my malloc of the struct array. I'll post the code below so you can see it. The goal of this function set is to read in movie data saved in a file and put the data into a structure.
#include <stdio.h>
#include <stdlib.h>
#include "support.h"
#include "scanner.h"
#include <string.h>
int counter(char *movierecords)
{
int count = 0;
char *name;
char *about;
int date;
int time;
char *rate;
char *ppl;
char *dir;
//printf("test");
FILE *fp = fopen(movierecords, "r");
//printf("gggg");
name = readString(fp);
while (!feof(fp))
{
//printf("test in loop");
about = readString(fp);
date = readInt(fp);
time = readInt(fp);
rate = readToken(fp);
ppl = readString(fp);
dir = readString(fp);
//printf("test read");
free(name);
free(about);
free(rate);
free(ppl);
free(dir);
//printf("test free");
count++;
name = readString(fp);
}
//printf("test escape loop");
fclose(fp);
//printf("test file close");
return count;
}
movie **readRecord(char *movierecords, int count) //mallocates space and reads data into an array of movie structures
{
int x = 0;
movie **data1;
FILE *fp = fopen(movierecords, "r");
data1 = malloc(sizeof(struct movie *) * (count + 1)); //mallocate space for the struct array movies1
printf("another test");
while (x < count + 1) //loop mallocates space for the string variables in movies1 struct for all movies
{
data1[x]->moviename = malloc(sizeof(char) * 1001);
data1[x]->description = malloc(sizeof(char) * 2001);
data1[x]->rating = malloc(sizeof(char) * 10);
data1[x]->cast = malloc(sizeof(char) * 512);
data1[x]->director = malloc(sizeof(char) * 30);
x++;
}
printf("test point3\n"); x = 0;
while (!feof(fp))
{
data1[x]->moviename = readString(fp);
data1[x]->description = readString(fp);
data1[x]->year = readInt(fp);
data1[x]->length = readInt(fp);
data1[x]->rating = readToken(fp);
data1[x]->cast = readString(fp);
data1[x]->director = readString(fp);
x++;
}
printf("test point4\n");
fclose(fp);
return data1;
}
Header file:
typedef struct entry
{
char *moviename;
char *description;
int year;
int length;
char *rating;
char *cast;
char *director;
} movie;
int counter(char *movierecords);
movie **readRecord(char *movierecords, int count);
Main:
#include <stdio.h>
#include <stdlib.h>
#include "support.h"
#include <string.h>
int main (int argc, char **argv)
{
int count = 0;
printf("%d", argc);
movie **data1;
count = counter(argv[1]);
printf("%d", count);
printf("hello");
data1 = readRecord(argv[1], count);
return 0;
}
You have to allocate memory for this "data1[x]" because your malloc(double pointer) allocate memory for array of your records(single pointer). Fot the single pointer data[x] you have to allocate memory
Below is my code:
I cant seem to use qsort effectively... It turns my array into 0's after they are populated with names and start times... Is it a problem with my qsort call? or the qsort itself.
The header with the structures is as follows:
/**
* Simulation of a process scheduler
*/
//#ifndef SCHEDULER_H_
#define SCHEDULER_H_
#include <stddef.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
/* types */
/** units of time */
typedef long time;
/** process identifier */
typedef int pid;
/** Information about a job of interest to the task scheduler */
struct job_data {
/* pid of this process */
pid pid;
/* time process starts */
time start;
/* time needed to finish */
time finish;
/* time spent processing so far */
time scheduled;
/* Number of lines */
int lines;
};
struct job {
/* Various parameters used by the scheduler */
char job_id[20];
struct job_data parameters;
char *lines[20];
};
/* I/O Files */
//static char *inputFile;
char * in;
static FILE *input;
static FILE *cur;
/*Scheduled jobs indexed by PID*/
struct job list[20];
/* the next job to schedule */
//static struct job *job_next = NULL;
/* Time */
time clock;
/*Comparison for qsort*/
int compare_start(const void *x, const void *y)
{
const struct job *a = x;
const struct job *b = y;
printf("%ld, %ld\n", a->parameters.start, b->parameters.start);
if (a->parameters.start < b->parameters.start)
{
return -1;
}
if (a->parameters.start > b->parameters.start)
{
return 1;
}
return 0;
}
/*Order Jobs*/
static void order_jobs(void)
{
qsort(list, (sizeof list) / (sizeof list[0]), sizeof list[0], compare_start);
}
/** Read and parse input from input file */
static void parse_input(void)
{
char buffer[BUFSIZ];
char lines[BUFSIZ];
int jobs = 0;
struct job *current;
while( fgets(buffer, sizeof(buffer), input) )
{
time start;
char buf[BUFSIZ];
sscanf(buffer,"./%s/", buf);
cur = fopen(buf, "r" );
int n_lines = 0;
while( fgets(lines, sizeof(lines), cur) )
{
if( n_lines == 0 )
{
current = &list[jobs];
strcpy(current->job_id, buf);
sscanf(lines,"%ld", &start);
current->parameters.start = start;
}
n_lines++;
}
current->parameters.lines = n_lines;
jobs++;
fclose(cur);
}
order_jobs();
for (int i = 0; i < jobs; i++)
{
printf("%s %ld %d\n", list[i].job_id, list[i].parameters.start, list[i].parameters.lines);
}
}
int main(int argc, char **argv)
{
in = argv[1];
if ( (input = fopen(in, "r")) == NULL ) {
fprintf(stderr, "cannot open %s\n", argv[1]);
}
parse_input();
fclose(input);
return EXIT_SUCCESS;
}
You only load jobs entries into the array, but you tell qsort() to sort the entire array (20 elements). This probably puts non-initialized elements at the front, which you then print.