0
#include<stdio.h>

#include<stdlib.h>

int main() {
    FILE * fp;
    fp = fopen("lets.txt", "r");
    int vowels = 0, constants = 0, spaces = 0, tabs = 0, specsym = 0, nolines = 1;
    int c;

    while ((c = fgetc(fp)) != EOF) {
        if (c == 65 || c == 69 || c == 73 || c == 70 || c == 85 || c == 97 || c == 101 || c == 105 || c == 111 || c == 117) {
            vowels++;

        } else if (c == 32) {
            spaces++;
        } else if ((33 <= c <= 47) || (58 <= c <= 64) || (91 <= c <= 96) || (123 <= c <= 126)) {
            specsym++;
        } else if ((65 <= c <= 90) || (97 <= c <= 122)) {
            constants++;

        }
    }

    rewind(fp);
    char c1;
    while ((c1 = fgetc(fp)) != EOF) {
        if (c1 == '\n') {
            nolines++;
        } else if (c1 == '\t') {
            tabs++;
        }
    }
    printf("The number of vowels are %d , constants %d, spaces %d, tabs %d, special symbols %d and lines %d", vowels, constants, spaces, tabs, specsym, nolines);
}

In the code below everything else is working fine other than the number of special symbols and characters, as you can see in the code they have completely different values to check for , but yet special symbols is counting characters too.If i put characters above it, it counts special symbols too.`

  • 5
    ```char c1; while ((c1 = fgetc)```---> but ```fgetc``` returns an ```int```. – Harith Jan 22 '23 at 18:52
  • 4
    Expressions such as `58 <= c <= 64` don't do what you think they do. You would need to write this as `58 <= c && c <= 64`. Also turn on compiler warnings and pay attention to them – Paul R Jan 22 '23 at 18:53
  • 2
    ```fp = fopen("lets.txt", "r");``` ---> Further operations try to read from ```NULL``` if ```fopen``` failed. Check its return code. It returns ```NULL``` on failure. – Harith Jan 22 '23 at 18:53
  • 1
    You can at least use [`toupper`](https://man7.org/linux/man-pages/man3/toupper.3.html) or `tolower` to cut your number of checks in half. – yano Jan 22 '23 at 19:01
  • *Aside:* No need to go through the file twice. Check for ```'\n'``` and ```'\t'``` along with the rest. – Harith Jan 22 '23 at 19:08
  • 1
    According to the [rules on operator precedence and associativity](https://en.cppreference.com/w/c/language/operator_precedence), the expression `(33 <= c <= 47)` is equivalent to `( ( 33 <= c ) <= 47 )`. Since the sub-expression `( 33 <= c )` can only evaluate to `0` (false) or `1` (true), the entire expression is equivalent to either `( 0 <= 47 )` or `( 1 <= 47 )`, so the entire expression is always true. This is not what you want. You need to write something like `(33 <= c && c <= 47)` instead. – Andreas Wenzel Jan 22 '23 at 19:08
  • Make it easier on yourself, and later readers! You can write `if (c == 'A' || c == 'E' || c == 'I' || …) vowels++;` instead. – Steve Summit Jan 22 '23 at 19:51
  • @SteveSummit I attempted a similar comment, but the OP tests the *range* of other alphabet characters, which would need significant changes to the code. Only the digit characters `'0'` to `'9'` are guaranteed to be consecutive and in order. Aside: when can we let go of EBCDIC? C23 already mandates 2's complement for integers. – Weather Vane Jan 22 '23 at 20:04
  • @WeatherVane I know what you mean, but the OP has made the choice of character set pretty clear already! Although, a pointer to `isalpha` wouldn't be amiss, either. (Personally, I have entirely let go of EBCDIC, and I would have very few qualms about writing code that quietly assumed 26 contiguous letter.) – Steve Summit Jan 22 '23 at 20:09
  • @SteveSummit I suppose a robust rejection of EBCDIC would test for non-ASCII character coding. – Weather Vane Jan 22 '23 at 20:16

0 Answers0