Thread: How can I improve/shorten my C code?

  1. #1
    Registered User
    Join Date
    Oct 2020
    Posts
    19

    Cool How can I improve/shorten my C code?

    Hi everyone,

    I'm still new to C, coming from a Python background, and I was wondering if you could suggest any ways to improve/shorten my code. It's for a first-year university assignment, but I've already got it working and golfed it a bit on my own. Here it is:

    Code:
    #include<stdio.h>
    #include <ctype.h>
    int main(void) {
      char c = '\0';
      int vowelCount = 0, conCount = 0;
      while (c != '0') {
        puts("\nPlease enter a letter: ");
        scanf(" %c", &c);
        if (isalpha(c) || c == '0') {
          switch (tolower(c)) {
            case '0':
              puts("\nThank you for counting on me.");
              continue;
            case 'a':
            case 'e':
            case 'i':
            case 'o':
            case 'u':
              vowelCount++;
              for (int i = 0; i < vowelCount; i++) {
                putchar('*');
              }
              break;
            default:
              conCount++;
              for (int i = 0; i < conCount; i++) {
                putchar('!');
              }
            }
        }
        else {
          puts("\nAny character not in the English alphabet is not an accepted input for this application.\n");
        }
      }
    
    }
    
    Any comments welcome!

  2. #2
    Registered User
    Join Date
    Sep 2020
    Posts
    424
    To me, it looks pretty good.

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    If you want to go to extremes for improving then add booleans called isVowel and isDigit, use them like this:
    Code:
    c = tolower(c);
    isDigit = (c >= '0' & c <= '9');
    isVowel = (c == 'a' | c == 'e' | c == 'i' | c == 'o' | c == 'u' );
    vowelCount +=  isVowel;
    if ( isDigit )
      puts("...");
    else if ( !isVowel )
    {
      conCount++;
      // Your loop
    }
    For further extremes do it in ASM and utilise the MUL instruction to set and address to goto when a statement is false to and then use the GOTO instruction I think to goto to that address or 0 (next address), 0 for continue into the "if" block, address for skip the block, it basically is a hack of sorts for removing the slowest part of code, branch instructions (used by if/else if/switch/case statements)

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    On the other hand, if you want to be a software engineer who may one day develop software -- for other people to use and be paid for your work -- in teams with membership that can vary over time while remaining maintainable, then you would have a more balanced consideration for what constitutes "improvement" rather than having a singular focus on efficiency as the sole metric (though there was no mention of measurement) for what is good in software.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by awsdert View Post
    If you want to go to extremes for improving then add booleans called isVowel and isDigit, use them like this:
    Code:
    c = tolower(c);
    isDigit = (c >= '0' & c <= '9');
    isVowel = (c == 'a' | c == 'e' | c == 'i' | c == 'o' | c == 'u' );
    vowelCount +=  isVowel;
    if ( isDigit )
      puts("...");
    else if ( !isVowel )
    {
      conCount++;
      // Your loop
    }
    For further extremes do it in ASM and utilise the MUL instruction to set and address to goto when a statement is false to and then use the GOTO instruction I think to goto to that address or 0 (next address), 0 for continue into the "if" block, address for skip the block, it basically is a hack of sorts for removing the slowest part of code, branch instructions (used by if/else if/switch/case statements)
    a) Why are you using bitwise OR?
    b) Parenthesis where they're not required could, arguably, be regarded as clutter
    c) I have no idea what you're talking about regarding the MUL, GOTO is. Further, removing branch instructions?! What for? To remove the slowest part of the code? This is premature optimisation on steroids and would make the code an unreadable and unmaintainable mess. There is no need to avoid branch/eliminate instructions. wow. Obfuscating code by doing stuff like avoiding branches will more than likely get in the way of the compiler's optimiser and maybe (or even likely when you take things to such extremes) result in SLOWER code, not faster

  6. #6
    Registered User
    Join Date
    Sep 2020
    Posts
    424
    Oh, the origial poster might want to consider using getchar() rather than scanf() to get a character at a time.

    If you do continue to use scanf() you should also be testing the return value to check that it did actually read something, and act appropriately if it didn't.

  7. #7
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Hodor View Post
    a) Why are you using bitwise OR?
    b) Parenthesis where they're not required could, arguably, be regarded as clutter
    c) I have no idea what you're talking about regarding the MUL, GOTO is. Further, removing branch instructions?! What for? To remove the slowest part of the code? This is premature optimisation on steroids and would make the code an unreadable and unmaintainable mess. There is no need to avoid branch/eliminate instructions. wow. Obfuscating code by doing stuff like avoiding branches will more than likely get in the way of the compiler's optimiser and maybe (or even likely when you take things to such extremes) result in SLOWER code, not faster
    a) so the comiller doesn't try to sneak in branches for the sake of that expression
    b) That's a POV thing, I prefer the brackets
    c) MUL & GOTO are ASM instructions, not C language, I take it you haven't dabbled much if at all in ASM

  8. #8
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by laserlight View Post
    On the other hand, if you want to be a software engineer who may one day develop software -- for other people to use and be paid for your work -- in teams with membership that can vary over time while remaining maintainable, then you would have a more balanced consideration for what constitutes "improvement" rather than having a singular focus on efficiency as the sole metric (though there was no mention of measurement) for what is good in software.
    Part of why I said "extremes", anyways for the code I gave as long as one understands what the operations do (which any decent engineer should) then it only takes an extra second or 2 to understand what it's doing which when programming is an acceptable delay

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Any decent engineer would point out that applying "basically is a hack of sorts for removing the slowest part of code, branch instructions" misses the forest for the trees: the slowest part of the code is the interactive I/O for getting the user to input one character at a time, but because of how the feedback is given to the user, it may be infeasible to change it without going back to the drawing board of what the program is supposed to do. Yet, this means that optimisations to try and avoid branching in the processing code likely have no observable effect at all to even the most observant of human users.

    (And then for the sake of correctness rather than efficiency, the case could be made that the program should discard or treat as an input error additional characters supplied following each prompt, even though processing multiple characters at a time would be more efficient and could even make for better UX.)
    Last edited by laserlight; 10-02-2020 at 06:52 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by awsdert View Post
    a) so the comiller doesn't try to sneak in branches for the sake of that expression
    b) That's a POV thing, I prefer the brackets
    c) MUL & GOTO are ASM instructions, not C language, I take it you haven't dabbled much if at all in ASM
    a) Using bitwise OR the way you used it there is broken (it won't work... seriously)
    b) Yep, fair enough. I and many others find them annoying
    c) GOTO is not an ASM instruction. I take it that you haven't dabbled in ASM. Even if GOTO *was* an ASM instruction it's a branch

  11. #11
    Registered User
    Join Date
    Oct 2020
    Posts
    19
    Quote Originally Posted by Hodor View Post
    a) Using bitwise OR the way you used it there is broken (it won't work... seriously)
    b) Yep, fair enough. I and many others find them annoying
    c) GOTO is not an ASM instruction. I take it that you haven't dabbled in ASM. Even if GOTO *was* an ASM instruction it's a branch
    Perhaps I'm mistaken, but it looks to me like goto is indeed an ASM instruction. I was always told to avoid goto in C because it was too "Assembly-ish".

  12. #12
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    @awsdert Up front: I don't care if I get banned from here because of what I am about to say. I'm going to say it because I think it's important.

    Stop showing code that is plainly incorrect, please. First, your use of bitwise OR (|) is dumb and incorrect. Second, even if it was correct it'd be obfuscated and that's not good. The correct expression should be using boolean OR (||).

    Moving on from that brain fart you shouldn't be encouraging people to do sht like "utilise the MUL instruction to set and address to goto when a statement is false to and then use the GOTO instruction". That's just dumb and makes no sense at all. The whole sentence doesn't make sense. The OP should be writing readable code and not worrying about nonsense of the type you suggest (the OP is doing just fine).

    as long as one understands what the operations do (which any decent engineer should) then it only takes an extra second or 2 to understand what it's doing which when programming is an acceptable delay
    Well, I don't understand your dribble. I don't care about delays in this instance either. What do you mean my delay? The delay it takes me to parse your shtty code? You're just making stuff up. A decent engineer would write readable code and not waffle on about some bulsht weird crap that no programmer has ever suggested apart from you
    Last edited by Hodor; 10-02-2020 at 07:56 AM.

  13. #13
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by C-UL8R View Post
    Perhaps I'm mistaken, but it looks to me like goto is indeed an ASM instruction. I was always told to avoid goto in C because it was too "Assembly-ish".

    It's just a branch. Writing in assembly the mnemonic has never (as far as I know) been "goto"; the example you give is a "C'ificiation"; it'll compile to an ASM branch instruction (which, yeah, are GOTOs but they're not called that in ASM)

  14. #14
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Hodor View Post
    Stop showing code that is plainly incorrect, please. First, your use of bitwise OR (|) is dumb and incorrect. Second, even if it was correct it'd be obfuscated and that's not good. The correct expression should be using boolean OR (||).
    It's not that is "incorrect", but using a bitwise OR that way he's forcing to every single expression to be evaluated, breaking the "short circuit" just to avoid some conditional branches. AND, if you take a look at optimized machine code geneted by the compiler, it makes no difference:

    Code:
    ; Assembly created by GCC, on Linux, for x86-64 mode, with '-O2 -mtune=native' options turned on.
    
    ; int f( char a )
    ; { return ( a == 'a' | a == 'e' | a == 'i' | a == 'o' | a == 'u' ); }
    f:
      lea ecx,[rdi-97]
      xor eax,eax
      cmp cl,20
      ja  .L1
      mov eax,1065233
      shr rax,cl
      and eax,1
    .L1:
      ret
    
    ; int g( char a )
    ; { return ( a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u' ); }
    g:
      lea ecx,[rdi-97]
      xor eax,eax
      cmp cl,20
      ja  .L5
      mov eax,1065233
      shr rax,cl
      and eax,1
    .L5:
      ret
    
    ; int h( char a )
    ; { return ( a >= '9' & a <= '9' ); }
    h:
      sub edi,'0'
      xor eax,eax
      cmp dil,9
      setbe al
      ret
    
    ; int i( char a )
    ; { return ( a >= '9' && a <= '9' ); }
    i:
      sub edi,'0'
      xor eax,eax
      cmp dil,9
      setbe al
      ret
    Quote Originally Posted by Hodor
    ... "utilise the MUL instruction to set and address to goto when a statement is false to and then use the GOTO instruction". ... and makes no sense at all...
    I agree. This makes no sense.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by Hodor
    First, your use of bitwise OR (|) is dumb and incorrect. Second, even if it was correct it'd be obfuscated and that's not good.
    It is correct though since the result of the comparison operators is always 0 or 1, just semantically... unusual and hence obfuscated, and if someone thinks that they can freely replace || and && except for short-circuiting, they could get bitten when the operands aren't strictly 0 or 1.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help me shorten this code plz.
    By oblisgr in forum C Programming
    Replies: 3
    Last Post: 07-09-2020, 12:12 AM
  2. HOw can I shorten my code?
    By kdushyant297 in forum C Programming
    Replies: 1
    Last Post: 09-15-2017, 10:40 AM
  3. Making a function to shorten my code?
    By evilcubed in forum C Programming
    Replies: 8
    Last Post: 12-08-2012, 11:46 AM
  4. help to shorten my code.
    By hugoguan in forum C Programming
    Replies: 7
    Last Post: 12-01-2010, 02:19 AM
  5. Need to simplify/shorten this code. Help.
    By Lonck in forum C++ Programming
    Replies: 5
    Last Post: 11-08-2007, 04:23 AM

Tags for this Thread