Using getopt with no arguments - c

By default I want the program will read input from stdin and send it's output to stdout.
The -f option will cause the
program to read the input from a text file and the -o option will cause the program to write the
output to a file instead of stdout.
The –c if specified will display the output in a CSV format (either in stdout or to a file depending if -o is specified).
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
int main(int argc, char * argv[]){
char opt;
char *filename_in, *filename_out;
int i, flagC=0,flagF=0,flagO=0;
while((opt = getopt(argc,argv,"cf:o:")) != -1){
switch(opt){
case 'c':
flagC=1;
break;
case 'o':
flagO=1;
filename_out = optarg;
break;
case 'f':
flagF=1;
filename_in = optarg;
openFile(filename_in);
break;
case '?':
printf("Opt ?");
return 0;
default:
printf("Opt Default");
return 0;
}
}
if((flagC==0) && (flagO==0) && (flagF==0)){
// puts("Please enter a string:");
}
for (i = optind; i < argc; i++)
printf("%s ", argv[i]); //prints anything without argument and space between
return 0;
}
Is there a better way to read input from stdin aside from checking each flag I created is set to 0?
char input[100];
if((flagC==0) && (flagO==0) && (flagF==0)){
// puts("Please enter a string:");
// scanf("%s", &input);
}

Related

Read a single user input using scanf and convert it into appropriate data type

I have a program that reads user input as such:
char c;
scanf("%c", &c);
and then checks if it is a digit:
if(isdigit(c)) {
int f = atoi(c);
return f;
}
switch(c) {
case 'q':
exit(1);
break;
...
}
...
Example program:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main() {
char c;
scanf("%c", &c);
if(isdigit(c)) {
int f = atoi(&c);
printf("f: %d\n", f);
return f;
}
switch(c) {
case 'q':
printf("q\n");
return -1;
break;
}
return 0;
}
However when I enter, for exmaple, 10 then the input becomes 1 and 0 and \n. I want 10. How do I read "10" and "100" and "4" for example as well as other characters such as "q"?
char variables are only capable of saving one character. So if you want to have multiple characters (numbers are also characters) in a char variable you have to use string or char VARIABLE[size] . For example: char variable[10] can save up to 10 characters. But then you can't use isdigit() in that way anymore. Instead you have to use a loop to check each character of the string.

Command-line parsing: How to parse a string as an argument

I am attempting to parse a command line argument, which in turn will execute an associated case within a switch statement. When I parse an integer argument (as seen in the code below), the associated case executes correctly. When I attempt to parse a string such as "CPU", I do not get the correct output.
Functioning code (parsing an integer e.g. an argument of 4 gives athe correct output of hello):
#include <stdio.h>
int main(int argc, char *argv[]) {
char execution_mode = atoi (argv[1]);
switch (execution_mode)
{
case (4) :
printf("Hello");
getchar();
break;
case (8) :
printf("Goodbye");
getchar();
break;
default:
printf("Error! execution mode is not correct");
getchar();
break;
}
return 0;
}
My attempt at parsing a string e.g. the argumentCPU:
#include <stdio.h>
int main(int argc, char *argv[]) {
typedef enum MODE { CPU, OPENMP } MODE;
MODE execution_mode = (char)argv[1];
switch (execution_mode)
{
case (CPU) :
printf("Hello");
getchar();
break;
case (OPENMP) :
printf("Goodbye");
getchar();
break;
default:
printf("Error! execution mode is not correct");
getchar();
break;
}
return 0;
}
You cannot convert a string to an enumerate like this. What you're doing is just converting the pointer to the string to char. Which fails.
One alternative (besides comparing first argument with strcmp) to avoid this would be to give a character value to your enumerates:
typedef enum { CPU='C', OPENMP='O' } MODE;
and now you can pick the first letter of the first argument and convert it:
MODE execution_mode = (MODE)argv[1][0];
The letters must be of course all different. And check argc>1 to see if argv[1] is valid, of course
If you want full string match, you have no other choice than using strcmp:
const char *execution_mode = argv[1];
if (strcmp(execution_mode,"CPU")==0)
{
// do something
}
else if (strcmp(execution_mode,"OPENMP")==0)
{
// do something else
}
With the help of the users who have answered this question, I have found a working solution by using strcmp as seen below. I have also added some error checking to ensure enough arguments have been enterred on the command-line.
#include <stdio.h>
int main(int argc, char *argv[]) {
//Ensure there are enough arguments
if (argc < 2)
{
printf("Error: not enough arguments");
exit(1);
}
typedef enum MODE { CPU, OPENMP, CUDA, ALL } MODE;
MODE execution_mode = (MODE)argv[1];
//Compare string with command-line arguments
if (strcmp("CPU", execution_mode) == 0)
{
//selects CPU case
execution_mode = CPU;
}
else if (strcmp("OPENMP", execution_mode) == 0)
{
//selects OPENMP case
execution_mode = OPENMP;
}
else
{
printf("invalid arg");
}
//Switch statement
switch (execution_mode)
{
case (CPU) :
printf("CPU MODE SELECTED");
getchar();
break;
case (OPENMP) :
printf("OPENMP MODE SELECTED");
getchar();
break;
default:
printf("Error: execution mode is not correct");
getchar();
break;
}
return 0;
}

