0

I am writing a C program that's supposed to take a char array and then count all the lowercase letters in it, all the uppercase letters in it as well as all the vowels. For some reason though, it's not running because the compiler returns a segmentation fault. I don't know what it is and I don't know where the problem is


#include <stdio.h>
int lccount(char x[10]){
    int count=0,i,j;
    char lowalphabet[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    for(i=0;i<=10;i++){
        for(j=0;j<=26;j++){
            if(x[i]==lowalphabet[j]){
                count++;
            }
        }
    }
return count;}
int uccount(char x[10]){
    int count=0,i,j;
    char upalphabet[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
    for(i=0;i<=10;i++){
        for(j=0;j<=26;j++){
            if(x[i]==upalphabet[j]){
                count++;
            }
        }
    }
return count;}
int vcount(char x[10]){
    int count=0,i,j;
    char vowels[]={'a','e','i','o','u','A','E','I','O','U'};
    for(i=0;i<=20;i++){
        for(j=0;j<=10;j++){
            if(x[i]==vowels[j]){
                count++;
            }
        }
    }
return count;
}
void main(){
    char x[10]={'a','W','E','R','s','d','a','e','i','A'};
    int v,uc,lc;
    v=vcount(x[]);
    uc=uccount(x[]);
    lc=lccount(x[]);
    printf("%d vowels\n%d uppercase\n%dlowercase",v,uc,lc);
}

Result => segmentation fault

SalTheFish
  • 13
  • 5
  • 2
    `for(j=0;j<=26;j++){` this requires an array of 27 elements. Imagine a simpler situation - array of size 2: `'a', 'b'`. this loop `for(j=0;j<=2;j++)` would require 3 though: 0, 1 and 2. Since index 2 does not exist there - you get a segfault. – fukanchik Jan 16 '23 at 12:27
  • The syntax to pass an array is `v=vcount(x);`. You current syntax `v=vcount(x[]);` is invalid. – Serge Ballesta Jan 16 '23 at 12:30
  • 2
    Your code doesn't compile, please post the _actual_ code you compile and run. – Jabberwocky Jan 16 '23 at 12:30
  • @Jabberwocky It's not valid in GCC but I think it compiles on the MSVS compiler. – TheNomad Jan 16 '23 at 12:32
  • 1
    @TheNomad I don't know what the MSVS compiler is but it definitely doesn't compile with the MSVC (compiler shipped with Microsoft Visual Studio). – Jabberwocky Jan 16 '23 at 12:33
  • BTW you should delete that uppercase count loop and just do it with ASCII value, that will save you a lot of time. – PIRIQITI Jan 16 '23 at 12:34
  • 2
    MSVS - MS Visual Studio :) I don't say MSVC as it's often attributed to MS Visual Code lately. – TheNomad Jan 16 '23 at 12:34
  • `for(i=0;i<=20;i++){`You define `char x[10]` in parameter list. The size in parameter list does not really have an effect but it looks like some logic error of the range doesn't match. – Gerhardh Jan 16 '23 at 12:44
  • `for(j=0;j<=10;j++){` Your array `vowels` only has 10 elements. You are accessing it beyonds its end. Generally your loop conditions should use `<` instead of `<=` – Gerhardh Jan 16 '23 at 12:45

2 Answers2

0

First of all, your main() signature is non-standard. Secondly, you pass arrays as params only with their identifiers.

int main(int argc, char *argv[])
{
    char x[10]={'a','W','E','R','s','d','a','e','i','A'};
    int v,uc,lc;
    v=vcount(x);
    uc=uccount(x);
    lc=lccount(x);
    printf("%d vowels\n%d uppercase\n%dlowercase",v,uc,lc);
    return 0;
}

Keep in mind there are a lot of other problems in your code. For example the fact it shows 8 lowercase when in fact there are 6. Check the comments the others posted in your question regarding loops as a hint to fix it.

TheNomad
  • 892
  • 5
  • 6
  • 3
    And what about the off by one error in the for loops? And the `for(i=0;i<=20;i++)` which is off by more than one.... – Jabberwocky Jan 16 '23 at 12:33
  • 1
    His question was about running the code, he didn't ask to fix all errors. I assume he can fix the loops himself since you guys already pointed them out. I did mention that in closing, but I'll do it explicitly. – TheNomad Jan 16 '23 at 12:35
  • 3
    THey pretend it segfaults, but a non compiling program can't run letg alone segfault.... – Jabberwocky Jan 16 '23 at 12:36
  • After changing the signature and the array passing it worked. AFAIK silver platter answers are if they are really at a dead-end and I think the OP has all the info they need to fix the counters too. Although, I would prolly rewrite it from scratch since it has a ton of redundant code. – TheNomad Jan 16 '23 at 12:37
  • Thanks! I didn't notice the errors until they were pointed out to me. – SalTheFish Jan 16 '23 at 13:59
  • 1
    @SalTheFish, if this solved your question, wouldn't it be nice to mark the answer as accepted? – trincot Jun 19 '23 at 08:01
0

As others pointed out in the comments, your code has a buffer overflow. Arrays in C are indexed starting from 0, which means that, if you have an array of (say) 26 characters, the first character is at position 0, the second at position 1, ..., the ith at position i-1, the 26th at position 25:

for (int i = 0; i < 25; ++i)
    ...

And you don't pass a string to a function with [].

Also, your main() declaration is not correct. It should be either one of these:

  1. int main(int argc, const char *argv[]) if you use arguments from the command line, or
  2. int main(void) otherwise.

There are a couple of things you can do to improve your code:

  • You can avoid allocating an array of chars and the nested for loop if you compare the ith character with its ASCII code.
  • You can pass the size of the array/string you want to process as a function argument.
  • Always use const when you don't modify your data.
int lccount(const size_t size, const char x[size])
{
    int count = 0;

    for (size_t i = 0; i < size; ++i)
        if (x[i] >= 'a' && x[i] <= 'z')
            ++count;
    
    return count;
}

int uccount(const size_t size, const char x[size])
{
    int count = 0;

    for (size_t i = 0; i < size; ++i)
        if (x[i] >= 'A' && x[i] <= 'Z')
            ++count;
    
    return count;
}

int vcount(const size_t size, const char x[size])
{
    int count = 0;
    for (size_t i = 0; i < size; ++i)
        switch (x[i]) {
        case 'a': case 'A':
        case 'e': case 'E':
        case 'i': case 'I':
        case 'o': case 'O':
        case 'u': case 'U':
            ++count;
            break;
        default: continue;
        }
    
    return count;
}

int main(void) // Since you don't use argc and argv
{
    char x[10] = {'a', 'W', 'E', 'R', 's', 'd', 'a', 'e', 'i', 'A'};
    const size_t size = sizeof(x) / sizeof(x[0]);

    int v = vcount(size, x);
    int uc = uccount(size, x);
    int lc = lccount(size, x);

    printf("%d vowels\n%d uppercase\n%d lowercase",v, uc, lc);
}

Result:

6 vowels
4 uppercase
6 lowercase
Zakk
  • 1,935
  • 1
  • 6
  • 17
  • Thanks for the help as well as the amendments you suggested, I just have a small question regarding inputting the size of the array as an argument. I read your code and I don't understand how size affects the code. Really sorry I'm new to programming. – SalTheFish Jan 16 '23 at 13:55
  • Don't think of a programming language or anything specific, think conceptually. You have a bag of a size. What happens if you put more objects in your bag then the bag allows? The bag will rip and won't be usable anymore, right? Now, imagine in code. You have an area in memory allocated to you. In your area you can "take" a chunk and allocate it to a buffer (for example an array, an object, a drawing, a file, anything - as said, don't think of specific programming languages). Let's say you have a buffer of 1 MB for a file. What happens if you put a file that is 2 MB in a buffer of 1? – TheNomad Jan 16 '23 at 14:14
  • Also, I have one more question. Why are you using pre increments here instead of post increments, does it affect the efficiency or quality of the program? – SalTheFish Jan 16 '23 at 14:14
  • @SalTheFish https://stackoverflow.com/q/16869020/16835308 – Zakk Jan 16 '23 at 14:39