Optional input variables in scanf - c

is there a way to have optional input variables in scanf ?
I have a program that scans input until EOF. That input can look like this:
+ 10 20 30
- 10 20 30
? 10
When I type (or read from a file) + or - it is always followed by three numbers but when I type in ? it is only followed by one number (always).
My current code looks like this:
#include <stdio.h>
#include <stdlib.h>
int main(){
char action;
int dc1,dc2,cable;
while(scanf(" %c %d %d %d",&action,&dc1,&dc2,&cable)!=EOF){
if((dc1==dc2)||(cable<1)||(dc1>999)||(dc2>999)||(dc1<0)||(dc2<0)){
printf("Wrong input.\n");
return 0;
}
else{
if(action=='+'){
/*code*/
}
else if(action=='-'){
/*code*/
}
else if(action=='?'){
/*code*/
}
else{
printf("Wrong input.\n");
return 0;
}
}
}
return 0;
}
Right now it requires me to type in three numbers all the time, even if I want to type in the "?" action.
Is there a way to make some of the variables in scanf optional so the input "? 10" would also be valid.
PS.
I have stripped the code so it is not too long. I hope I have included everything that is necessary.
I would also appreciate if I didn't have to rework the code too much because it is basically done, everything works like it needs to. This is the only thing that is stopping me from turning in my code.
PPS. This is for a homework.

As mentioned in comment this can be easily checked with sscanf() and fgets.
We are using the fgets to read a line and then pass it to the parser function. That function tries to parse the line. sscanf returns the successful number of parameters passed. Based on that count we are deciding which input it is.
This code is just a starting point for how to start. It avoids the lots of error checking and concentrates on the technique as discussed above by Jonathan Leffler.
Code example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 256
void add (int b,int c,int d){
printf("%d+%d+%d=%d\n",b,c,d,b+c+d);
}
void sub (int b,int c,int d){
printf("%d-%d-%d=%d\n",b,c,d,b-c-d);
}
void query (int a){
printf("?%d\n",a);
}
void parseAndProcess(const char *buf){
char a;
int b, c, d;
size_t ct;
ct = sscanf(buf,"%c%d%d%d",&a,&b,&c,&d);
if( ct <= 1){
//error
}
else if( ct==2 ) {
if( a == '?'){
query(b);
}
else{
//error
}
}
else if( ct == 3){
// error
}
else if( ct == 4){
if( a == '+') add(b,c,d);
else if( a == '-') sub(b,c,d);
else{
//error
}
}
else{
// error
}
}
int main(void){
char buf[BUFFSIZE];
while(fgets(buf,BUFFSIZE,stdin)){
parseAndProcess(buf);
}
return EXIT_SUCCESS;
}
Here add,sub methods are to be implemented for actual code. A demo implementation is shown here above. For example here in add,sub no overflow checking is there.

Related

how to check if a word contains number in c

