I have a program that reads the words of two files (the first a wordlist, and the second an ebook from the Gutenberg project ) into two char *arrays.
I am trying to add all the unique words from the second char *array that don't appear in
the first char *array into a third char *array then print them.
This program adds the correct words, but is adding them more than once.
The error occurs in findOdds().
Note when I use a non-binary search method this program works correctly, but takes a long time.
What is the problem with my program? I apologize for my English.
#include <stdio.h>
#include <stdlib.h> /* for malloc() */
#include <ctype.h>
#include <string.h>
#define MAXCHAR 24
#define MAXLINES 150000
int add2array(FILE *fp, char *lineptr[]);
int findOdds(char *lineptr[], char *lineptr1[], int nlines, int nlines1);
int binsearch1(char *val, char *lineptr[], int nlines);
char *lineptr2[MAXLINES]; /* The unique words not in the word list */
int main(int argc, char *argv[])
{
FILE *my_stream, *my_stream1;
char *lineptr[MAXLINES], *lineptr1[MAXLINES];
int i, nlines, nlines1, nlines2;
/* Load the wordlist. */
my_stream = fopen("words.txt","r");
if(my_stream == NULL) {
printf("error: Couldn't open file\n");
return 2;
} else {
nlines = add2array(my_stream, lineptr);
fclose(my_stream);
}
if(nlines==-1) {
printf("error: Epic Failure to copy words to char *lineptr[]\n");
return -1;
}
/* Load the ebook. */
my_stream1 = fopen("horsemanship.txt","r");
if(my_stream1 == NULL) {
printf("error: Couldn't open file\n");
return 2;
} else {
nlines1 = add2array(my_stream1, lineptr1);
fclose(my_stream1);
}
if(nlines1==-1) {
printf("error: Epic Failure to copy words to char *lineptr[]\n");
return -1;
}
/* Find and print the unique words from the ebook not in the wordlist */
nlines2 = findOdds(lineptr, lineptr1, nlines, nlines1);
for(i=0; i<nlines2; i++)
printf("%s\n",lineptr2[i]);
return 0;
}
/* add2array: read the words from the file into char *lineptr[] */
int add2array(FILE *fp, char *lineptr[])
{
int nlines=0, c=0, pos=0;
char temp[MAXCHAR];
char *p;
while((c = getc(fp)) != EOF) {
if(isalpha(c))
temp[pos++] = tolower(c);
else if(!isalpha(c)) {
temp[pos] = '\0';
pos = 0;
if(isalpha(temp[0])){
if((p = malloc(sizeof(temp)))==NULL)
return -1;
strcpy(p, temp);
lineptr[nlines++] = p;
}
}
}
return nlines;
}
/* Add the unique words from lineptr1 not in lineptr to lineptr2 */
int findOdds(char *lineptr[], char *lineptr1[], int nlines, int nlines1)
{
char *p;
char temp[MAXCHAR];
int i, nlines2=0;
for(i=0; i<nlines1; i++) {
if(binsearch1(lineptr1[i], lineptr, nlines)==-1) {
if(binsearch1(lineptr1[i], lineptr2, nlines2)==-1) {
if((p = malloc(sizeof(temp)))==NULL)
return -1;
strcpy(p, lineptr1[i]);
lineptr2[nlines2++] = p;
}
}
}
return nlines2;
}
int binsearch1(char *val, char *lineptr[], int nlines)
{
int pos;
int start = 0;
int end = nlines-1;
int cond = 0;
while(start <= end){
pos=(start + end)/2;
if((cond = strcmp(lineptr[pos],val)) == 0)
return pos;
else if(cond < 0)
start = pos+1;
else
end = pos-1;
}
return -1;
}
Arrays must be sorted if you want to use binary search, as stated above by n.m.
in main() ...
shellsort1(lineptr1, nlines1);
/* Find and print the unique words from the ebook not in the wordlist */
nlines2 = findOdds(lineptr, lineptr1, nlines, nlines1);
...
int shellsort1(char *v[], int n)
{
int gap, i, j;
char temp[MAXCHAR];
char *p;
for(gap=n/2; gap>0; gap/=2)
for(i=gap; i<n; i++)
for(j=i-gap; j>=0 && strcmp(v[j],v[j+gap])>0; j-=gap) {
if((p = malloc(sizeof(temp)))==NULL)
return -1;
p = v[j];
v[j] = v[j+gap];
v[j+gap] = p;
}
return 0;
}
Related
I am trying to read from file hw4.data and see if it has a name. The user inputs the name via a command line argument. Everything works fine but I can't get the file to be passed between the functions correctly. The assignment requires that I define the file in main and pass it between SCAN and LOAD.
#include <stdio.h>
#include <stdlib.h>
struct _data {
char name[20];
long number;
};
int SCAN(FILE *(*stream)) { // skim through the file and find how many entries there are
int size = 0;
char s_temp[100];
long l_temp;
while (1) {
fscanf(*stream, "%s %ld", s_temp, &l_temp);
if (feof(*stream)) break;
size++;
}
return size;
}
struct _data* LOAD(FILE *stream, int size) { // loop through the file and load the entries into the main data array
struct _data* d = malloc(size * sizeof(struct _data));
int i;
for (i = 0; i < size; i++) {
fscanf(stream, "%s %ld", d[i].name, &d[i].number);
}
return d;
}
void SEARCH(struct _data *BlackBox, char* name, int size) { // loop through the array and search for the right name
int i;
int found = 0;
for (i = 0; i < size; i++) {
printf("%s %s\n", BlackBox[i].name, name);
if (strcmp(BlackBox[i].name, name) == 0) {
printf("*******************************************\nThe name was found at the %d entry.\n*******************************************\n", i);
found = 1;
break;
}
}
if (found == 0) {
printf("*******************************************\nThe name was NOT found.\n*******************************************\n");
}
}
void FREE(struct _data* BlackBox, int size) { // free up the dynamic array
free(BlackBox);
}
int main(int argv, char* argc[]) {
if (argv == 2) {
printf("The argument supplied is %s\n", argc[1]);
FILE* file = fopen("./hw4.data", "r");
int size = SCAN(&file);
struct _data* data = LOAD(&file, size);
SEARCH(data, argc[1], size);
fclose(file);
return 0;
} else {
printf("*******************************************\n* You must include a name to search for.*\n*******************************************\n");
return 0;
}
}
Here's the format of hw4.data
ron 7774013
jon 7774014
tom 7774015
won 7774016
A few issues:
In SCAN, remove the feof. Replace with: if (fscanf(*stream, "%s %ld", s_temp, &l_temp) != 2) break;
Note that after calling SCAN, you should do: rewind(file);. Otherwise, LOAD will only see [immediate] EOF.
And, as others have mentioned, just pass file to SCAN/LOAD and not &file.
Add a check for null return from fopen (e.g.) if (file == NULL) { perror("fopen"); exit(1); }
Stylistically:
If you have a comment describing a function, put it on the line above the function.
Try to keep lines within 80 chars
Here is the refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _data {
char name[20];
long number;
};
// skim through the file and find how many entries there are
int
SCAN(FILE *stream)
{
int size = 0;
char s_temp[100];
long l_temp;
while (1) {
if (fscanf(stream, "%s %ld", s_temp, &l_temp) != 2)
break;
size++;
}
return size;
}
// loop through the file and load the entries into the main data array
struct _data *
LOAD(FILE *stream, int size)
{
struct _data *d = malloc(size * sizeof(struct _data));
int i;
for (i = 0; i < size; i++) {
fscanf(stream, "%s %ld", d[i].name, &d[i].number);
}
return d;
}
// loop through the array and search for the right name
void
SEARCH(struct _data *BlackBox, char *name, int size)
{
int i;
int found = 0;
for (i = 0; i < size; i++) {
printf("%s %s\n", BlackBox[i].name, name);
if (strcmp(BlackBox[i].name, name) == 0) {
printf("*******************************************\n");
printf("The name was found at the %d entry.\n", i);
printf("*******************************************\n");
found = 1;
break;
}
}
if (found == 0)
printf("*******************************************\n"
"The name was NOT found.\n"
"*******************************************\n");
}
// free up the dynamic array
void
FREE(struct _data *BlackBox, int size)
{
free(BlackBox);
}
int
main(int argv, char *argc[])
{
if (argv == 2) {
printf("The argument supplied is %s\n", argc[1]);
FILE *file = fopen("./hw4.data", "r");
if (file == NULL) {
perror("fopen");
exit(1);
}
int size = SCAN(file);
rewind(file);
struct _data *data = LOAD(file, size);
SEARCH(data, argc[1], size);
fclose(file);
}
else
printf("*******************************************\n"
"* You must include a name to search for.*\n"
"*******************************************\n");
return 0;
}
Using realloc, we can combine SCAN and LOAD into a single function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _data {
char name[20];
long number;
};
// loop through the file and load the entries into the main data array
struct _data *
LOAD(FILE *stream, int *sizep)
{
struct _data *all = NULL;
struct _data *d;
int size = 0;
int capacity = 0;
while (1) {
if (size >= capacity) {
capacity += 10;
all = realloc(all,sizeof(*all) * capacity);
if (all == NULL) {
perror("realloc");
exit(1);
}
}
d = &all[size++];
if (fscanf(stream, "%s %ld", d->name, &d->number) != 2)
break;
}
// trim to size actually used
all = realloc(all,sizeof(*all) * size);
*sizep = size;
return all;
}
// loop through the array and search for the right name
void
SEARCH(struct _data *BlackBox, char *name, int size)
{
int i;
int found = 0;
for (i = 0; i < size; i++) {
printf("%s %s\n", BlackBox[i].name, name);
if (strcmp(BlackBox[i].name, name) == 0) {
printf("*******************************************\n");
printf("The name was found at the %d entry.\n", i);
printf("*******************************************\n");
found = 1;
break;
}
}
if (found == 0)
printf("*******************************************\n"
"The name was NOT found.\n"
"*******************************************\n");
}
// free up the dynamic array
void
FREE(struct _data *BlackBox, int size)
{
free(BlackBox);
}
int
main(int argv, char *argc[])
{
if (argv == 2) {
printf("The argument supplied is %s\n", argc[1]);
FILE *file = fopen("./hw4.data", "r");
if (file == NULL) {
perror("fopen");
exit(1);
}
int size;
struct _data *data = LOAD(file, &size);
SEARCH(data, argc[1], size);
fclose(file);
}
else
printf("*******************************************\n"
"* You must include a name to search for.*\n"
"*******************************************\n");
return 0;
}
I had to use rewind() in order to reset the file so that LOAD() would read from the start of the file and give good data.
I have a C program that will count the amount of words in each file given on the command line. I now need to make it count how many times each word appears. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define MAXWORDS 10000
#define MAXSTRING 100
/* structure holding word frequency information */
typedef struct _word {
char s[MAXSTRING]; /* the word */
int count; /* number of times word occurs */
} word;
static int *total_amount_of_words;
int countWords(FILE *file){
int count = 0;
char character;
while((character = fgetc(file)) != EOF){
if(character == '\n' || character == ' ')
count++;
}
return count;
}
void insert_word (word *words, int *n, char *s) {
int i;
/* linear search for the word */
for (i=0; i<*n; i++) if (strcmp (s, words[i].s) == 0) {
/* found it? increment and return. */
words[i].count++;
return;
}
/* error conditions... */
if (strlen (s) >= MAXSTRING) {
fprintf (stderr, "word too long!\n");
exit (1);
}
if (*n >= MAXWORDS) {
fprintf (stderr, "too many words!\n");
exit (1);
}
/* copy the word into the structure at the first available slot,
* i.e., *n
*/
strcpy (words[*n].s, s);
/* this word has occured once up to now, so count = 1 */
words[*n].count = 1;
/* one more word */
(*n)++;
}
int wordcmp (word *a, word *b) {
if (a->count < b->count) return +1;
if (a->count > b->count) return -1;
return 0;
}
/* return 1 if c is alphabetic (a..z or A..Z), 0 otherwise */
int is_alpha (char c) {
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') return 1;
return 0;
}
void remove_char (char *s, int i) {
while (s[i]) {
i++;
s[i-1] = s[i];
}
s[i] = 0;
}
void remove_non_alpha (char *s) {
int i;
for (i=0; s[i]; i++) if (!is_alpha (s[i])) remove_char (s, i);
}
void make_lowercase (char *s) {
int i;
for (i=0; s[i]; i++) s[i] = tolower (s[i]);
}
int main(int argc, char *argv[])
{
word words[MAXWORDS];
char s[1000];
int i, j, n, m;
int pid;
FILE *current_file;
n = 0;
total_amount_of_words = mmap(NULL, sizeof *total_amount_of_words, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//Create processes for each file on the command line
for(i = 1; i < argc; i++)
{
pid = fork();
if(pid == -1) //Error
{
exit(-1);
}
else if(pid == 0) //Children
{
current_file = fopen(argv[i], "r");
int current_word_amount = countWords(current_file);
*total_amount_of_words += current_word_amount;
printf("Child Process for File %s: number of words is: %i\n", argv[i], current_word_amount);
rewind(current_file);
/* read all the words in the file... */
while (!feof (current_file)) {
fscanf (current_file, "%s", s);
/* only insert the word if it's not punctuation */
if (is_alpha (s[0])) {
/* get rid of non-letters */
remove_non_alpha (s);
/* make all letters lowercase */
make_lowercase (s);
/* put this word in the list */
insert_word (words, &n, s);
}
}
fclose(current_file);
exit(0);
}
else //Parent
{
wait(NULL);
}
}
/* sort the list of words by descending frequency */
qsort((void *) words, n, sizeof (word),
(int (*) (const void *, const void *)) wordcmp);
/* print the words with their frequencies */
for (j=0; j<*total_amount_of_words; j++){
printf ("Word: %s\t", words[j].s);
printf ("Frequency: %%d\n", words[j].count);
}
printf("All %i files have been counted!\n Total Amount of Words: %d\n", (argc-1), *total_amount_of_words);
munmap(total_amount_of_words, sizeof *total_amount_of_words);
}
In the for loop at the bottom I cannot get it to print out each word and how many times it appeared. I cannot get anything to output, the struct need gets initialized. How do I share the struct with all processes?
I'm writing a program that takes a file with the 3 lines of encrypted passwords and compares them to all 4 lower case letters from aaaa - zzzz. The only issue I am having is that I can't figure out how to go line by line of the file I input and how to compare it to the 4 letter words individually. It should then print the 3 decrypted 4 letter words that correlate to the passwords from the file. Also if there are any types on how to improve my code, please let me know. I'm a beginner at this so I need clear explanations and examples if possible. Thank you.
EDIT*****
The main problem is in the all function and main. I'm not wanting to print the aaaa, aaab, aaac, etc to the screen but I want to put it in an char array so that i can compare each individually to each line from the file using crypt. So I need advice on how to put all 456976 combinations into an array, compare it to each line of code, and print the solutions to the screen.
file looks like this:
$1$6gMKIopE$I.zkP2EvrXHDmApzYoV.B.
$1$pkMKIcvE$WQfqzTNmcQr7fqsNq7K2p0
$1$0lMKIuvE$7mOnlu6RZ/cUFRBidK7PK.
My code looks like this:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int my_fgets(char* buf, int len, int f)
{
for (int i = 0; i < len; i++,buf++)
{
int count = read(f, buf, 1);
if (!count || (buf[0] == '\n'))
{
buf[0] = 0;
return i;
}
}
return 0;
}
int inc(char *c,char begin, char end){
if(c[0]==0)
return 0;
if(c[0] == end){ // This make the algorithm to stop at char 'f'
c[0]=begin; // but you can put any other char
return inc(c+sizeof(char), begin, end);
}
c[0]++;
return 1;
}
char all(int a, int n,char begin, char end){
int i, j;
char *c = malloc((n+1)*sizeof(char));
char result[] = "";
for(i = a; i <= n; i++)
{
for(j=0;j<i;j++) c[j]=begin;
c[i]=0;
do {
int k = sizeof(result);
for (int g = 0; g < k -1; g++)
{
result[g] = c;
}
} while(inc(c,begin,end));
}
free(c);
}
int main(int argc, char* argv[])
{
char *result;
char let[456976];
int f = open("pass.txt", O_RDONLY);
if (f < 0)
return 0;
char buf[1024];
while (my_fgets(buf, sizeof(buf), f))
{
let = all(4,4,'a','z');
int i = 0;
result = crypt((let[i+1]), buf);
int ok = strcmp (result, pass) == 0;
return ok ? 0 : 1;
all(4, 4, 'a', 'z');
}
close(f);
}
I think you need to reword the question. Maybe the code below is what you want. Let's say you have a password, and you have a file which contains a list of encrypted passwords (or hash usually), you want to see if password is right or wrong. You compare the hash of the password with hashes in the file. I haven't tested this code.
ps, let me know if I am way off, I'll delete the answer.
void crypt(char* hash, const char* password_test) {
//create hash from password, or encrypt it or something?
}
int test_password(const char *filename, const char *password){
FILE *f;
f = fopen(filename, "r");
if (!f) return 0;
char password_hash[256];
crypt(password_hash, password);
char hash[256];
char buf[1024];
while (fgets(buf, sizeof(buf), f) != NULL)
{
crypt(hash, buf);
if (strcmp(password_hash, hash) == 0)
return 1;
}
fclose(f);
return 0;
}
void main() {
int result = test_password("test.txt", "password");
if (result == 1)
printf("password is good\n");
}
Reading line by line using open/read/close
int my_fgets(char* buf, int len, int f)
{
for (int i = 0; i < len; i++,buf++)
{
int count = read(f, buf, 1);
if (!count || (buf[0] == '\n'))
{
buf[0] = 0;
return i;
}
}
return 0;
}
int main(){
int f = open("test.txt", O_RDONLY);
if (f < 0) return 0;
char buf[1024];
while (my_fgets(buf, sizeof(buf), f))
printf("%s\n", buf);
close(f);
}
Hi guys I am in the second weekend of trying to find the solution to this problem. I am new at c programming and I have been trying to read each individual line of a text file and pass each of them to their own variable, where I will be able to manipulate them(such as compare them, do calculations etc).
I have a code to read each individual lines but I am unsure how to pass each line to a variable, here is the code:
#include <stdlib.h>
#include <stdio.h>
struct line_reader {
FILE *f;
char *buf;
size_t siz;
};
void
lr_init(struct line_reader *lr, FILE *f)
{
lr->f = f;
lr->buf = NULL;
lr->siz = 0;
}
char *
next_line(struct line_reader *lr, size_t *len)
{
size_t newsiz;
int c;
char *newbuf;
*len = 0;
for (;;) {
c = fgetc(lr->f);
if (ferror(lr->f))
return NULL;
if (c == EOF) {
if (*len == 0)
return NULL;
else
return lr->buf;
} else {
if (*len == lr->siz) {
newsiz = lr->siz + 4096;
newbuf = realloc(lr->buf, newsiz);
if (newbuf == NULL)
return NULL;
lr->buf = newbuf;
lr->siz = newsiz;
}
lr->buf[(*len)++] = c;
if (c == '\n')
return lr->buf;
}
}
}
void
lr_free(struct line_reader *lr)
{
free(lr->buf);
lr->buf = NULL;
lr->siz = 0;
}
int
main()
{
struct line_reader lr;
FILE *f;
size_t len;
char *line;
f = fopen("file.txt", "r");
if (f == NULL) {
perror("foobar.txt");
exit(1);
}
lr_init(&lr, f);
while (line = next_line(&lr, &len)) {
fputs("1: ", stdout);
fwrite(line, len, 1, stdout);
}
if (!feof(f)) {
perror("next_line");
exit(1);
}
lr_free(&lr);
return 0;
}
Any help would be appreciated.
What about using an array simply as a suggestion
e.g.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** readFile(const char *filename, size_t *lineCount){
FILE *fp;
char buff[4096];
size_t lines = 0, capacity=1024;
char **line;
if(NULL==(fp=fopen(filename, "r"))){
perror("file can't open.");
return NULL;
}
if(NULL==(line=(char**)malloc(sizeof(char*)*capacity))){
perror("can't memory allocate.");
fclose(fp);
return NULL;
}
while(NULL!=fgets(buff, sizeof(buff), fp)){
line[lines++] = strdup(buff);
if(lines == capacity){
capacity += 32;
if(NULL==(line=(char**)realloc(line, sizeof(char*)*capacity))){
perror("can't memory allocate.");
fclose(fp);
return NULL;
}
}
}
*lineCount = lines;
fclose(fp);
return (char**)realloc(line, sizeof(char*)*lines);
}
void freeMem(char** p, size_t size){
size_t i;
if(p==NULL) return;
for(i=0;i<size;++i)
free(p[i]);
free(p);
}
int main(){
size_t lines;
char **line;
if(NULL!=(line=readFile("file.txt", &lines))){//lines: set line count of file
printf("%s", line[25]);// 26th line of file, zero origin
}
freeMem(line, lines);
return 0;
}
On any POSIX-compliant system just use the m scan modifier:
for ( char *line, nl; scanf("%m[^\n]%c",&line,&nl) != EOF ; free(line) ) {
if ( !line )
strcpy(line=malloc(1),""), getchar();
// ...
}
m has been in the standard for five years now.
// Struct for Country Data
typedef struct
{
char name[50]; // Country name
char code[3]; // Country code
int population; // Country Population
double lifeExp; // Country Life expectancy
} CountryData;
// Struct for Dir File
typedef struct
{
char code[50];
int offSet;
} DirData;
// Function Declarations
void fillCountryStructs(CountryData **dataPtr, int nLines, int fd);
void fillDirectoryStructs(CountryData **dataPtr, DirData **director, int nLines,int fd2);
void sortStructs(DirData **director, int nLines);
int verifyString(char *s1, char *s2);
// Main Function
// - This function starts the program, get the number of lines as a
// parameter, fills the structs and writes the data to the Country
// File and the Directory file.
int main(int argc, char *argv[]) // Always remember to pass an argument while executing
{
// Some variables
int nLines; // The number of lines
char *pEnd; // For String functions
FILE *Fin,*Fout; // File pointers
int fd;
int fd2;
nLines = strtod(argv[1], &pEnd);
CountryData **countryDataPtr; // Array of structs
CountryData **tempStruct;
DirData **director;
char buffer[15];
// Allocate memory for the struct pointers
countryDataPtr = calloc(nLines, sizeof(CountryData*));
director = calloc(nLines, sizeof(DirData*));
// File Stream for "AllCountries.dat"
if((fd = open("AllCountries.dat", O_RDWR|O_CREAT)) ==-1)
err_sys("File not found...\n");
// File Stream for "RandomStruct.bin"
if ((fd2 = open("RandomStruct.bin",O_RDWR|O_CREAT)) == -1)
err_sys("Failed to open binary\n");
// Filling the Country stucts
fillCountryStructs(countryDataPtr, nLines, fd);
close (fd);
//fclose(Fin); // Closing the file "AllCountries.dat"
// Writing Binary File
write(fd2, (countryDataPtr[0]->name[0]), sizeof(CountryData));
int c=0;
int n=0;
int counter=0;
int tempn=0;
for (c=0;c<nLines;c++)
{
write(fd2, (countryDataPtr[c]->name),50);
write(fd2, (countryDataPtr[c]->code),4);
sprintf(buffer, "%d", countryDataPtr[c]->population); // Function from String.h
n = strlen(buffer);
write(fd2, buffer, n);
if (n<15)
{
for (counter=0;counter<(15-n);counter++)
{
write(fd2," ",1);
}
}
//printf("n: %i n-15: %i\n",n,(15-n));
//sprintf(buffer, "%0.1f", countryDataPtr[c]->lifeExp); // Function from String.h
//n=((int)(countryDataPtr[c]->lifeExp));
tempn=((int)(countryDataPtr[c]->lifeExp));
sprintf(buffer, "%d", tempn); // Function from String.h
n = strlen(buffer);
write(fd2, buffer,n);
write(fd2,"\n",1);
}
close (fd2);
printf("prueba\n");
//fclose(Fout);
printf("RandomStruct.bin written Sucessfully\n");
// Filling the Directory File
// File Stream for "RandomStructDir.dir"
if ((fd2 = open("RandomStructDir.dir",O_RDWR|O_TRUNC)) != -1)
err_sys("Failed to open binary\n");
printf("holla0\n");
fillDirectoryStructs(countryDataPtr, director, nLines, fd2);
printf("holla\n");
sortStructs(director, nLines); // Sorting the structs
printf("holla2\n");
// Write the number of lines in the FIRST LINE
// of the Directory File
write(fd2, &nLines, sizeof nLines);
// Writing Directory File after the number of lines was written
//write(fd2,(director[0]->code[0]), sizeof(DirData));
for (c=0;c<nLines;c++)
{
write(fd2, (director[c]->code),4);
}
close (fd2);
//fclose(Fout);
printf("RandomStructDir.dir written Sucessfully\n\n");
exit(0);
}
// Filling the Country structs
// - This function extracts the data from the file using strtok
// and fills all the structs with their corresponding values.
void fillCountryStructs(CountryData **dataPtr, int nLines, int fd)
{
int curLine = 0; // Current line
int index = 0; // The index
char buf[BUFSIZE]; // The Buffer with the size of BUFSIZE
char *tok; // Token
char *pEnd; // For the String functions
char ch = 'a'; // The temp character
int temPop;
double temLifeExp;
int num=0;
for(curLine = 0; curLine < nLines; curLine++)
{
// Reading each line
dataPtr[curLine] = (CountryData *)calloc(1, sizeof(CountryData));
index = 0;
do
{
read(fd, &ch, 1);
buf[index++] = ch;
}
while(ch != '\n');
// Strtoking...
tok = strtok(buf, ",\n");
index = 1;
while(tok != NULL)
{
tok = strtok(NULL, ",\n");
// Get the Country Code
if(index == 1)
{
strcpy(dataPtr[curLine]->code, tok); // Copying code to the struct
//write(fd2, (tok), sizeof(CountryData[0]));
}
// Get the Country Name
if(index == 2)
{
strcpy(dataPtr[curLine]->name, tok); // Copying name to the struct
//write(fd2, (tok), sizeof(CountryData));
}
// Get the Country Population
if(index == 7)
{
temPop = (int)strtol(tok, &pEnd, 10);
dataPtr[curLine]->population = temPop; // Copying population to the struct
}
// Get the Country Life expectancy
if(index == 8)
{
num=countchar(tok);
printf ("The number of characters entered is %d\n", num);
printf ("The character entered is %s\n",tok);
temLifeExp = strtod(tok, &pEnd);
dataPtr[curLine]->lifeExp = temLifeExp; // Copying life expectancy to the struct
}
index++;
}
}
}
int countchar (char list[])
{
int i, count = 0;
for (i = 0; list[i] != '\0'; i++)
count++;
return (count);
}
// Filling the Directory Structs
// - This function fills the directory with the offset
void fillDirectoryStructs(CountryData **dataPtr, DirData **director, int nLines, int fd2)
{
int i = 0;
for(i = 0; i < nLines; i++)
{
strcpy(director[i]->code, dataPtr[i]->code); //It crashes in this Line
director[i]->offSet = 72 * (i);
}
}
// Sorting the Dir Structs
// - This function sorts the Directory Structs.
void sortStructs(DirData **director, int nLines)
{
int maxNumber;
int i;
DirData **temp;
temp = calloc(1, sizeof(DirData*));
// Sorting the array of pointers!
for(maxNumber = nLines - 1; maxNumber > 0; maxNumber--)
{
for(i = 0; i < maxNumber; i++)
{
if((verifyString(director[i]->code, director[i+1]->code)) == 1)
{
temp[0] = director[i];
director[i] = director[i+1];
director[i+1] = temp[0];
}
}
}
}
// Veryfying the strings
// - This function compares two strings and return a specific value
// accordingly.
int verifyString(char *s1, char *s2)
{
int i;
if(strcmp(s1,s2) == 0)
return(0); // They are equal
for(i = 0; s1[i] != 0; i++)
{
if(s1[i] > s2[i])
return(1); // s1 is greater
else if(s1[i] < s2[i])
return(2); // s2 is greater
}
return (2); // s2 is greater
}
So this is my code for some reason, when I call this method it crashes:
void fillDirectoryStructs(CountryData **dataPtr, DirData **director, int nLines, int fd2) ...
The exact line where it crashes:
strcpy(director[i]->code, dataPtr[i]->code); <-here
It must be something about pointers or I don't know, I'm trying to copy what is on the right side to the struct in the left side. I print dataPtr[0]->code and it shows the right value.
strcpy(director[i]->code, dataPtr[i]->code); //It crashes in this Line
At this point, director[i] doesn't point to anything. You need a director[i] = calloc(... line just like in fillCountryStructs.