The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 7.01 on page 153
Write a program that converts upper case to lower or lower case to upper, depending on the name it is invoked with, as found in argv[0].
Solution by Richard Heathfield
/* This program converts its input to upper case * (if argv[0] begins with U or u) or lower case. * If argc is 0, it prints an error and quits. */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> int main(int argc, char **argv) { int (*convcase[2])(int) = {toupper, tolower}; int func; int result = EXIT_SUCCESS; int ch; if(argc > 0) { if(toupper((unsigned char)argv[0][0]) == 'U') { func = 0; } else { func = 1; } while((ch = getchar()) != EOF) { ch = (*convcase[func])((unsigned char)ch); putchar(ch); } } else { fprintf(stderr, "Unknown name. Can't decide what to do.\n"); result = EXIT_FAILURE; } return result; }
Solution by Bryan Williams (category 1)
/* Exercise 7-1. Write a program that converts upper case to lower case or lower case to upper, depending on the name it is invoked with, as found in argv[0]. Assumptions: The program should read from stdin, until EOF, converting the output to stdout appropriately. The correct outputs should be : Program Name Output lower stdin with all caps converted to lower case upper stdin with all lowercase characters converted to uppercase [anything else] helpful message explaining how to use this Author : Bryan Williams */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define SUCCESS 0 #define NO_ARGV0 1 #define BAD_NAME 2 int main(int argc, char *argv[]) { int ErrorStatus = SUCCESS; int (*convert)(int c) = NULL; int c = 0; /* check that there were any arguments */ if(SUCCESS == ErrorStatus) { if(0 >= argc) { printf("Your environment has not provided a single argument for the program name.\n"); ErrorStatus = NO_ARGV0; } } /* check for valid names in the argv[0] string */ if(SUCCESS == ErrorStatus) { if(0 == strcmp(argv[0], "lower")) { convert = tolower; } else if(0 == strcmp(argv[0], "upper")) { convert = toupper; } else { printf("This program performs two functions.\n"); printf("If the executable is named lower then it converts all the input on stdin to lowercase.\n"); printf("If the executable is named upper then it converts all the input on stdin to uppercase.\n"); printf("As you have named it %s it prints this message.\n", argv[0]); ErrorStatus = BAD_NAME; } } /* ok so far, keep looping until EOF is encountered */ if(SUCCESS == ErrorStatus) { while(EOF != (c = getchar())) { putchar((*convert)(c)); } } /* and return what happened */ return SUCCESS == ErrorStatus ? EXIT_SUCCESS : EXIT_FAILURE; }
Solution by Cromagnon (talk) (category 0)
December 26, 2019.
This uses a function getbasename
to get the basename of the command. Thus, argv[0] = "/tmp/lower"
implies getbasename(argv[0]) = "lower"
#include <stdio.h> #include <ctype.h> #include <string.h> char *getbasename(char *); /* convert input to lower or upper case depending on argv[0]*/ int main(int argc, char *argv[]) { int c, (*convert)(int) = NULL; char* bn; if (strcmp((bn = getbasename(argv[0])), "lower") == 0) convert = tolower; else if (strcmp(bn, "upper") == 0) convert = toupper; else return 1; while ((c = getchar()) != EOF) putchar((*convert)(c)); return 0; } char *getbasename(char *s) { char *p; char *base; for (base = p = s; *p != '\0'; p++) if (*p == '/') base = p; return base + 1; }
Solution by DtxdF
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define IS_LOWER 1 #define IS_UPPER 2 #define IS_NONE -1 int get_size(char *fn); int main(int argc, char **argv) { int c, size; char *filename = *argv; filename += 2; size = get_size(filename); if (size == IS_NONE) { fputs("Invalid filename!\n", stderr); return EXIT_FAILURE; } while ((c = getchar()) != EOF) { if (size == IS_LOWER) c = tolower(c); else c = toupper(c); putchar(c); } return EXIT_SUCCESS; } int get_size(char *fn) { if (strcmp(fn, "tolower") == 0) return IS_LOWER; else if (strcmp(fn, "toupper") == 0) return IS_UPPER; else return IS_NONE; }
Solution by anonymous
My solution takes into account if it is a Unix/Linux executable or a Windows executable and it handles different ways of being called.
#include <stdio.h> #include <string.h> #include <ctype.h> /* Exercise 7-1. Write a program that converts upper case to lower or lower case to upper, depending on the name it is invoked with, as found in argv[0]. */ enum type { LOWER, UPPER }; int main(int argc, char *argv[]) { int c, mode = -1; if (argc > 1) { printf("usage 1: ./lower\nusage 2: .\\lower.exe\nusage 3: ./upper\nusage 4: .\\upper.exe\n"); return 1; } if (stricmp(*argv, "lower") == 0 || stricmp(*argv, "lower.exe") == 0) // handles when argv simply equals the executable name mode = LOWER; else if (stricmp(*argv, "upper") == 0 || stricmp(*argv, "upper.exe") == 0) // handles when argv simply equals the executable name mode = UPPER; else // handles when argv has a relative or absolute path for the executable { while (*++*argv != '\0') // go to end of string ; while (*--*argv != '\\' && **argv != '/') // go back until a slash is found ; (*argv)++; // move right to not include the slash if (stricmp(*argv, "lower") == 0 || stricmp(*argv, "lower.exe") == 0) mode = LOWER; else if (stricmp(*argv, "upper") == 0 || stricmp(*argv, "upper.exe") == 0) mode = UPPER; } if (mode == LOWER) while ((c = getchar()) != EOF) putchar(tolower(c)); else if (mode == UPPER) while ((c = getchar()) != EOF) putchar(toupper(c)); else { printf("usage 1: ./lower\nusage 2: .\\lower.exe\nusage 3: ./upper\nusage 4: .\\upper.exe\n"); return 1; } return 0; }