2

I am attempting to write a program that will take two sets of strings N and Q. The goal of the program is to print out the number of times each string in Q occurs in N. However, I am struggling to manage strings and pointers in C and in particular I believe my issue stems from attempting to have an array of strings. I get a segmentation fault when the code below is executed. I have commented out my attempts at debugging using printf(). I believe the issue occurs when I try to assign S into the N_array.

int main() {
    int N, Q; 
    char *N_array[1000], *Q_array[1000];

    scanf("%d", &N);

    for (int N_i = 0; N_i < N; N_i++) {
        //printf("made it through A for loop %d times\n", N_i+1);
        scanf("%s", N_array[N_i]);
    }

    scanf("%d", &Q);

    //Does the array contain any information?
    //for (int N_i = 0; N_i < N; N_i++) { printf("N_array[%d] == %d\n", N_i, N_array[N_i]);}

    for (int Q_i = 0; Q_i < Q; Q_i++) {
        //printf("Made it to B for loop\n");
        int occurs = 0, result;
        char s[21];
        scanf("%s", &s[21]);
        strcpy(Q_array[Q_i], s);
        for (int N_i2 = 0; N_i2 < N; N_i2++) {
            //printf("Made it to C for loop\n");
            result = strcmp(Q_array[Q_i], N_array[N_i2]);
            if (result == 0) occurs++;
        }
        printf("%d", occurs);
    }

    return 0;
} 
JG7
  • 371
  • 2
  • 10
  • remember that scanf won't read past a blank character in the string. also if you use scanf on a 20 character buffer then you should use scanf("%19s", ... ) so that you don't overflow the buffer. It is safer to use fgets (not gets) to read a whole line at a time. – bruceg Jan 08 '16 at 20:03

2 Answers2

6

One problem is here

for (int N_i = 0; N_i < N; N_i++) {
    //printf("made it through A for loop %d times\n", N_i+1);
    scanf("%s", N_array[N_i]);
}

N_Array contains 1000 pointers to char, but each of those pointers points to, well.. nowhere. It's an uninitialized pointer which points to a random memory location you don't own. This is undefined behavior. You have to allocate memory before scanf.

 N_Array[N_i] = malloc(max_length_of_string + 1);

Another problem is this line

 char s[21];
 scanf("%s", &s[21]);

The second parameter of scanf should be just s, not &s[21], which is just outside your array.

And one line below you have the same problem as described in my first point

strcpy(Q_array[Q_i], s);

Q_array[Q_i] doesn't yet point to any memory which you're allowed to write to. You should allocate memory here as well.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
3
  1. scanf("%s", N_array[N_i]);

    This should lead to SegFault as expected as N_array[N_i] doesn't contain a valid memory address.

    What you need is to allocate memory using malloc, calloc to point N_array[N_i] to a valid memory location.

Correct code would be:

for (int N_i = 0; N_i < N; N_i++)
{
    if(!(N_array[N_i] = malloc((MAX_STRING_LENGTH + 1) * sizeof(char))))
    {
        printf("malloc failed!\n);
        exit(1);
    } 
    scanf("%s", N_array[N_i]);
}

  1. scanf("%s", &s[21]);

    This is incorrect as %s expects char * but type of &s[21] is char **.

    You need to use scanf("%20s", s); instead.

    This way scanf only read at most 20 chars (as we have char s[21]. So leaving last byte for \0 character) and thus this will avoid accidental buffer overrun (where the length of string entered by user is greater than 20).


  1. strcpy(Q_array[Q_i], s);

    Again here Q_array[Q_i] points to invalid memory address as it contains garbage value. Use malloc, calloc etc. to allocate memory first.

Correct code could be:

if(!(Q_array[Q_i] = malloc((MAX_STRING_LENGTH + 1) * sizeof(char))))
{
    printf("malloc failed!\n);
    exit(1);
}
strcpy(Q_array[Q_i], s);  
rootkea
  • 1,474
  • 2
  • 12
  • 32