Search code examples
cuppercase

How to convert a string to uppercase in C


I'm trying to make all keywords from C into uppercase from a C file, but when I try to use the toupper function from stdlib it only accepts char type

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char *words[] = {
  "auto", "break", "case", "char", "continue", "do", "default", "const","double", "else", "enum", "extern", "for", "if", "goto", "float", "int", "long", "register", "return", "signed", "static", "sizeof", "short", "struct","switch","typedef","union","void",  "while","volatile", "unsigned"
};


int main()
{
  char line[200];
  size_t len = 0;

  FILE *f;
  f = fopen("main.c", "r");

  int line_no = 0;
  while (fgets(line, sizeof line, f))
  {
    ++line_no;
    for (size_t i = 0; i < (sizeof words)/sizeof *words; i++)
    {
      if (strstr(line, words[i]) != NULL && line_no > 8)
      {
        printf("%s", words[i]);
      }
    }
  }
  fclose(f);
}

Solution

  • It's raining, and this challenge seemed interesting.

    Here's a rough cut of what you might expand to suit your needs.

    Instead of dealing with one line at a time (fgets), this simulates loading the entire file (fopen/ftell/fseek/fread) with a single long 'target' string.

    It loops through each of the keywords, uppercase'ing when it encounters one. (You need to be careful... Notice the test that ensures "longval" is not made uppercase.)

    Thanks for the fun!

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    const char *words[] = {
        "auto", "break", "case", "char", "continue", "do", "default", "const",
        "double", "else", "enum", "extern", "for", "if", "goto", "float", "int",
        "long", "register", "return", "signed", "static", "sizeof", "short",
        "struct","switch","typedef","union", "void", "while", "volatile", "unsigned"
    };
    
    void uc( char *buf, const char *word ) {
        int len = strlen( word ); // may need this...
        bool found = false;
    
        for( char *cp = buf; ( cp = strstr( cp, word ) ) != NULL; cp++ ) {
            char c = cp[len]; // one char beyond keyword length
            if( !isalpha( c ) && !isdigit( c ) && c != '_' ) {
                found = true;
                for( int i = 0; i < len; i++ )
                    cp[i] = (char)toupper( cp[i] );
            }
        }
        if( found )
            printf( "\n\n**FOUND** '%s'\n\n%s", word, buf );
    }
    
    int main() {
        char *src = 
            "#include <stdio.h>\n\n"
            "int func( int x ) {\n    return (x * x);\n}\n\n"
            "int main( void ) {\n"
            "    int longval = 3;\n"
            "    while( ( longval = func( longval ) ) < 10000 )\n"
            "        printf( \"%d\\n\", longval );\n"
            "    return 0;\n"
            "}\n";
    
        // some compilers disallow modifying string literals
        char *copy = malloc( strlen( src ) + 1 );
        strcpy( copy, src );
    
        printf( "%s", copy );
    
        for( int i = 0; i < sizeof words/sizeof words[0]; i++ )
            uc( copy, words[i] );
    
        free( copy );
        return 0;
    }
    

    I make no claim that this is complete. My hope is that you will be able to understand what is needed.

    Output of final printf(): (added as 'proof' of functionality). Notice that return, int, void and while have been UPPERCASE'd.

    **FOUND** 'while'
    
    #include <stdio.h>
    
    INT func( INT x ) {
        RETURN (x * x);
    }
    
    INT main( VOID ) {
        INT longval = 3;
        WHILE( ( longval = func( longval ) ) < 10000 )
            printf( "%d\n", longval );
        RETURN 0;
    }