Zuzana Zuzana - 20 days ago 11
C Question

Segmentation fault in C while using getchar()

I am writing a program that can read letters and it gives to them values

2^n
, so
a=2^0
,
b=2^1
....
z=2^25
and then I sum them. Somewhere in the input must be
|
and I count letters before and letter after it separately -
sum[0]=
before
|
,
sum[1]=
after
|
. When I type
aeoifha|shzs
, everything is OK, but when I type
|abc
or
abc|
, it gives me Segmentation fault, but I need it to tell me it is
sum[0]=0
and
sum[1]=7
for
|abc
or
sum[0]=7
and
sum[1]=0
for
abc|
. If there is just
|
, it is Wrong. The output is really Wrong, but it also gives me Segmentation fault.

Here is the code:

const int table[] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432};
const char *a_z = "abcdefghijklmnopqrstuvwxyz";
long long int sum[2] = {0};
int ch, count = 0;

for(;;)
{
if(!islower(ch = getchar()))
{
if(ch == '\n' && sum[0] && sum[1])
break;
else if(ch == EOF)
{
printf("Wrong.\n");
}
else if(ch == '|' && sum[0] != 0 && count == 0)
{
count = 1;
continue;
}
printf("Wrong.\n");
sum[0] = sum[1] = count = 0;
while(ch != '\n' && (ch=getchar())!=EOF && ch != '\n')
continue;
}
sum[count] += table[strchr(a_z, ch) - a_z];
}


Any idea how to get rid of the fault and how to give sum[]=0?

Answer

Before updating the sum[count], you don't have checked if the strchr(a_z, ch) is not NULL, meaning that ch is not an expected 'a'...'z' character.

After entering "abc|" and pressing 'Return' key, an additional '\n' = 0x0A is parsed but not filtered by if(ch == '\n' && sum[0] && sum[1]) break; because sum[1] is equal to 0.

First modification: (Stop even when left or right is missing)

But, to prevent a missing '|', the break-condition shall be true only when count = 1 (equal '|' detection).

    if(!islower(ch = getchar()))
    {
        if(ch == '\n' && (sum[0] || sum[1]) && (count == 1))

Instead of

    if(!islower(ch = getchar()))
    {
        if(ch == '\n' && sum[0] && sum[1])

Second modification (force to switch to count=1 even left is missing):

        else if(ch == '|' && count == 0)
        {
            count = 1;

Instead of

        else if(ch == '|' && sum[0] != 0 && count == 0)
        {
            count = 1;

And to prevent unexpected ch value, filter before:

    if (strchr(a_z, ch)!=NULL) { // only 'a' to 'z' characters
        sum[count] += table[strchr(a_z, ch) - a_z];
    }