C Text conversion program - c

I am very new to the C language and have been working on a program that takes either a text file or input from the keyboard and either turns all the letters to capitals, lowercase, or rotates them by 13 places depending on the input given by the user which should go something like: ./tconv -u test.txt
This should, in theory, turn all the letters in test.txt to uppercase letters. If no file is given, ./tconv -u, then it should take input from the keyboard.
I think I am missing something fairly simple, but when I run it with any -r,-u, or -l arguments, it says it cannot read "-r", "-u", or"-l". What am I missing?
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
FILE*
input_from_args(int argc, const char *argv[])
{
if (argc==1){
return stdin;
}else{
return fopen(argv[1],"r");
}
}
int
rot13(c)
{
int e;
int ROT;
ROT = 13;
if(c>='A' && c <='Z'){
if((e=c+ROT)<='Z')
return e;
else{
e = c - ROT;
return e;
}
}
else{
return c;
}
}
int
main(int argc, const char*argv[])
{
FILE *src = input_from_args(argc,argv);
FILE *dest = stdout;
if (src == NULL){
fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[1]);
exit(EXIT_FAILURE);
}
char *rotate = "-r";
char *lower = "-l";
char *upper = "-u";
int i;
i =0;
int ch;
while ((ch = fgetc(src))!=EOF){
if (strcmp(upper,argv[i])==0){
fprintf(dest,"%c",toupper(ch));
}
else if (strcmp(lower,argv[i])==0){
fprintf(dest,"%c",tolower(ch));
}
else if (strcmp(rotate,argv[i])==0){
fprintf(dest,"%c",rot13(ch));
}
else{
fprintf(dest,"%c",ch);
}
}
fclose(src);
return EXIT_SUCCESS;
}

Argv[0] is your program, argv[1] is your flag and argv[2] is the file name if you provided one. You are trying to open argv[1] a file named "-r"

If you are using linux platform you can look into getopt_long to parse the command line options. it is provided by GNU for linux systems and it is system dependent. For system independent command line parsing Google gflags
This will help to reduce the overhead of command line parsing and you can concentrate more on program logic.
Here is an example taken from http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-Example.html
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by ‘--verbose’. */
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
while (1)
{
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options don’t set a flag.
We distinguish them by their indices. */
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "abc:d:f:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'a':
puts ("option -a\n");
break;
case 'b':
puts ("option -b\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
/* Instead of reporting ‘--verbose’
and ‘--brief’ as they are encountered,
we report the final status resulting from them. */
if (verbose_flag)
puts ("verbose flag is set");
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
exit (0);
}

Related

getopt_long()'s longindex always 0

In a C program I have to parse command line option for which I am using C function getopt_long() whose syntax is:
int getopt_long(int argc, char * const *argv, const char *optstring, const struct option *longopts, int *longindex);
Problem is I always receive the value of last parameter longindex as 0.
Below is the sample code:
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
printf("MAIN\n");
int i;
printf("argc = %d\n",argc);
for(i=0;i<argc;i++)
{
printf("argv[%d] = %s\n",i, argv[i]);
}
while (1)
{
static struct option long_options[] =
{
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "c:d:f:",
long_options, &option_index);
printf("\nOPT c = %d, option_index = %d START\n", c, option_index);
if (c == -1)
{
printf("BREAKKKKKKKKKKK\n");
break;
}
printf("OPTION FOUND c = %d, option_index = %d, long_options[option_index].name = %s\n", c, option_index, long_options[option_index].name);
switch (c)
{
case 0:
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
break;
default:
abort ();
}
}
if (verbose_flag)
puts ("verbose flag is set");
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
return (0);
}
Output:
MAIN
argc = 5
argv[0] = /home/a.out
argv[1] = -delete
argv[2] = dell
argv[3] = -create
argv[4] = ceat
OPT c = 100, option_index = 0 START
OPTION FOUND c = 100, option_index = 0, long_options[option_index].name = delete
option -d with value `elete'
OPT c = 99, option_index = 0 START
OPTION FOUND c = 99, option_index = 0, long_options[option_index].name = delete
option -c with value `reate'
OPT c = -1, option_index = 0 START
BREAKKKKKKKKKKK
non-option ARGV-elements: dell ceat
Am I missing something?
Why do I always the value of last parameter longindex as 0?
How to rectify the issue?
From your argv[…] = … output it seems like you’re using long options incorrectly. Rather than invoke your program like this
/home/a.out -delete dell -create creat
Invoke it like this:
/home/a.out --delete dell --create creat
This will cause the index to be set correctly.
Check the getopt_long(3) manpage, section “Description”, for details on how to use long options.

C - getopt_long() example - tests in case 0

