My program is reading in files and using thread to compute the highest prime number, when I put a print statement into the getNum() function my numbers are printing out. However, it seems to just lag no matter how many threads I input. Each file has 1 million integers in it. Does anyone see something apparently wrong with my code? Basically the code is giving each thread 1000 integers to check before assigning a new thread. I am still a C noobie and am just learning the ropes of threading. My code is a mess right now because I have been switching things around constantly.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#include <semaphore.h>
//Global variable declaration
char *file1 = "primes1.txt";
char *file2 = "primes2.txt";
char *file3 = "primes3.txt";
char *file4 = "primes4.txt";
char *file5 = "primes5.txt";
char *file6 = "primes6.txt";
char *file7 = "primes7.txt";
char *file8 = "primes8.txt";
char *file9 = "primes9.txt";
char *file10 = "primes10.txt";
char **fn; //file name variable
int numberOfThreads;
int *highestPrime = NULL;
int fileArrayNum = 0;
int loop = 0;
int currentFile = 0;
sem_t semAccess;
sem_t semAssign;
int prime(int n)//check for prime number, return 1 for prime 0 for nonprime
{
int i;
for(i = 2; i <= sqrt(n); i++)
if(n % i == 0)
return(0);
return(1);
}
int getNum(FILE* file)
{
int number;
char* tempS = malloc(20 *sizeof(char));
fgets(tempS, 20, file);
tempS[strlen(tempS)-1] = '\0';
number = atoi(tempS);
free(tempS);//free memory for later call
return(number);
}
void* findPrimality(void *threadnum) //main thread function to find primes
{
int tNum = (int)threadnum;
int checkNum;
char *inUseFile = NULL;
int x=1;
FILE* file;
while(currentFile < 10){
if(inUseFile == NULL){//inUseFIle being used to check if a file is still being read
sem_wait(&semAccess);//critical section
inUseFile = fn[currentFile];
sem_post(&semAssign);
file = fopen(inUseFile, "r");
while(!feof(file)){
if(x % 1000 == 0 && tNum !=1){ //go for 1000 integers and then wait
sem_wait(&semAssign);
}
checkNum = getNum(file);
/*
*
*
*
* I think the issue is here
*
*
*
*/
if(checkNum > highestPrime[tNum]){
if(prime(checkNum)){
highestPrime[tNum] = checkNum;
}
}
x++;
}
fclose(file);
inUseFile = NULL;
}
currentFile++;
}
}
int main(int argc, char* argv[])
{
if(argc != 2){ //checks for number of arguements being passed
printf("To many ARGS\n");
return(-1);
}
else{//Sets thread cound to user input checking for correct number of threads
numberOfThreads = atoi(argv[1]);
if(numberOfThreads < 1 || numberOfThreads > 10){
printf("To many threads entered\n");
return(-1);
}
time_t preTime, postTime; //creating time variables
int i;
fn = malloc(10 * sizeof(char*)); //create file array and initialize
fn[0] = file1;
fn[1] = file2;
fn[2] = file3;
fn[3] = file4;
fn[4] = file5;
fn[5] = file6;
fn[6] = file7;
fn[7] = file8;
fn[8] = file9;
fn[9] = file10;
sem_init(&semAccess, 0, 1); //initialize semaphores
sem_init(&semAssign, 0, numberOfThreads);
highestPrime = malloc(numberOfThreads * sizeof(int)); //create an array to store each threads highest number
for(loop = 0; loop < numberOfThreads; loop++){//set initial values to 0
highestPrime[loop] = 0;
}
pthread_t calculationThread[numberOfThreads]; //thread to do the work
preTime = time(NULL); //start the clock
for(i = 0; i < numberOfThreads; i++){
pthread_create(&calculationThread[i], NULL, findPrimality, (void *)i);
}
for(i = 0; i < numberOfThreads; i++){
pthread_join(calculationThread[i], NULL);
}
for(i = 0; i < numberOfThreads; i++){
printf("this is a prime number: %d \n", highestPrime[i]);
}
postTime= time(NULL);
printf("Wall time: %ld seconds\n", (long)(postTime - preTime));
}
}
Yes I am trying to find the highest number over all. So I have made some head way the last few hours, rescucturing the program as spudd said, currently I am getting a segmentation fault due to my use of structures, I am trying to save the largest individual primes in the struct while giving them the right indices. This is the revised code. So in short what the first thread is doing is creating all the threads and giving them access points to a very large integer array which they will go through and find prime numbers, I want to implement semaphores around the while loop so that while they are executing every 2000 lines or the end they update a global prime number.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#include <semaphore.h>
//Global variable declaration
char *file1 = "primes1.txt";
char *file2 = "primes2.txt";
char *file3 = "primes3.txt";
char *file4 = "primes4.txt";
char *file5 = "primes5.txt";
char *file6 = "primes6.txt";
char *file7 = "primes7.txt";
char *file8 = "primes8.txt";
char *file9 = "primes9.txt";
char *file10 = "primes10.txt";
int numberOfThreads;
int entries[10000000];
int entryIndex = 0;
int fileCount = 0;
char** fileName;
int largestPrimeNumber = 0;
//Register functions
int prime(int n);
int getNum(FILE* file);
void* findPrimality(void *threadNum);
void* assign(void *num);
typedef struct package{
int largestPrime;
int startingIndex;
int numberCount;
}pack;
//Beging main code block
int main(int argc, char* argv[])
{
if(argc != 2){ //checks for number of arguements being passed
printf("To many threads!!\n");
return(-1);
}
else{ //Sets thread cound to user input checking for correct number of threads
numberOfThreads = atoi(argv[1]);
if(numberOfThreads < 1 || numberOfThreads > 10){
printf("To many threads entered\n");
return(-1);
}
int threadPointer[numberOfThreads]; //Pointer array to point to entries
time_t preTime, postTime; //creating time variables
int i;
fileName = malloc(10 * sizeof(char*)); //create file array and initialize
fileName[0] = file1;
fileName[1] = file2;
fileName[2] = file3;
fileName[3] = file4;
fileName[4] = file5;
fileName[5] = file6;
fileName[6] = file7;
fileName[7] = file8;
fileName[8] = file9;
fileName[9] = file10;
FILE* filereader;
int currentNum;
for(i = 0; i < 10; i++){
filereader = fopen(fileName[i], "r");
while(!feof(filereader)){
char* tempString = malloc(20 *sizeof(char));
fgets(tempString, 20, filereader);
tempString[strlen(tempString)-1] = '\0';
entries[entryIndex] = atoi(tempString);
entryIndex++;
free(tempString);
}
}
//sem_init(&semAccess, 0, 1); //initialize semaphores
//sem_init(&semAssign, 0, numberOfThreads);
time_t tPre, tPost;
pthread_t coordinate;
tPre = time(NULL);
pthread_create(&coordinate, NULL, assign, (void**)numberOfThreads);
pthread_join(coordinate, NULL);
tPost = time(NULL);
}
}
void* findPrime(void* pack_array)
{
pack* currentPack= pack_array;
int lp = currentPack->largestPrime;
int si = currentPack->startingIndex;
int nc = currentPack->numberCount;
int i;
int j = 0;
for(i = si; i < nc; i++){
while(j < 2000 || i == (nc-1)){
if(prime(entries[i])){
if(entries[i] > lp)
lp = entries[i];
}
j++;
}
}
return (void*)currentPack;
}
void* assign(void* num)
{
int y = (int)num;
int i;
int count = 10000000/y;
int finalCount = count + (10000000%y);
int sIndex = 0;
pack pack_array[(int)num];
pthread_t workers[numberOfThreads]; //thread to do the workers
for(i = 0; i < y; i++){
if(i == (y-1)){
pack_array[i].largestPrime = 0;
pack_array[i].startingIndex = sIndex;
pack_array[i].numberCount = finalCount;
}
pack_array[i].largestPrime = 0;
pack_array[i].startingIndex = sIndex;
pack_array[i].numberCount = count;
pthread_create(&workers[i], NULL, findPrime, (void *)&pack_array[i]);
sIndex += count;
}
for(i = 0; i< y; i++)
pthread_join(workers[i], NULL);
}
//Functions
int prime(int n)//check for prime number, return 1 for prime 0 for nonprime
{
int i;
for(i = 2; i <= sqrt(n); i++)
if(n % i == 0)
return(0);
return(1);
}
Here is my latest update, having issues with my threads running, the only thread is thread 0 that is completing
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#include <semaphore.h>
//Global variable declaration
char *file1 = "primes1.txt";
char *file2 = "primes2.txt";
char *file3 = "primes3.txt";
char *file4 = "primes4.txt";
char *file5 = "primes5.txt";
char *file6 = "primes6.txt";
char *file7 = "primes7.txt";
char *file8 = "primes8.txt";
char *file9 = "primes9.txt";
char *file10 = "primes10.txt";
sem_t semHold;
int numberOfThreads;
long unsigned int entries[10000000];
unsigned int entryIndex = 0;
int fileCount = 0;
char** fileName;
long unsigned int largestPrimeNumber = 0;
//Register functions
int prime(unsigned int n);
int getNum(FILE* file);
void* findPrimality(void *threadNum);
void* assign(void *num);
typedef struct package{
long unsigned int largestPrime;
unsigned int startingIndex;
unsigned int numberCount;
}pack;
pack pack_array[10];
//Beging main code block
int main(int argc, char* argv[])
{
if(argc != 2){ //checks for number of arguements being passed
printf("To many threads!!\n");
return(-1);
}
else{ //Sets thread cound to user input checking for correct number of threads
numberOfThreads = atoi(argv[1]);
if(numberOfThreads < 1 || numberOfThreads > 10){
printf("To many threads entered\n");
return(-1);
}
int threadPointer[numberOfThreads]; //Pointer array to point to entries
int i;
fileName = malloc(10 * sizeof(char*)); //create file array and initialize
fileName[0] = file1;
fileName[1] = file2;
fileName[2] = file3;
fileName[3] = file4;
fileName[4] = file5;
fileName[5] = file6;
fileName[6] = file7;
fileName[7] = file8;
fileName[8] = file9;
fileName[9] = file10;
FILE* filereader;
long unsigned int currentNum;
sem_init(&semHold, 0, 1);
for(i = 0; i < 10; i++){
filereader = fopen(fileName[i], "r");
while(fscanf(filereader, "%lu" , ¤tNum)!= EOF){
entries[entryIndex] = currentNum;
// while(entryIndex < 5){
//char* tempString = malloc(20 *sizeof(long unsigned int));
//fgets(tempString, 20, filereader);
//tempString[strlen(tempString)-1] = '\0';
//currentNum = atoi(tempString);
//printf("Test %lu\n",currentNum);
//entries[entryIndex] = atoi(tempString);
//entryIndex++;
//free(tempString);
//}
entryIndex++;
}
}
printf("Test %lu\n",entries[9999999]);
//sem_init(&semAccess, 0, 1); //initialize semaphores
//sem_init(&semAssign, 0, numberOfThreads);
time_t tPre, tPost;
pthread_t coordinate;
tPre = time(NULL);
pthread_create(&coordinate, NULL, assign, (void**)numberOfThreads);
pthread_join(coordinate, NULL);
tPost = time(NULL);
printf("Largest prime = %lu , time: %ld\n", largestPrimeNumber,(long)(tPost-tPre));
}
}
void* findPrime(void* pack_array)
{
pack* currentPack = pack_array;
unsigned int lp = currentPack->largestPrime;
unsigned int si = currentPack->startingIndex;
unsigned int nc = currentPack->numberCount;
int i;
printf("Starting index Count: %d\n", si);
for(i = si; i < nc; i++){
if(i%100000==0)
printf("Here is i: %d\n", i);
if(entries[i]%2 != 0){
if(entries[i] > currentPack->largestPrime){
if(prime(entries[i])){
currentPack->largestPrime = entries[i];
printf("%lu\n", currentPack->largestPrime);
if(currentPack->largestPrime > largestPrimeNumber)
sem_wait(&semHold);
largestPrimeNumber = currentPack->largestPrime;
sem_post(&semHold);
}
}
}
}
}
void* assign(void* num)
{
int y = (int)num;
int i;
int count = 10000000/y;
int finalCount = count + (10000000%y);
int sIndex = 0;
printf("This is count: %d\n", count);
printf("This is final count: %d\n", finalCount);
pthread_t workers[y]; //thread to do the workers
for(i = 0; i < y; i++){
printf("for thread %d Starting index: %d\n", i, sIndex);
if(i == (y-1)){
pack_array[i].largestPrime = 0;
pack_array[i].startingIndex = sIndex;
pack_array[i].numberCount = finalCount;
}
pack_array[i].largestPrime = 0;
pack_array[i].startingIndex = sIndex;
pack_array[i].numberCount = count;
pthread_create(&workers[i], NULL, findPrime, (void *)&pack_array[i]);
printf("thread created\n");
sIndex += count;
}
for(i = 0; i < y; i++)
pthread_join(workers[i], NULL);
}
//Functions
int prime(unsigned int n)//check for prime number, return 1 for prime 0 for nonprime
{
int i;
for(i = 2; i <= sqrt(n); i++)
if(n % i == 0)
return(0);
return(1);
}
OK here's part of my solution, it's missing most of main, and has some other simple stuff missing, if you choose to base your code around this you can do one of two things load all the data before starting your workers, or have the main thread load it while the workers are running, I did the latter in my complete version. However you'll have to do some work to get that to be handled correctly because currently the workers will never exit.
Also you might want to try adapting your single array code above based on this.
So if you load all the data before starting the workers you don't need the condition variable and they can just exit when next_chunk is NULL. I recommend you figure out how to get loading while the workers are running working because it'll be more efficient.
Hint: pthread_cond_broadcast()
Also missing is the actual worker function.
// A singly linked list of chunks of 1000 numbers
// we use it as a queue of data to be processed
struct number_chunk
{
struct number_chunk *next;
int size;
int nums[1000];
};
pthread_mutex_t cnklst_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t data_available = PTHREAD_COND_INITIALIZER;
struct number_chunk *next_chunk = NULL;
void load_chunks(char *filename)
{
FILE *in = fopen(filename, "r");
int done = 0;
int i;
if(in == NULL) {
fprintf(stderr, "Failed to open file %s\n", filename);
return;
}
// read in all the chunks of 1000 numbers from the file
while(!done) {
struct number_chunk *cnk = malloc(sizeof(struct number_chunk)); // allocate a new chunk
cnk->next = NULL;
for(i=0; i < 1000; i++) { // do the actual reading
char tmp[20];
if(fgets(tmp, 20, in) == NULL) { // end of file, leave the read loop
done = 1;
break;
}
cnk->nums[i] = atoi(tmp);
}
// need to do this so that the last chunk in a file can have less than 1000 numbers in it
cnk->size = i;
// add it to the list of chunks to be processed
pthread_mutex_lock(&cnklst_mutex);
cnk->next = next_chunk;
next_chunk = cnk;
pthread_cond_signal(&data_available); // wake a waiting worker
pthread_mutex_unlock(&cnklst_mutex);
}
fclose(in);
}
struct number_chunk *get_chunk()
{
struct number_chunk *cnk = NULL;
pthread_mutex_lock(&cnklst_mutex);
//FIXME: if we finish we will never exit the thread
// need to return NULL when all the work that there will ever be
// is done, altertitively load everything before starting the workers and
// get rid of all the condition variable stuff
while(next_chunk == NULL)
pthread_cond_wait(&data_available, &cnklst_mutex);
cnk = next_chunk;
if(next_chunk != NULL) next_chunk = next_chunk->next;
pthread_mutex_unlock(&cnklst_mutex);
return cnk;
}
The way my workers report the final max prime is to just do it at the end by looking at a single global variable and setting it or not based on the highest prime they found during their run. Obviously you'll need to synchronize for that.
Also note it uses a mutex rather than a semaphore because of the use of pthread_cond_wait() If you haven't covered condition variables yet just drop that stuff and load everything before starting your workers.
Also since this is homework, read my code try to understand it then without looking at it again try to write your own.
I would have changed it more but I'm not sure how because it's already basically a really generic producer/consumer example that's missing some bits :P
Another thing to try if you do decide to adopt the same strategy I did and have the loading running in the main thread while the workers work you could add a second condition variable and a counter to limit the number of chunks in the queue and have your workers wake up the main thread if they run out of work.
Related
I have an assignment in C Language; the requirement is that I am given number of students, everyone has 2 grades midterm grade and final grade my task is to calculate the number of students who passed. But I will use forking; we will fork Teaching Assistants to separately choose whether a student should pass or not and the number of Teaching Assistants will be passed on terminal.
Everything is fine. I wrote the code, but I noticed something very weird, I got a segmentation fault which is so weird because I am sure I am not accessing wrong memory. I tried to print something (line 53) and I found that this line is printed 4 times actually, which is equal to number of children + parent, although this line above the fork(). My code creates more than one process (TA) and every TA takes a partition and calculate number of passed students and exit with this code and on parent I make for loop and wait until any child dies so I print its exit code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
void main(int argc, char **argv)
{
int Number_of_TAs = atoi(argv[1]);
int leastgrade = atoi(argv[2]);
int size_of_array = 0;
int flag = 0;
int last_visited = 0;
int ind = 0;
FILE* ptr;
char ch;
// Opening file in reading mode
ptr = fopen("students.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
do {
ch = fgetc(ptr);
size_of_array = 2 * ((int)ch - 48);
break;
} while (ch != EOF);
fclose(ptr);
int arr_of_grades[size_of_array];
int arr_of_grades2[size_of_array/2];
FILE *myFile;
myFile = fopen("students.txt", "r");
int *dummy;
fscanf(myFile, "%d", &dummy);
for (int i = 0; i < size_of_array; i++)
fscanf(myFile, "%d", &arr_of_grades[i]);
int index2 = 0;
printf("%d", size_of_array);
printf(" ");
for (int i = 0; i< size_of_array; i=i+2)
{
arr_of_grades2[index2] = arr_of_grades[i] + arr_of_grades[i+1];
index2 = index2 + 1;
}
fclose(myFile);
int pid, stat_loc;
int passed_students = 0;
int partion = size_of_array / (2 * Number_of_TAs );
for (int i=0; i< Number_of_TAs; i++)
{
pid = fork();
ind = ind + partion;
}
if (pid == 0)
{
for (int i = ind; i< ind + partion; i++)
{
if (arr_of_grades2[i]>=leastgrade )
passed_students = passed_students + 1;
}
exit(passed_students);
}
else
{
int sid;
for (int i = 0; i<Number_of_TAs; i++)
{
sid = wait(&stat_loc);
if(!(stat_loc & 0x00FF))
printf(stat_loc>>8);
printf(" ");
}
}
return 0;
}
I am a newbie in C so I didn't try many things
The segmentation fault issue may happen at any array access with the wrong index.
In your case, it may happen at the first 2 lines:
int Number_of_TAs = atoi(argv[1]);
int leastgrade = atoi(argv[2]);
if you execute the program without the 2 parameters.
Another issue of your program is that you should move the if-else statement where you check the pid inside the for loop where you create the processes with the fork() otherwise it creates more processes than expected.
Okay, so I've been struggling with this problem for a few days. I'm trying to distribute an array of strings to various nodes in my Raspberry Pi 4 computing cluster using its most recent version of openmpi. I figured this was a perfect way to learn how clustering works, but I am completely lost at this point and have no direction. For the current set of code, I'm getting a segmentation fault, but when I follow other sets of instructions, I will sometimes receive only the first character of the first string, and null every other character. Those times are when instead of the current array send line, the first argument would be &(NodeOne[0][0]). Most of these sets of instructions are 6-9 years old.
Does anyone have any ideas to make the code do more than compile?
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>
#include <mpi.h>
#define NUMC 4
void *set_Stats(void *z);
struct Tickers {
char ** x;
int length;
};
struct Tickers getTickers()
{
CURL *curl = curl_easy_init();
char line[300];
struct Tickers tickers;
int length = 0;
char url[60] = "ftp://ftp.nasdaqtrader.com/symboldirectory/nasdaqtraded.txt";
if(curl)
{
FILE *temp = tmpfile();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)temp);
curl_easy_perform(curl);
if(temp)
{
rewind(temp);
char c = fgetc(temp);
while (fgets(line,sizeof(line),temp))
{
length++;
}
rewind(temp);
length = length - 2;
tickers.length = length;
tickers.x = malloc(length * sizeof(char*));
fgets(line, sizeof(line), temp);
fgets(line, sizeof(line), temp);
for(int count = 0; count < length; count++)
{
char *string = line + 2;
int tickLen = strstr(string, "|") - string;
char sub[tickLen];
tickers.x[count] = malloc(tickLen);
strncpy(sub, string, tickLen);
sub[tickLen] = '\0';
strcpy(tickers.x[count], sub);
fgets(line, sizeof(line), temp);
}
fclose(temp);
}
}
curl_easy_cleanup(curl);
return tickers;
}
char ** allocate_DD(int rows, int cols)
{
char *data = (char *)malloc(rows*cols);
char **array= (char **)malloc(rows*sizeof(char*));
for(int i = 0; i < rows; i++)
array[i] = &(data[cols*i]);
return array;
}
int main() //Designed for one master, three slaves
{
int my_id;
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
MPI_Status status;
int firstNodeLength;
if(my_id == 0) // meaning this process is a host job
{
struct Tickers tickers = getTickers();
int length = tickers.length / 3;
int remainder = tickers.length % 3;
char ** NodeOneTicks = allocate_DD(length + remainder, 6);
//char ** NodeTwoTicks = allocate_DD(length, 6);
//char ** NodeThrTicks = allocate_DD(length, 6);
int count = 0;
int x = 0;
while(count < length + remainder)
{
strcpy(NodeOneTicks[x], tickers.x[count]);
NodeOneTicks[x][5] = '\0';
count++;
x++;
}
x = 0;
firstNodeLength = length + remainder;
printf("%d\n", firstNodeLength);
MPI_Send(&firstNodeLength,1, MPI_INT,1,1000,MPI_COMM_WORLD);
MPI_Send(NodeOneTicks,firstNodeLength,MPI_CHAR,1,1001,MPI_COMM_WORLD);
}
else // must be slave process
{
int myLen;
int x = 0;
int ierr = MPI_Recv(&myLen,1,MPI_INT,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
printf("%d\n", myLen);
char ** myTicks = allocate_DD(myLen,6);
ierr = MPI_Recv(myTicks[0], myLen,MPI_CHAR,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
myTicks[0][5] = '\0';
printf("%s\n", myTicks[0]);
}
MPI_Finalize();
}
It turned out that the problem came from the original array returned by getTickers(). Even though it printed fine when the function was non-mpi, it was overflowed at certain points, rendering the MPI array to be garbage. Thank you to #GillesGouaillardet for helping / basically solving the problem for me!
Hello I am taking an intro to C-programming class so I am using very basic codes. Here I am simply trying to get a matrix of the commas out of the main string. However when I try running the program it keeps crashing on me and I don't know what is my problem. I was able to use the fgets function correctly so I think that is working fine still.
CD Data.txt File
Eagles, Hotel California, 1976, Rock, 4
The Fratellis, Costello Music, 2006, Garage Rock, 5
Awolnation, Megalithic Symphony, 2011, Indie Rock, 5
Lindsey Stirling, Lindsey Stirling, 2012, Classical Crossover, 5
Arctic Monkeys, AM, 2013, Indie Rock, 4
Program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define row 1000
#define column 1000
void getCommas(char str[], int commas[])
{
int flag, count, index;
count = 0;
index = 0;
flag = 1;
while(flag = 1)
{
if(str[count] = ',')
{
commas[index] = count;
index = index + 1;
}
count = count + 1;
if(str[count] = '\0')
{
flag = 0;
}
}
}
int main()
{
int i;
char CdInfo[row][column];
int Index[row][column];
FILE *fp;
fp = fopen("CD Data.txt","r");
for(i=0; i<5; i++)
{
fgets(CdInfo[i], sizeof CdInfo, fp);
//printf("%s\n",CdInfo[i]);
}
for (i=0; i<5; i++)
{
getCommas(CdInfo[i], Index[i]);
}
fclose(fp);
return 0;
}
These two variables are too big to be on the stack:
int main()
{
int i;
char CdInfo[row][column]; //<<
int Index[row][column]; //<<
declare them as static or as global variables.
And:
while(flag = 1)
should be
while(flag == 1)
and all
if (str[count] = ...
should be
if(str[count] == ...
You should also think about replacing
while(flag = 1) {
with :
while(flag == 1)
// note:
// the code is not making any use of more than one line of the
// input file at any one time, so
// only the current row actually needs to be defined
// note:
// this code makes no check for max length of each row (1000 char)
// that could/will be a problem when the input line is longer than 1000 character
// to avoid the error of writing an assignment rather than a literal,
// place the literal on the left side,
// then the compiler will notify you of the error
// rather than you having to spend time debugging the code
// trying to find the error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define row 1000
#define column 1000
//void getCommas(char str[], int commas[])
void getCommas( char * pStr, int * pCommas )
{
//int flag, count, index;
//count = 0;
//index = 0;
//flag = 1;
int flag = 1;
int count = 0;
int index = 0;
//while(flag = 1)
// following while loop could eliminate
// the 'flag' variable and related code by using
// and would be safer because never looking at string termination
// character but once.
// while( '\0' != pStr[count] )
while( 1 == flag )
{
//if(str[count] = ',')
if( ',' == pStr[count] )
{
pCommas[index] = count;
index = index + 1;
}
count = count + 1;
//if(str[count] = '\0')
if( '\0' == pStr[count] )
{ // then found end of string
flag = 0;
}
}
}
char CdInfo[row][column];
int Index[row][column];
int main()
{
int i = 0;
int rowCount = 0;
//char CdInfo[row][column]; // this is a huge item on the stack,
//int Index[row][column]; // this is a huge item on the stack,
//FILE *fp;
FILE *fp = NULL;
fp = fopen("CD Data.txt","r");
// always check the result of calls to io functions
if ( NULL == fp )
{ // then fopen failed
perror( "fopen" );
exit(1);
}
// implied else
// there is no reasonable reason (in the real world)
// to expect the input to be only 5 lines
//for(i=0; i<5; i++)
//{
// fgets(CdInfo[i], sizeof CdInfo, fp);
// //printf("%s\n",CdInfo[i]);
//}
for( i=0; i<row; i++ )
{
// following line checks results of call to I/O function
if( 0 == fgets( CdInfo[i], row, fp ) ) { break; }
// above line exits loop on end of file or I/O error
rowCount++;
}
//for (i=0; i<5; i++)
for( i = 0; i < rowCount; i++ )
{
getCommas(CdInfo[i], Index[i]);
}
fclose(fp);
return 0;
}
As the title says, whenever I try to copy string (using my own string type and library) I get a segmentation fault. According to debugger it happens at 29th line of source (where s_strcpy4() is called), which goes to the line in sstring.h with "_dest[i] = _sour[i];". i seems to have some different value from time to time at the time of the crash, but some times sticks to one value (not sure why yet). As of the writing it got stuck at 16896.
Anyone knows where I could be causing the segfault in the code?
source.c
#include "sstring.h"
#include <string.h>
#include <stdio.h>
#include <time.h>
int main(void) {
s_string ss1,
ss2;
long long int start, end;
struct timespec time;
FILE *LoremIpsum;
s_init(&ss1, NULL, 65536);
s_init(&ss2, NULL, 65536);
LoremIpsum = fopen("Lorem ipsum", "r");
if(LoremIpsum == NULL) {
perror("Error opening file ");
return 1;
}
fgets(ss2.string, 65536, LoremIpsum);
if(fclose(LoremIpsum) == EOF) {
perror("Error closing file ");
return 2;
}
s_strcpy4(&ss1, &ss2);
return 0;
}
sstring.h
#include <stdlib.h>
#include <stdint.h>
enter code here
typedef struct {
int length;
char *string;
} s_string;
s_string *s_init(s_string *str, char *array, size_t num) {
int i;
if(str == NULL)
str = malloc(sizeof(s_string));
if(array == NULL) {
(*str).length = num;
if(num != 0)
(*str).string = malloc(num);
} else {
if(num == 0) {
(*str).string = NULL;
for(i = 0; array[i] != '\0'; i++) {
(*str).string = realloc((void *)(*str).string, i + 1);
(*str).string[i] = array[i];
}
(*str).length = i;
} else {
(*str).string = (char *)malloc(num);
(*str).length = num;
for(i = 0; i < num; i++)
(*str).string[i] = array[i];
}
}
return str;
}
s_string *s_strcpy4(s_string *__restrict__ destination, const s_string *__restrict__ source) {
int i;
long long *_dest = (long long *)(destination->string),
*_sour = (long long *)(source->string);
for(i = 0; i < source->length - 8; i+=8)
_dest[i] = _sour[i];
for( ; i < source->length; i++)
destination->string[i] = source->string[i];
destination->length = i;
return destination;
}
_dest[i] = _sour[i];
should be
_dest[i/8] = _sour[i/8];
or something equivalent.
There are lots of other things wrong with the code. For example, on architectures that require properly aligned pointers, trying to access a group of eight characters that don't start on a multiple-of-eight address will cause a bus error.
I assume you are doing this as an exercise, and not to use in production. Just use memcpy()
size_t const LLsize = sizeof(long long);
for(i = 0; i < source->length / LLsize; ++i)
_dest[i] = _sour[i];
for( i = i*LLsize; i < source->length; ++i)
destination->string[i] = source->string[i];
I had my program printing out the words in a file and incrementing when they appeared more than once. I am now getting just "NULL" and the count as "17" instead. I can't find anything that I changed but am not sure if it is because I haven't figured out how to properly free up my arrays.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BASE 5
#define MAX 50
typedef char *string;
struct wordCount
{
string word;
unsigned int count;
};
int main (void)
{
unsigned int i;
unsigned int found;
unsigned int arraysize;
unsigned int newsize;
char temp [40];
struct wordCount* wordArray;
FILE *infile;
arraysize = 0;
infile = fopen("input.txt","r");
wordArray = malloc(BASE * sizeof(struct wordCount));
/*store in word from infile to struct, increment counter each time it appears*/
while (fscanf(infile, "%s", temp) == 1) {
found = 0;
for (i = 0; i < arraysize; i++){
if(strcmp(temp,wordArray[i].word) == 0){
wordArray[i].count++;
found++;
}
}
if (found== 0){
if (arraysize<BASE){
wordArray[arraysize].word = (char
*)malloc((strlen(temp)+1) * sizeof(char));
strcpy(wordArray[arraysize].word,temp);
wordArray[arraysize].count = 1;
arraysize++;
} else {
wordArray = realloc(wordArray, arraysize * sizeof(struct wordCount));
wordArray[arraysize].word = (char *)malloc((strlen(temp)+1) *
sizeof(char));
strcpy(wordArray[arraysize].word,temp);
wordArray[arraysize].count = 1;
arraysize++;
}
}
}
fclose(infile);
/*newsize = SearchAndDestroy(wordArray, arraysize); */
for (i = 0; i < arraysize; i++) {
printf("%s ", wordArray[arraysize].word);
printf("%d\n", wordArray[arraysize].count);
/*free(wordArray[i].word);*/
}
/* and when done:*/
free(wordArray);
return 0;
}
You aren't tracking things properly. You need to pay more attention to the fact that "How many words I have", "how many words I have room for", and "how many words I would like to have room for" are three distinct items that need to all be tracked separately. In particular, it doesn't look like your call to realloc() is correct.