-1

I have tried everything I know but I just can't create the array. Every time the terminal shows "Segmentation fault: 11". Please help, thanks!(details in my comments)

Updated: char*load file(int *numberofwords)returns reading from txt file(I made it up just to test how my program works):

Have,a.nice day

Bye.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char *loadfile(int *counter) {
    int  i;
    char chr;
    char *data;
    char *junk;
    FILE *GENE;
    GENE = fopen("hw7codex.txt", "r");

    if (GENE == NULL) {
       printf("ERROR - Could not open file.\n");
       return NULL; 
    }


   while (1) {
      fscanf(GENE, "%s", junk);
      (*counter)++;
      if (feof(GENE)) break;
   }

   int wholecounter = 0;
   while (1) {
      fscanf(GENE, "%c", &chr);
      wholecounter++;
     if (feof(GENE)) break;
   }

   data = (char *)calloc(wholecounter, sizeof(char));
      if (data == NULL) {
        printf("ERROR - Could not allocate memory for the file.\n");
        return NULL;
   }

   rewind(GENE);
   i = 0;
   while (1) {
       fscanf(GENE, "%c", &chr);
       data[i++] = chr;
       if (feof(GENE)) break;
   }
   fclose(GENE);

   return data;
}






int main(void){

int wordscount=0;

char *temp;

//temp gets a long string from a txt file(which looks like
//"Have,a.nice day"then divides it to separate words:"Have","a", "nice","day"
temp = strtok(loadfile(&wordscount)," ,.\n"); 

//I want to know how many separate words in this txt file
printf("%s\n", loadfile(&wordscount));  //it prints out 5
printf("%d\n", wordscount);       //it prints out 'Have,a.nice day\nBye'


//I want to create a string array here to hold all those words , but I keep failing
char array[wordscount][40];

int j=0;
while (temp != NULL){
    strcpy(array[j], temp);
    j++;
    temp = strtok (NULL, " ,.\n");
    }


for (j = 0; j < wordscount; j++){
   printf("%s\n", array[j]);
    }
  • Where is the declaration of `array`? – jmstoker Apr 01 '14 at 01:05
  • you added a space in variable `words count`. – Deduplicator Apr 01 '14 at 01:06
  • @jmstoker, that's the problem, I wrote something like `array[wordscount][40]` or `char *array; array = (char*)malloc(sizeof(char))` doesn't work. Terminal shows **Segmentation fault: 11** – user3226666 Apr 01 '14 at 01:08
  • also, you probably want to reserve space for your string, before you copy it there. maybe use `strdup()` instead. If you don't have it, define it. it's easy. – Deduplicator Apr 01 '14 at 01:08
  • Add to your post the code for the array declaration you're using that gives the seg fault – jmstoker Apr 01 '14 at 01:10
  • use `char ** array;`, and dynamically allocate all your strings and the array itself. Use `realloc()` for that. – Deduplicator Apr 01 '14 at 01:11
  • In order to define a static/auto array, use `char array[MAXSTRINGLENGTH][MAXSTRINGCOUNT]`. – Deduplicator Apr 01 '14 at 01:12
  • @Deduplicator, I think it should be `char array[MAXSTRINGCOUNT][MAXSTRINGLENGTH]`? That doesn't work anyway – user3226666 Apr 01 '14 at 01:16
  • try it out, i so seldom use 2 dimensional static arrays... – Deduplicator Apr 01 '14 at 01:18
  • First, initialize `j` to 0 before using it as the answer below says. – jfly Apr 01 '14 at 01:22
  • Your program crashes before `printf("%d\n", wordscount);` or after? – jfly Apr 01 '14 at 01:29
  • @jfly, after. As long as I try to declare `array`. – user3226666 Apr 01 '14 at 01:35
  • `char array[wordscount][40];` is illegal if your compiler don't support VLA. You need to declare an array of pointers, then allocate memory manually. – jfly Apr 01 '14 at 01:40
  • @jfly,thx! but I tried `char *array;`then `array = malloc(sizeof(char)*wordscount);`. It doesn't work – user3226666 Apr 01 '14 at 01:46
  • no, you **only** declare one pointer by `char *array`, see my answer. – jfly Apr 01 '14 at 01:47
  • Use `char**` as i said. One * too few. Also, `sizeof(char)` shows how green you are, forget about it fast: "How many char comprise a char?" Tautology is not concise. – Deduplicator Apr 01 '14 at 01:48
  • 1
    It surprises me that no-one has asked to see the code for `loadfile()`. I'd also be happier if you captured the return value from it into a variable, and then dumped the data it returns before doing anything else with it (such as shredding it with `strtok()`). I know what you say it contains, but you've not shown the data file nor exactly what it looks like when returned by `loadfile()`. – Jonathan Leffler Apr 01 '14 at 01:51

3 Answers3

0

char array[wordscount][40]; is illegal if your compiler doesn't support VLA. You should declare an array of pointers that point to strings, then allocate memory manually:

char** array;
int i;
array = (char**)malloc(wordscount * sizeof(char*)); // 

for ( i = 0; i < wordscount; i++) {
    array[i] = (char*)malloc(40 * sizeof(char)); // make sure the length of every word is less than 40
}; 

EDIT:
if the loadfile() return what you write(don't know how you implement the loadfile(), you should allocate memory for the string in the function), and the wordscount is 5, then here is an example for you which works fine:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void){

    int wordscount = 5;

    char *temp;
    char buf[128] = "Have,a.nice day\nBye";

    temp = strtok(buf, " ,.\n"); 

    char** array;
    int i;
    array = (char**)malloc(wordscount * sizeof(char*)); // 

    for ( i = 0; i < wordscount; i++) {
        array[i] = (char*)malloc(40 * sizeof(char)); // make sure the length of every word is less than 40
    }; 

    int j = 0;
    while (temp != NULL){
        strcpy(array[j], temp);
        j++;
        temp = strtok (NULL, " ,.\n");
    }

    for (j = 0; j < wordscount; j++){
        printf("%s\n", array[j]);
    }
}

In your loadfile(), junk is an uninitialized pointer, so this line: fscanf(GENE, "%s", junk); will cause undefined behavior.

jfly
  • 7,715
  • 3
  • 35
  • 65
  • Hm, don't remodel your code halfway. Do or don't do, there is no try, yoda spoke. – Deduplicator Apr 01 '14 at 01:50
  • thank you but this only holds one word. What I want is to hold `words count` words – user3226666 Apr 01 '14 at 01:55
  • It does allocate space for `wordscount` words. Check the value of `wordscount` after the function `loadfile()`, and show us the string to be parsed. – jfly Apr 01 '14 at 02:03
  • print the return value of `loadfile()`, and the value of `wordscount`. – jfly Apr 01 '14 at 02:14
  • @jfly, I did print these 2 – user3226666 Apr 01 '14 at 02:17
  • So what are they like? – jfly Apr 01 '14 at 02:24
  • `printf("%s\n", loadfile(&wordscount));` //it prints out 5 `printf("%d\n", wordscount); ` //it prints out 'Have,a.nice day\nBye' – user3226666 Apr 01 '14 at 02:25
  • If so, I guess the `loadfile()` is the problem. You allocated the memory for the string to be parsed in the `loadfile()`? Edited the answer. – jfly Apr 01 '14 at 02:35
  • Your code sample is not correct, you declare an array of `40` pointers but then iterate up to `wordsCount`. If this count is over `40` then you have a buffer overflow. – M.M Apr 01 '14 at 04:51
  • @user3226666 In your loadfile(), `junk` is an uninitialized pointer, so this line: `fscanf(GENE, "%s", junk);` will cause undefined behavior. And the `counter` in it is not accurate. – jfly Apr 01 '14 at 05:13
0

You char *loadfile(int *counter) seems buggy because you used while (1) {} for reading file and break the loop by if (feof(GENE)) break; but feof it self buggy see here

Also you missed rewind(GENE); between first two while..loop. Add it.

So you can do as follows

   while (fscanf(GENE, "%s", junk)==1) // The scanf functions return the number of objects read.
   {
      (*counter)++;
   }

similar you apply for other loop.

This is the code error i captured form your loadfile function but still i don't know what you expect from return value of loadfile and what output you want?

Community
  • 1
  • 1
Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73
0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DELIMITER " ,.\n"

const char *LoadFile = "data.txt";

char *loadfile(int *wc){
    FILE *fp = fopen(LoadFile, "r");
    if(!fp){
        perror("fopen");
        return NULL;
    }
    long fsize = 0;

    fseek(fp,0,SEEK_END);
    fsize = ftell(fp);//non portable
    fseek(fp,0,SEEK_SET);//reset stream position!!

    char *buff = malloc(fsize+1);
    if(!buff){
        perror("malloc");
        return NULL;
    }
    size_t rsize = fread(buff, sizeof(char), fsize, fp);
    fclose(fp);
    buff[rsize]='\0';

    int count = 0, pos = 0;//long ?
    while(1){
        int len = 0;
        sscanf(buff + pos, "%*[" DELIMITER "]%n", &len);
        pos += len;
        if(EOF!=sscanf(buff + pos, "%*[^" DELIMITER "]%n", &len)){
            pos +=len;
            ++count;
        } else {
            break;
        }
    }
    *wc = count;
    return buff;
}

int main(void){
    int wordscount=0;
    char *buff, *temp;

    buff = loadfile(&wordscount);
    printf("%d\n", wordscount);  

    char array[wordscount][40];

    temp = strtok(buff, DELIMITER);
    int j;
    for(j = 0; temp != NULL; ++j){
        strcpy(array[j], temp);
        temp = strtok (NULL, DELIMITER);
    }
    free(buff);
    for (j = 0; j < wordscount; j++){
        printf("%s\n", array[j]);
    }
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70