I would like to use getopt_long() correctly and am trying to understand why certain choices were made in the example of getopt_long. (I've copied the full code listing below).
I understand that case 0 occurs when the flag field of the struct is not null (find getopt_long returns 0), but why does the example show retesting long_options[option_index].flag for null in case 0? Isn't this guaranteed given that we are in case 0?
Asked another way: What input could I provide to cause the code to enter case 0 but fail the first if-statement within it? Is printf ("option %s", long_options[option_index].name); unreachable?
25.2.4 Example of Parsing Long Options with getopt_long
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by ‘--verbose’. */
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
while (1)
{
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options don’t set a flag.
We distinguish them by their indices. */
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "abc:d:f:", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'a':
puts ("option -a\n");
break;
case 'b':
puts ("option -b\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
/* Instead of reporting ‘--verbose’
and ‘--brief’ as they are encountered,
we report the final status resulting from them. */
if (verbose_flag)
puts ("verbose flag is set");
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
exit (0);
}

C programming with getopt(): giving command line flags criteria

I am beginning to teach myself C. I have run into a few bumps here and there but right now I am stumped by getOpt(). The main thing thats giving me trouble is when I try to make certain flags dependent on other flags. For example I want these to work:
./myfile -a -b -c blue
But none of the other options to work without -a. Thus ./myfile -b -c purple would be invalid. Is it possible for getopt to handle this kind of "flag dependent" criteria? How would I go about doing that? Secondly, lets say that no matter which flags are passed, along with it must be a colour.
So ./myfile -a -b green and ./myfile red are both valid. I understand that this all lies within the options parameter of getOpt() (which is currently set up to look something like this "abc"), but how would I make one parameter required for each instance without doing "a:b:c:" since this would not include the mandatory colour if no flags are passed.
Here's the example (from the manpage) of getopt:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int
main (int argc, char *argv[])
{
int flags, opt;
int nsecs, tfnd;
nsecs = 0;
tfnd = 0;
flags = 0;
while ((opt = getopt (argc, argv, "nt:")) != -1)
{
switch (opt)
{
case 'n':
flags = 1;
break;
case 't':
nsecs = atoi (optarg);
tfnd = 1;
break;
default: /* '?' */
fprintf (stderr, "Usage: %s [-t nsecs] [-n] name\n", argv[0]);
exit (EXIT_FAILURE);
}
}
printf ("flags=%d; tfnd=%d; optind=%d\n", flags, tfnd, optind);
if (optind >= argc)
{
fprintf (stderr, "Expected argument after options\n");
exit (EXIT_FAILURE);
}
printf ("name argument = %s\n", argv[optind]);
/* Other code omitted */
exit (EXIT_SUCCESS);
}
Note you'll need to add some declarations, and a main() function to get that to work.
You can see the example n above is a flag, and works like your b option. The t option above takes a parameter and works like your c option. If you want to have an a option that is also a flag, you would make the getopt parameter "abf:" (i.e. add an a in without a colon), and a stanza to the switch like this:
case 'a':
aflag = 1;
break;
having first set aflag to 0. At the end you would check for the illegal condition where other options were passed without aflag being set.
So all in all, it would look like this:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int
main (int argc, char *argv[])
{
int flags, opt;
int nsecs, tfnd;
int aflag;
nsecs = 0;
tfnd = 0;
flags = 0;
aflag = 0;
while ((opt = getopt (argc, argv, "ant:")) != -1)
{
switch (opt)
{
case 'a':
aflag = 1;
break;
case 'n':
flags = 1;
break;
case 't':
nsecs = atoi (optarg);
tfnd = 1;
break;
default: /* '?' */
fprintf (stderr, "Usage: %s [-t nsecs] [-n] name\n", argv[0]);
exit (EXIT_FAILURE);
}
}
printf ("flags=%d; tfnd=%d; optind=%d\n", flags, tfnd, optind);
if (optind >= argc)
{
fprintf (stderr, "Expected argument after options\n");
exit (EXIT_FAILURE);
}
if (!aflag && (flags || tfnd))
{
fprintf (stderr, "Must specify a flag to use n or t flag\n");
exit (EXIT_FAILURE);
}
printf ("name argument = %s\n", argv[optind]);
/* Other code omitted */
exit (EXIT_SUCCESS);
}

getopt_long() and parameters that aren't flags?

I'm trying to use the getopt_long() function for the first time only I'm having problems with arguments that aren't flags. For instance, in my code when a unknown argument is given I want to use it as a input file. When I run this with only a file name it is not printed, if I first use a flag, any flag, then I can print it.
How can I fix this?
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[]) {
int c;
int option_index = 0;
while(42) {
c = getopt_long(argc, argv, "hi:o:a:", long_options,
&option_index);
if(c == -1)
break;
switch(c) {
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag\n");
break;
case 'o': /* --output */
printf("--output flag\n");
break;
case 'a': /* --algorithm */
printf("--algorithm flag \n");
break;
default: /* ??? */
fprintf(stderr, "Invalid option");
return 1;
}
if(optind < argc) {
printf("other arguments: ");
while(optind < argc) {
printf ("%s ", argv[optind]);
optind++;
}
printf("\n");
}
}
return 0;
}
The loop should only contain the switch. Process the residual arguments in a separate (not nested) loop:
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int i;
while ((opt = getopt_long(argc, argv, "hi:o:a:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag (%s)\n", optarg);
break;
case 'o': /* --output */
printf("--output flag (%s)\n", optarg);
break;
case 'a': /* --algorithm */
printf("--algorithm flag (%s)\n", optarg);
break;
default: /* ??? */
fprintf(stderr, "Invalid option %c\n", opt);
return 1;
}
}
for (i = optind; i < argc; i++)
printf("Process: %s\n", argv[i]);
return 0;
}
There is a way to have GNU getopt() and getopt_long() return file name arguments as if they were options with the 'letter' ^A '\1'; use '-' as the first character of the short options string, and trap '\1' in the switch; the value of optarg is the name of the file.
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int i;
while ((opt = getopt_long(argc, argv, "-hi:o:a:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag (%s)\n", optarg);
break;
case 'o': /* --output */
printf("--output flag (%s)\n", optarg);
break;
case 'a': /* --algorithm */
printf("--algorithm flag (%s)\n", optarg);
break;
case '\1':
printf("File: %s\n", optarg);
break;
default: /* ??? */
fprintf(stderr, "Invalid option %c\n", opt);
return 1;
}
}
for (i = optind; i < argc; i++)
printf("Process: %s\n", argv[i]);
return 0;
}
However, you do need the loop after the argument processing loop in case your cantankerous user types:
program -- abc def
The '--' terminates the while() loop without processing the file name arguments.
It doesn't work because you break out of the outer while loop when getopt_long returns -1 (which indicates that there are no more options).
You need to move the if (optind < argc) block out of the outer while loop; it doesn't belong there anyway. This might be clearer if you wrote that outer while loop as:
while ((c = getopt_long(...)) != -1)
{
switch (c)
{
/* Deal with flags. */
}
}

