Search code examples
cfor-loopc-stringspalindromefunction-definition

segmentation fault, c programm


I had to write a program in c as a homework assignment. The program checks if the inputed string is a palindrome. Unfortunately I am getting a segmentation fault error when executing my program.

According to my knowledge segmentation fault means I am accessing memory that does not belong to me.

After some trying I found out, that I get that error "during" the marked scanf function. Please help.

This is the source-code:

#include <stdio.h>
#include <ctype.h>

#define FALSE 0
#define TRUE !FALSE

#define STR_LEN01 1000

unsigned long long fStrLen(unsigned char str[])
{
    unsigned long long strLEN = 0;
    for (unsigned short i = 0; str[i++]; strLEN++) {}
    return strLEN;
}

unsigned short fStrComp(unsigned char str01[], unsigned char str02[])
{
    for (unsigned short i = 0; /* EMPTY */ ; i++)
    {
        if ( str01[i] == 0 && str02[i] == 0 ) 
            { return 0; }
        else if ( str01[i] != str02[i] && str02[i] == 0 ) 
            { return 1; }
        else if ( str01[i] != str02[i] && str01[i] == 0 ) 
            { return 2; }
        else if ( str01[i] != str02[i] && str02[i] != 0 && str01[i] != 0) 
            { return 3; }
    }
}
// ret 0 = strings are equal
// ret 1 = string 1 is longer
// ret 2 = string 2 is longer
// ret 3 = strings are not equal

void fStrRev(unsigned char str[])
{
    unsigned short len = fStrLen(str);
    unsigned char helpi, helpj;

    for (unsigned short i = len-1, j = 0; i >= 0; i--, j++)
    {
        helpi = str[i];
        helpj = str[j];

        str[i] = helpj;
        str[j] = helpi;

    }

} // ATTENTION! Inputted string will be reversed!

unsigned short fPalindrome(unsigned char str[]) // TODO
{
    unsigned char rev[STR_LEN01];

    for (unsigned short i = 0; str[i]; i++)
    {
        rev[i] = str[i];
    }
    fStrRev(str);

    return fStrComp(str, rev);   
} 
// ret 0 = palindrome
// *ret 1 = string 1 is longer*
// *ret 2 = string 2 is longer*
// ret 3 = strings are not equal, so no palindrome

int main(void)
{
    unsigned short ret = 0;
    unsigned char strIN01[STR_LEN01], strREV01[STR_LEN01], exit[] = "end";

    while(TRUE)
    {
        printf("\n\n"
                "Your word: ");


        scanf(" %s", strIN01); ***// MARKED SCANF***


        for (unsigned short i = 0; strIN01[i]; i++) 
        { putchar( tolower( strIN01[i] ) ); }

        if(fStrComp(strIN01, exit) == 0) { return 0; }

        for (unsigned int i = 0; strIN01[i]; i++)
        {
            strREV01[i] = strIN01[i];
        }
        strREV01[ fStrLen(strIN01) ] = 0;
        fStrRev(strREV01);
        printf("word reversed: %s", strREV01);

        ret = fPalindrome(strIN01);

        if(ret == 0)
        {
            printf("Hurray! We have a palindrome :)\r\n");
        }
        else if(ret == 3)
        {
            printf("Unfortunately, your word is no palindrome :(\r\n");
        }
    }

    return 0;
}

This is the Shell error:

    └─$ gcc -Wall palindrom.c -o pal -lm                                                                                
    └─$ ./pal                           


    Your word: hello    
    zsh: segmentation fault  ./pal

    └─$ 

Thank you for your help in advance.

Yours Faithfully, Tiger

PS The functions were tested by me separately while programming and should work


Solution

  • the for loop in fStrRev is what's causing you segmentation fault

    for (unsigned short i = len-1, j = 0; i >= 0; i--, j++)
    {
        helpi = str[i];
        helpj = str[j];
    
        str[i] = helpj;
        str[j] = helpi;
    }
    

    i gets decremented by one each cycle and the cycle continues until i is less than 0, the problem is that when i get decremented from 0 it becomes 65535 instead of -1 as i is an unsigned short causing the for loop to continue and your seg fault when it tries to access str[65535] to fix this just change the for loop from unsigned short to short or another signed integer type if you need the extra range like so.

    for (short i = len-1, j = 0; i >= 0; i--, j++)
    {
        helpi = str[i];
        helpj = str[j];
    
        str[i] = helpj;
        str[j] = helpi;
    }
    

    There's also another problem with your code as it's not working as intended for reversing the word and reversing it twice, so the comparison should be changed from i >= 0 to i >= len/2 or what Ian Abbott commented if you're going with his solution