0

I am trying to input a file into a two-dimensional array but I am getting a seg fault when trying to find the max line length and the max number of lines. The seg fault occurs in the function checkSpelling. I have tried using gdb to see where the seg fault occurs but I am getting that it exits right away which I don't completely understand. My code is below. Any help is greatly appreciated.

#define MAX 1000000

struct TData{
    char **pChar;
};

int checkSpelling(const char *input, const char *dict, struct TData *pInput, struct TData *pDictionary);
int searchReplace(const char *input, const char *dict, struct TData *pInput, struct TData *pDictionary);
int save(const char *input, const char *output);

int main (int argc, char **argv){
    struct TData input, dictionary, output;
    int choice = 0;

    if(argc != 4){
            printf("Not enough input arguments in the command line.\n");
            exit(1);
    }

    do{
            printf("Menu\n");
            printf("1. Check the spelling for the file using the dictionary.\n");
            printf("2. Search and replace a given string in the inputed file.\n");
            printf("3. Save the modified file to the output file.\n");
            printf("4. Exit the program.\n");
            scanf("%d", &choice);

            switch(choice){
                    case 1:
                            checkSpelling(argv[1], argv[3], &input, &dictionary);
                            break;
                    case 2:
                            searchReplace(argv[1], argv[3], &input, &dictionary);
                            break;
                    case 3:
                            save(argv[1],argv[2]);
                            break;
                    case 4:
                            choice = 4;
                            break;
                    default:
                            printf("Input is invalid");
                            break;
            }
    }while (choice != 4);
return 0;
}

