0

I must write a function which gets 30 names without repeated names and after that it prints random on name of this 30. But when I run the program after my second name I entered, I get Segmentation fault and I don't know why. Cause when I put the first name every thing is good.

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

#define SIZE 30  /*The size of the array of names*/
#define MAX_L 21    /*The length of a name included  the ending 0*/
#define REPEAT 10 /*The amount of getting a random name in the names list */

char names[SIZE][MAX_L];/* = { 0 } ; /*Global array for the names we get from the users*/

/*Gives back a random name in an array nameslist*/
char * get_name(){
    int random; /*the random index we get of the names list*/
    char *r; /*the string name to return*/

    random= rand()%SIZE; /*picks a random number from 0-29 */
    r= names[random]; /*r points to the random name in the list*/
    return r;
}


/*Gets from user 30 names without repeat and calls after that function get_names 10 times*/
int  main(){
    int i;  /*counter for array names list */
    int j;  /*counter for array in the first inner loop to check if there are repeated names*/
    int k;  /*counter for the repeat loop for random names*/
    int w;  /*counter for the index of the character in the string */
    bool same = true; /*says if two strings are the same or not*/

    for (i=0; i< SIZE; i++){  /*Gets from the user 30 names and initialize them in the array*/
        printf("\nPlease enter a name (repeated names forbidden until we'll get to 30 names)\n");
        scanf("%s", names[i]);

       if (i>0){
       for (j=0; j<i; j++){  /*checks if is a repeated name or not*/
        for (w=0; w< MAX_L || same ==false; w++){
            if (names[i][w] != names[j][w]){
                    if (names[i][w] >= 'a' && names[i][w] <= 'z'){ 
                            if (names[i][w] - 32 != names[j][w]) 
                                same=false;}

                else if (names[i][w] >= 'A' && names[i][w] <= 'Z'){
                            if (names[i][w] + 32 != names[j][w]) 
                                same=false;}
            }
        }   
        if (same ==true){ /*repeated name*/
             printf("\nERROR! You already entered this name!");
             return 0;}     
       }}
       printf("\nThe name you entered is: %s\n", names[i]);
    }

    for (k=0; k<REPEAT; k++){ /*Calls the function get_name 10 times to get 10 random names from the array*/
        printf("\nThe random name you got from the list is: %s", get_name());
    }
    return 0;
}
5
  • 1
    "I get Segmentation fault and I don't know why". The way to try and find out why is to run your program in a debugger. Commented Dec 18, 2019 at 19:57
  • You are returning the address of a local variable at return r; Commented Dec 18, 2019 at 19:57
  • Not directly related to your problem, but comparing character by character is an inefficient way of comparing strings. Something like strcmp(toupper(names[i]), toupper(names[j])) would be faster and cleaner. Converting both names to upper case gets rid of the plus and minus 32 cases. Commented Dec 18, 2019 at 20:00
  • 1
    w< MAX_L || same ==false That looks pretty dangerous. The point of w<MAX_L is to ensure the array bounds are not exceeded. Adding || potentially removes that safety barrier. Commented Dec 18, 2019 at 20:01
  • 1
    And don't compare same to true or false. Just use if (same) or if( !same ). It is too easy to mistype the number of equal signs, creating an error that is usually very difficult to find. Commented Dec 18, 2019 at 20:10

1 Answer 1

1

Use gdb to debug your program.

All you need to do is:

  1. Compile your program with -g flag, e.g.: gcc -g -Wall main.c -o prog
  2. Launch gdb: gdb prog
  3. Set breakpoint(-s):
gdb) b 36
Breakpoint 
  1. Run your program: (gdb) r
  2. Use s to step by step debug and c to continue to next breakpoint

And you will easily discover the cause of your segmentation fault:

Program received signal SIGSEGV, Segmentation fault.
0x000055555555526f in main () at main.c:39
39                  if (names[i][w] != names[j][w]){

To see why exactly it segfaults you can print variables using p %variable name%:

(gdb) p i
$1 = 1
(gdb) p w
$2 = 139115
(gdb) p j
$3 = 0
(gdb) p same
$4 = false

So the cause is obvious: same ==false condition make your w variable overflow.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer! Just a question if I want make the code little bit easier with compare the string without bool and every single character in the compare section. How can I do it. I tried this code but didnt work. if (strlen(names[i]) == strlen(names[j])){ if (strcmp(toupper(names[i]), toupper(names[j]) == 0){ printf("\nERROR! You already entered this name!"); return 0; } }
if (strlen(names[i]) == strlen(names[j])){ if (strcmp(toupper(names[i]), toupper(names[j]) == 0){ printf("\nERROR! You already entered this name!"); return 0; } }
There are a lot of warnings for your updated code, check out toupper function, it's used for int variables, not for a string. By the way don't forget to mark my answer as accepted with ‎✓ sign.
Thanks Artem Bondar

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.