Pass arguments into C program from command line

So I'm in Linux and I want to have a program accept arguments when you execute it from the command line.
For example,
./myprogram 42 -b -s
So then the program would store that number 42 as an int and execute certain parts of code depending on what arguments it gets like -b or -s.
You could use getopt.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
int bflag = 0;
int sflag = 0;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "bs")) != -1)
switch (c)
{
case 'b':
bflag = 1;
break;
case 's':
sflag = 1;
break;
case '?':
if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
printf ("bflag = %d, sflag = %d\n", bflag, sflag);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
In C, this is done using arguments passed to your main() function:
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
More information can be found online such as this Arguments to main article.
Consider using getopt_long(). It allows both short and long options in any combination.
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by `--verbose'. */
static int verbose_flag;
int
main (int argc, char *argv[])
{
while (1)
{
static struct option long_options[] =
{
/* This option set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
/* These options don't set a flag.
We distinguish them by their indices. */
{"blip", no_argument, 0, 'b'},
{"slip", no_argument, 0, 's'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
int c = getopt_long (argc, argv, "bs",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'b':
puts ("option -b\n");
break;
case 's':
puts ("option -s\n");
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
if (verbose_flag)
puts ("verbose flag is set");
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
return 0;
}
Related:
Which command line commands style do you prefer?
What is the general syntax of a Unix shell command?
Take a look at the getopt library; it's pretty much the gold standard for this sort of thing.
Instead of getopt(), you may also consider using argp_parse() (an alternative interface to the same library).
From libc manual:
getopt is more standard (the
short-option only version of it is a
part of the POSIX standard), but using
argp_parse is often easier, both for
very simple and very complex option
structures, because it does more of
the dirty work for you.
But I was always happy with the standard getopt.
N.B. GNU getopt with getopt_long is GNU LGPL.
Other have hit this one on the head:
the standard arguments to main(int argc, char **argv) give you direct access to the command line (after it has been mangled and tokenized by the shell)
there are very standard facility to parse the command line: getopt() and getopt_long()
but as you've seen the code to use them is a bit wordy, and quite idomatic. I generally push it out of view with something like:
typedef
struct options_struct {
int some_flag;
int other_flage;
char *use_file;
} opt_t;
/* Parses the command line and fills the options structure,
* returns non-zero on error */
int parse_options(opt_t *opts, int argc, char **argv);
Then first thing in main:
int main(int argc, char **argv){
opt_t opts;
if (parse_options(&opts,argc,argv)){
...
}
...
}
Or you could use one of the solutions suggested in Argument-parsing helpers for C/UNIX.

Resources