When I read from file I want to check the word do not contains the number, for example, 2sum or 23b2 but is OK if the file read the mathematical operation like
sum = x + 5
I try to put inside the if statement [a-zA-Z]* put it does not work.
This part of my code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int charClass;
char lexeme [100];
void addChar();
void getChar();
void getNonBlank();
int lex();
int main() {
if ((in_fp = fopen("/Users/Desktop/ff.txt", "r")) == NULL)
printf("ERROR - cannot open front.in \n");
else {
getChar();
do {
if(strcmp(lexeme, "[a-zA-Z]*") == 0){
printf("error");
break;
}
lex();
} while (nextToken != EOF);
}
}
Regarding:
if(strcmp(lexeme, "[a-zA-Z]*") == 0){
This is comparing the char array [a-zA-Z]* to the array pointed at by lexeme
There are two ways to approach this problem.
First, use an regular expression, which requires several complexities that will just confuse you (or me)
Second, iterate over the expression pointed to by: lexeme as in:
for( size_t i=0; lexeme[i]; i++ )
{
if( isalpha( lexeme[i] )
{
....
}
}
The functions in ctype.h work on indivdual int values and when referencing: lexeme[i] that single character gets prompted to an 'int'

Get text while not EOF

Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 256
int main(int argc, const char * argv[]) {
char testo[N];
int i;
printf("PER TERMINARE L'INSERIMENTO PREMERE CTRL+Z oppure CTRL+D \n");
for(i=0;i<N;i++)
{
scanf("%c",&testo[i]);
/* if(testo[i]=='h' && testo[i-1]=='c')
{
i--;
testo[i]='k';
}
if(testo[i]==testo[i-1])
{
i--;
} */
if(testo[i]==EOF)
{
break;
}
}
puts(testo);
return 0;
}
When the code in /* ... */ is compiled, I can't stop the insert of text with EOF, but when the code is built and run as shown here, the EOF works.
Does anyone have any idea what the problem is?
You're testing for EOF incorrectly. With scanf(), you need to look at the return value. In fact, with almost all input functions, you need to test, if not capture and test, the return value.
Superficially, you need:
for (i = 0; i < N; i++)
{
if (scanf("%c", &testo[i]) == EOF)
break;
…
}
However, in general, you should check that scanf() made as many successful conversions as you requested, so it is better to write:
for (i = 0; i < N; i++)
{
if (scanf("%c", &testo[i]) != 1)
break;
…
}
In this example, it really won't matter. If you were reading numeric data, though, it would matter. The user might type Z instead of a number, and scanf() would return 0, not EOF.
To detect EOF, check the result of scanf()
if scanf("%c",&testo[i]) == EOF) break;
Note: testo[] may not be null character terminated. To print as a string, insure it is.
char testo[N];
int i;
// for(i=0;i<N;i++) {
for(i=0;i<(N-1);i++) {
if (scanf("%c",&testo[i]) == EOF) break;
}
testo[i] = '\0'; // add
puts(testo);
To stop at end of file, check the return value from scanf:
scanf returns the number of inputs correctly parsed. In your case, %c reads a byte from the stream correctly as long as end of file has not been reached. if (scanf("%c",&testo[i]) != 1) break; will do.
Yet using scanf to read one byte at a time from the input stream is overkill. The idiomatic way to do this in C is using the getchar() or the getc() function. The return value must be stored in an int variable and has special value EOF upon end of file.
You should also make the array 1 byte longer and store a null byte at the end to make it a C string, as expected by puts.
Here is a modified version of your program:
int main(int argc, const char *argv[]) {
char testo[N+1];
int i;
printf("PER TERMINARE L'INSERIMENTO PREMERE CTRL+Z oppure CTRL+D\n");
for (i = 0; i < N; i++) {
int c = getchar();
if (c == EOF)
break;
testo[i] = c;
/* ... further processing ... */
}
testo[i] = '\0';
puts(testo);
return 0;
}

how to know whether input is a number or not?

I have a problem.
My program needs to check whether the input is a number or anything else,in C.I searched and found that isdigit(int) is a function provided for this..but it only checks 48<=ASCII<=57 .
But what if i have to check for numbers only ? Is there any function like isInteger(),isReal(),isFloat() etc? and if not then how can i check for them?
In case of isdigit() too, I am getting a problem:
#include<stdio.h>
#include<ctype.h>
int main(){
int i = 1;
printf("%d",isdigit(i));
return 0;
}
it outputs 0 ,i do not understand ,it should be a non zero value ...
Assuming the input is a string, use strtol() and/or strtod().
Example
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char input[1000];
// get input, don't forget to check for errors
if (fgets(input, sizeof input, stdin) == NULL) {
fprintf(stderr, "Error in input\n");
exit(EXIT_FAILURE);
}
char *err;
errno = 0;
long x = strtol(input, &err, 10);
if (errno || *err) {
fprintf(stderr, "input is not an integer in the range for `long`.\n");
exit(EXIT_FAILURE);
}
errno = 0;
double y = strtod(input, &err);
if (errno || *err) {
fprintf(stderr, "input is not a correct double.\n");
exit(EXIT_FAILURE);
}
// use x and y as needed
return 0;
}
Read the documentation of isdigit(3). It applies to characters, not numbers. So isdigit('2') should be true (non-zero). As answered by pmg see also strtol(3)...
If you wanted to test digits of UTF-8 or Unicode it is much more complex. Use a library function, e.g. g_unichar_is_digit from Glib for Unicode.
You might make a fundamental mistake. A number is not made of digits. It is represented or written with digits. So two, 2 (decimal), II (roman notation), 0b10 or 10 (binary), deux (French), 1+1 (arithmetic expression), 二 (Chinese) .... all represent the same number (which is the successor of one), but only the second representation -decimal 2- has one digit.
From isdigit man page:
Check if character is decimal digit
So you can see that this function is applied to characters. Its return value should be non - zero.
You may try this:
bool checkNumber(const char *str)
{
while(*str != '\0')
{
if(*str < '0' || *str > '9')
return false;
str++;
}
return true;
}
Try this man.....
#include<stdio.h>
int main()
{
char a;
printf("enter any int\n");
scanf("%c",&a);
if(isdigit(a))
{
printf("input was a number");
}
else
printf("input wasnt a number");
return 0;
}

How can I return a string to the operating system in my C code?