Segmentation fault in atoi command

I have the following code:
int main(int argc, char *argv[])
{
int value,direction=0;
char c;
printf ("go\n");
while((c = getopt(argc, argv, "wr:")) != -1) {
printf ("go\n");
printf("%c\n",c);
switch(c) {
case 'w':
printf ("go\n");
value=atoi(optarg);
printf ("go\n");
printf("The input value is %x",value);
direction=1; //1 for write
break;
case 'r':
direction=0; // 0 for read
break;
default:
printf("invalid option: %c\n", (char)c);
usage();
return -1;
}
}
}
Now when i run the program by writing
./spicode.out -w 25
I need to pick the 25 after w using optarg, but its producing a segmentation fault.
What am i doing wrong?
You should put colon between commandline options.
c = getopt(argc, argv, "w:r")
From gnu.org :
An option character in this string can be followed by a colon (‘:’) to
indicate that it takes a required argument
Therefore wr: becomes w:r

C - making this program portable

The idea
scanning a password entered by the user and showing ********** in place of P#$$w00r_D
explaining the code
inside a while loop keep scanning the characters using getch() and put them into an array password[], until the user press return
The Code
#include <stdio.h>
#include <conio.h>
#define TRUE 1
#define P_MAX 25
int main(int argc, char* argv[]) {
char password[P_MAX], ch;
int i = 0;
puts("Enter the password [MAX 25]: ");
while (TRUE) {
if (i < 0) {
i = 0;
}//end if
ch = getch();
if (ch == 13)//return
break;
if (ch == 8) // BACKSPACE
{
putch('b');
putch(NULL);//Overwrite that character by NULL.
putch('b');
i--;//Decrement Current Track of Character. (i)
continue;
}//end if
password[i++] = ch;
ch = '*';
putch(ch);
}//end while
printf("\nPassword Entered : %s", password);//test
getch();
return 0;
}//end main
Compiling on Unix machine
[ar.lnx#host Documents] $ gcc 115.c -o x
115.c:2:18: fatal error: conio.h: No such file or directory
compilation terminated.
[ar.lnx#host Documents] $
this code works fine on windows, but not in Unix.
any help?

Testing the input if it is numeric or not

I wrote a C program wherein I am accepting a numeric input from the user. However, if the user inputs a character, then I have to show that it is an invalid input and make the user enter a number again. How do I achieve this? I am writing the program using gcc compiler in Ubuntu. The search results on Google suggest to use isalpha function...however, it is not available in the libraries I guess.
I also tried the below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void main()
{
system("clear");
if (isdigit(1))
printf("this is an alphabet\n");
else
printf("this is not an alphabet\n");
}
You will need to use scanf to get user input with %d as you want to scan an integer. In your case, scanf will return 1 on sucessfull scanning.
int num;
//loop to prompt use to enter valid input
while(scanf("%d",&num)==0) //scanning an integer failed
{
printf("invalid input ! Try again\n");
scanf("%*s"); //remove the invalid data from stdin
}
The functions isalpha() and isdigit() works when you are getting a character input using %c in the scanf. If you want to scan input using %c , then you can simply check like what you have done in your code provided that you get input using %c. Note that character 1 ('1') is note equal to integer 1 . Characters have their integer values as represented by the ASCII table. Your program to prompt the user again when the user enters anything other that a number using %c will look like this:
char ch;
while(1){
printf("Enter a number\n");
scanf(" %c",&ch);
printf(Your input is %c\n",ch);
if(isdigit(ch))
{
printf("This is a number\n");
break;
}
else
printf("This is not a number. Invalid input\n");
}
I tried the below code which worked fine..using isdigit()
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
void main()
{
system("clear");
char str[1];
printf("Enter a number\n");
scanf("%s",str);
printf("What you entered was %s\n",str);
if(isdigit(str[0]))
printf("this is not an alphabet\n");
else
printf("this is an alphabet\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include<ctype.h>
int main()
{
char c;
printf("Enter a character: ");
scanf("%c",&c);
bool check=true;
while(check)
{
if( (c>='a'&& c<='z') || (c>='A' && c<='Z'))
{
printf("%c is an alphabet.",c);
check=true;
break;
}
else
{
printf("%c is not an alphabet.",c);
check=false;
}
}
return 0;
}
You can write your own. It's better to check digits since there're less cases for digits.
bool isDigit(char c) {
bool rtn = false;
switch(c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
rtn = true;
break;
default:
rtn = false;
break;
}
return rtn;
}

Resources