int checkSpelling(const char *input, const char *dicto, struct TData *pInput, struct TData *pDictionary){

    FILE *inputFile;
    FILE *dictFile;
    int i = 0, j = 0, k = 0, l = 0, m = 0;
    char temp[60], dicttemp[60];
    int rowCount = 0, charCount = 0;

    printf("Checking the spelling of the inputed file.\n");
    printf("Opening the inputed file...\n");
    if((inputFile = fopen(input, "rt")) == NULL){
            printf("Cannot open file\n");
            exit(1);
    }

    printf("Opening the dictonary...\n");
    if((dictFile = fopen(dicto, "rt")) == NULL){
            printf("Cannot open dictionary\n");
            exit(1);
    }

    while(!feof(inputFile)){
            if(pInput->pChar[i][j] == '\n'){
                    rowCount++;
            }
    }
    rewind(inputFile);

    pInput->pChar[i][j] = 0;

    while(pInput->pChar[i][j] != '\n'){
            charCount++;
    }
    rewind(inputFile);

    printf("Lines: %d, Max line length: %d", rowCount, charCount);

    fclose(inputFile);
    fclose(dictFile);

    printf("\n");
return 0;
}
sarah
  • 59
  • 1
  • 5
  • 2
    You didn't initialize the `struct TData input` variable before of inside CheckSpelling, so it is pointing to god-knows-where when you access`pInput->pChar[i][j]`. – Jefferson Apr 01 '19 at 22:44
  • Yes I did. Look at the first couple lines of main – sarah Apr 01 '19 at 22:46
  • 2
    You created the variable, but didn't assign it to anything. Could you point the line it happens otherwise? – Jefferson Apr 01 '19 at 22:48
  • Is it not assigning pointer to a struct within the function checkSpelling? – sarah Apr 01 '19 at 22:53
  • 1
    The problem is that `pInput` doesn't point to a valid, allocated memory block, so `pInput->pChar[i][j] == '\n'` will normally cause a crash since you're comparing against a junk memory area. You need to read a line from `inputfile` into a temp buffer that has been allocated on the stack, and then allocate some memory for `pInput` to use. – bruceg Apr 01 '19 at 22:54
  • Rather, `pInput` does point to a valid allocated memory block (namely the `input` variable in `main`), but it is never initialized, so it contains garbage. In particular, within `main`, you need to initialize `input.pChar` to point to something. – Nate Eldredge Apr 01 '19 at 22:56
  • 1
    Not really the issue, but it is kind of confusing that `input` is the name of a variable within `main`, as well as of an unrelated argument in the function `checkSpelling`, and so it's hard to keep straight which one we're talking about. Perhaps you could rename one of them for the purposes of this question? – Nate Eldredge Apr 01 '19 at 22:58
  • the posted code does not compile! please correct so it cleanly compiles, then repost. Amongst many other problems, it is missing the needed `#include` statements for the needed header files – user3629249 Apr 03 '19 at 03:57
  • OT: for ease of readability and understanding: 1) consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces, (not tabs) 2) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* – user3629249 Apr 03 '19 at 04:01
  • OT regarding: `printf("Not enough input arguments in the command line.\n");` Error messages should be output to `stderr`, not `stdout` and when the error is about the wrong number of command line arguments, should output a `USAGE` message, similar to: `fprintf( stderr, "USAGE %s \n", argv[0] );` – user3629249 Apr 03 '19 at 04:04
  • OT: regarding: `scanf("%d", &choice);` When calling any of the `scanf()` family of functions, always check the returned value (not the parameter values) to assure the operation was successful. In this case suggest: `if( scanf("%d", &choice) != 1 ) { handle error then call `exit( EXIT_FAILURE ); }` – user3629249 Apr 03 '19 at 04:06
  • regarding: `struct TData input, dictionary, output;` these pointers to struct `TData` are not set to point to anything useful, so contain what every trash happens to be on the stack where they are declared – user3629249 Apr 03 '19 at 04:09
  • OT: regarding: `int i = 0, j = 0, k = 0, l = 0, m = 0;` for readability and understanding, do not use single character variable names. They are meaningless, even in the current context – user3629249 Apr 03 '19 at 04:12
  • regarding: `char temp[60], dicttemp[60]` the posted code contains some 'magic' numbers, like 60. 'magic' numbers are numbers with no basis. 'magic' numbers make the code much more difficult to understand, debug, etc. Suggest using a `enum` statement or `#define` statements to give those 'magic' numbers meaningful names, then use those meaningful names throughout the code. – user3629249 Apr 03 '19 at 04:15
  • OT: regarding; `printf("Cannot open file\n");` When a C library function (in this case `fopen()`) indicates an error occurred, always output both your error message and the text reason the system thinks the error occurred to `stderr`. The function: `perror()` is made for that purpose – user3629249 Apr 03 '19 at 04:17
  • to help avoid sloppy code, before calling `exit()` always clean up. I.E. close open files, close sockets, pass allocated memory to `free()`, etc – user3629249 Apr 03 '19 at 04:19
  • regarding: `while(!feof(inputFile)){` 1) the EOF condition is not being updated in that code block. 2) [why while(!feof( file )) is never correct](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) – user3629249 Apr 03 '19 at 04:22
  • regarding: `while(pInput->pChar[i][j] != '\n'){ charCount++; }` This code block does not step through the char array: `pChar[][]` so will never exit unless the very first char in the array is '\n' – user3629249 Apr 03 '19 at 04:24

1 Answers1

1

Here is a small code that exemplifies the task

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

#define MAX_LENGTH 1000

int main()
{
    FILE *fp;
    char line[MAX_LENGTH];
    size_t n_rows, n_cols, length;

    fp = fopen("myfile.txt", "r");

    n_cols = 0;
    n_rows = 0;
    while (fgets(line, MAX_LENGTH, fp) != NULL) {
        n_rows++;
        length = strlen(line);
        if (length > n_cols)
            n_cols = length;
    }

    fclose(fp);

    /* the number of lines is in n_rows and the max line length is in n_cols
    do whatever you want with them */

    return 0;
}
hpc
  • 41
  • 4
  • 1
    I'm not sure that this new version is helpful for OP to understand what is wrong with her code. – Nate Eldredge Apr 01 '19 at 23:30
  • Any implementation must have at least these steps. I wrote a short version with educational purpose. The code is not safe enough to be copied and pasted for production.. – hpc Apr 01 '19 at 23:48