I am a C beginner and this is my C code:
#include <stdio.h>
#include <stdlib.h>
main()
{
printf("Hello, World!\n");
return 'sss';
}
That will show an error. So how can I return a string in C code?
If you are looking to return a string from a function (other than main), you should do something like this.
#include <stdio.h>
const char * getString();
int main()
{
printf("Hello, World!\n");
printf("%s\n", getString());
return 0;
}
const char * getString()
{
const char *x = "abcstring";
return x;
}
The magic is in the key word static which preserves the memory content of the string even after the function ends. (You can consider it like extending the scope of the variable.)
This code takes one character each time, then concatenates them in a string and saves it into a file:
#include <stdio.h>
#include <conio.h>
char* strbsmallah ()
{
static char input[50];
char position = 0, letter;
scanf("%c", &letter);
while (letter != '~') { // Press '~' to end your text
input[position] = letter;
++position;
scanf("%c", &letter);
}
input[position] = '\0';
char *y;
y = (char*) &input;
//printf("%s\n ", y);
return y;
}
int main() {
printf("\n");
FILE *fp;
fp = fopen("bsmallah.txt", "w+");
fprintf(fp, strbsmallah());
while (!_kbhit())
;
return 0;
}
You could do this in a way similar to scanf. In other words:
void foo(char **value_to_return) {
*value_to_return = malloc(256); // Store 256 characters
strcpy(*value_to_return, "deposited string");
}
int main() {
char *deposit;
foo(&deposit);
printf("%s", deposit);
return 0;
}
You don't return a string. Applications exit with an integer exit code.
Conventionally, exiting with a return of 0 will always show that your application exited without error / completed. You return an integer other than 0 to show that your application exited abnormally.
You could throw an exception and handle it with a logging method higher in the call stack, or you could just return something other than 0 and make sure you had it documented in your release notes as to what each error integer means.
Sadly there is no way to do that.
You could add something to the end of your C program like:
int main()
{
int err = 0; // 0 is "success" is most C programs
printf("Hello, World!!\n");
switch( err )
{
case 0:
printf("Program shutdown successfully!\n");
break;
case 1:
printf("We had an issue somewhere. Please fix your input data\n");
break;
//case 2, 3, etc...
};
return err;
}
You might be able to use environment variables for that. Not sure though.

how can i return a char value from function? in c unix

To write programs in C which reads lines from a file
text, whose name will give the user at runtime.
The program should select a random line of the file and to print the screen, giving the user a time X to type the words seen on the screen.
The time of X depends on the length of each phrase and you can consider that each character will give the user 1 second.
If the message is printed correctly and on time, the user receives congratulations. If the error message printed (and on time), then the user is informed precisely about the mistakes he has done.
Finally, if time runs out before printing the message, then asks the user if he wants to continue and provided the user answers yes to the above sequence is repeated for a new random line of the file, otherwise the program terminates.
Can someone tell me what I have done wrong; I would have been easier if you write the code you need ...
thanks nik
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void catch_alarm (int sig)
{
char ans[2];
printf ("Operation timed out. Exiting...\n");
printf ("thes mia akoma eukairia?[y/n]\n");
scanf ("%s", ans);
exit (0);
}
void exodos (int sig)
{
printf ("termatismos ergasias... \n");
signal (SIGQUIT, SIG_DFL);
exit (0);
}
int main (int argc, char **argv)
{
int i, j, x, count, gram[80];
i = j = count = 0;
char arxeio[25], grammi[80], buf[80][80], protash[80], ch, ans[2];
FILE *fp;
printf("dwse to onoma tou arxeiou pou thes na anoixeis: \n");
scanf("%s", arxeio);
do
{
fp = fopen( arxeio, "r");
while ( (ch = getc(fp)) != EOF )
{
buf[i][j] = ch;
if ( buf[i][j] == '\n' )
{
++i;
gram[i] = j;
j = 0;
}
++j;
}
fclose(fp);
// edw vazoume tin rand kai to apotelesma tis sto 4 parakatw
x = rand() % i;
j = 0;
while (j<=gram[x+1])
{
printf("%c", buf[x][j]);
j++;
}
/* elenxos entos xronou an oxi TIME OUT... */
signal(SIGALRM, catch_alarm);
fflush(stdout);
alarm(gram[x+1]);
scanf("%s",protash);
if (ans[0] == 'n')
signal(SIGQUIT, exodos);
/* elenxos or8hs eisagwghs dedomenwn*/
j = 0;
while ( j<=(gram[x+1]-2) )
{
if ( buf[x][j+1] != protash[j] )
printf("anti gia %c egrapses %c\n", buf[x][j+1], protash[j]);
else
printf("swsto\n");
++j;
}
/* deuterh eukairia... */
}
while ( ans[0] == 'y' );
return 0;
}
The example you pasted here is slightly hard to follow, but it looks like you're trying to make a signal handler return a char. This isn't possible because the signal handler is required to be void (although it is in general possible for a function to return a char).
The simplest work around for this would be a global (static?) variable instead.
Also note that printf and scanf are not async-safe. The work around for that would be to set a "flag" somewhere and then notice that this has been set later on.
Edit I think this is a simplified example of what you're trying to achieve here:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <errno.h>
static int timeout = 0;
static void catch_alarm(int sig) {
if (SIGALRM != sig || 0 != timeout)
abort();
timeout = 1;
}
int main() {
char buf[80];
signal(SIGALRM, catch_alarm); //TODO: check return!
printf("Type some stuf:\n");
fflush(NULL);
alarm(5);
int read = -1;
while (read < 0 && !timeout) {
read = scanf("%80s", buf);
}
if (timeout) {
printf("Time out, do something else\n");
}
exit(0);
}

Resources