Here's my code:
1. User types in two names, with a space in between. This means that two strings need to be read. I.e. input:
John Doe.
The strings are then checked in a char-array. (works fine).
The while loop goes on until the user types "stop" - only "stop".
How can I make it to stop directly if "stop" is entered - without the need to check the second string?
The code:
while(bool==false)
{
scanf("%20s%20s", name1, name2);
if(strcmp(name1, "stop")==0)
{
break;
}
// but still the second name has to be entered
rest of code...
}
Thanks for any tips!
I suggest you use fgets to get the input, check for the "stop" string, and then use sscanf to parse the input.
You can put to use the regular expression character class support provided by scanf.
You could do:
scanf("%s%[^\n]s", name, temp);
Here, your first word is mandatory while second is optional.
When you input 2 words, your temp would have a leading space.
If you want to directly avoid it, you can do so by:
char *p = temp;
scanf("%s%[^\n]s", name, p++);
Here, you can later access your 2 words using name and p
Related
I am a beginner of C and trying to extract Characters from standard input.
Input = "C0h1r2i3s4"
Expected Outcome = "Chris"
I've tried two ways to achieve this:
Use scanf to store input in one variable -> traverse through input one character a time -> if that character is not a number in ASCII table, store that character in a variable
Use fgets to get input and store in one variable -> traverse through input one character a time -> if that character is not a number in ASCII table, store character in a variable
I wonder if it's possible to use scanf/fgets to get only the characters from stdin? So that I don't have to traverse through every characters.
I've tried to use scanset below, but it seems scanf always screens at character-level and stops when the next char does not fit specified format.
Anyway, I wonder if there is a more powerful use of scanset & scanf.
Code for scanf()
#include <stdio.h>
#include <stdlib.h>
void main()
{
char str[50];
//intput = C0h1r2i3s4
scanf("%s", &str); // str = "C0h1r2i3s4"
//intput = C0h1r2i3s4
scanf("%*c%*d%s", &str); // str = "h1r2i3s4" -> C & 0 is ignored
//intput = C0h1r2i3s4
scanf("%[A-Z,a-z]%*d%s", &str); // str = "C" -> are they a valid format identifier? "%[A-Z,a-z]%*d%s"
}
Just want to close this question in case someone else is looking for similar one
In C, there is no simple way to extract certain characters directly from stdin.
first, we need to read the complete inputs from stadin
then, we travers through the inputs to decides which characters are in concern
Thank you, the-busybee, for your comment that saved my life earlier this year. I cannot add a comment due to not enough reputation on GitHub, and I just realized that I could reply to my own post.
I am trying to create a pattern like below, for ,when enter button is pressed twice, the program should terminate, but if user enters something in the line, the program shouldn't terminate.
[\n\n] {
if( strcmp(yytext,"?")){
return 0;
}
}
I try to check with strcmp for yytex is null space, but what should ı put inside " " ?
[\n\n] doesn't match two consecutive line breaks. It's a character class matching a single character that's either a line break or ... a line break. It's equivalent to just \n - duplicate elements in a character class have no effect.
To match two consecutive line breaks, what you want is \n\n without the bracket.
As for strcmp, there is absolutely no reason to check the contents of yytext here. Using the pattern [\n\n], yytext can only ever be equal to "\n" and using \n\n, it can only ever be equal to "\n\n". Either way there's no reason to compare it to anything when you already know what its value is going to be.
This is the solution for this situation guys
^\n yyterminate();
I need to create a method that get's commands from users using scanf and runs a function. The command can be simple as help or list but it can also be a command that has an argument like look DIRECTION or take ITEM. What is the best way to go about this? I could just loop through the characters of a single given string and check it manually but I was wondering there was a better way of doing this.
scanf("%s %s", command, argument);
This won't work if there's no argument. Is there a way around this?
There is a 'method' that may work. In fact, two come to mind.
Both rely on whitespace chars (in plain-english, '\n', ' 'and '\t') separating the arguments , and I assume this is good enough.
1
First, the relatively easy one - using main(int argc,char *argv[]) as most CLI programs do.
Then, running a long string of if()s/else if()s which check if the input string matched valid arguments , by testing if strcmp(argv[x],expected_command) returns 0.
You may not yet have been taught about how to use this, and it may appear scary, but its quite easy if you are familiar with string.h, arrays and pointers already.
Google searches and YouTube videos may be of help, and it won't take more than 20 or so minutes.
2
Second, if you have your program with a real CLU 'UI' and the program is in a loop and doesn't just terminate once output is generated - unlike say cat or ls , then you take input of 'command' strings within the program.
This means you will have to, apart from and before the if-ed strcmp()s , ensure that you take input with scanf() safely, and that you are able to take multiple strings as input, since you talk of sub-arguments like look DIRECTION.
The way I have done this myself (in the past) is as follows :
1. Declare a command string, say char cmd[21] = ""; and (optionally) initialise it to be empty , since reading an uninitialised string is UB (and the user may enter EOF).
2. Declare a function (for convenience) to check scanf() say like so:
int handle_scanf(int returned,int expected){
if(returned==expected)
return 0;
if(returned==EOF){
puts("\n Error : Input Terminated Immaturely.");
/* you may alternatively do perror() but then
will have to deal with resetting errno=0 and
including errno.h */
return -1;
}
else{
puts("\n Error : Insufficient Input.");
return -2;
}
}
Which can be used as : if(handle_scanf(scanf(xyz,&xyz),1)==0) {...}
As scanf() returns number of items 'taken' (items that matched with expected format-string and were hence saved) and here there is only 1 expected argument.
3. Declare a function (for convenience) to clear/flush stdin so that if and when unnecessary input is left in the input stream , (which if not dealt with, will be passed to the next place where input is taken) it can be 'eaten'.
I do it like so :
void eat()
{
int eat; while ((eat = getchar()) != '\n' && eat != EOF);
}
Essentially clears input till a newline or EOF is read. Since '\n' and EOF represent End Of Line and End Of File , and modern I/O is line buffered and performed through the stdin file , it makes sense to stop upon reading them.
EDIT : You may alternatively use a macro, for slightly better performance.
4. Print a prompt and take input, like so :
fputs("\n >>> ",stdout);
int check = handle_scanf(scanf("%20s",cmd),1);
Notice what I did here ?
"%20s" does two things - stops buffer overflow (because more than 20 chars won't be scanned into cmd) and also stops scanning when a whitespace char is encountered. So, your main command must be one-word.
5. Check if the the command is valid .
This is to be done with the aforementioned list of checking if strcmp(cmd,"expected_cmd")==0 , for all possible expected commands.
If there is no match, with an else , display an error message and call eat();(arguments to invalid command can be ignored) but only if(check != -1).
If check==-1 , this may mean that the user has sent an EOF signal to the program, in which case, calling eat() within a loop will result in an infinite loop displaying the error message, something which you don't want.
6. If there is a match, absorb the whitespace separating char and then scanf() into a char array ( if the user entered, look DIRECTION, DIRECTION is still in the input stream and will only now be saved to said char array ). This can be done like so :
#define SOME_SIZE 100 // use an appropriate size
if(strcmp(cmd,"look")==0 && check==0){ // do if(check==0) before these ifs, done here just for my convenience)
getchar(); // absorb whitespace seperator
char strbuff[SOME_SIZE] = ""; // string buffer of appropriate size
if(handle_scanf(scanf("%99[^\n]",strbuff),1)==0){
eat();
/* look at DIRECTION :) */
}
// handle_scanf() generated appropriate error msg if it doesn't return 0
}
Result
All in all, this code handles scanf mostly safely and can indeed be used in a way that the user will only type , say :
$ ./myprogram
>>> look DIRECTION
# output
>>> | #cursor
If it is all done within a big loop inside main() .
Conclusion
In reality, you may end up needing to use both together if your program is complex enough :)
I hope my slightly delayed answer is of help :)
In case of any inaccuracies , or missing details, please comment and I will get back to you ASAP
Here's a good way to parse an inputted string using strtok and scanf with a limit of 99 characters
#include <string.h>
char command[99];
scanf("%[^\n]%*c", command); //This gets the entire string and spaces
char *token;
token = strtok(command, " "); //token = the first string separated by a " "
if (strcmp(token, "help") == 0){
//do function
}
else if (strcmp(token, "go") == 0){ //if the command has an argument, you have to get the next string
token = strtok(NULL, " "); //this gets the next string separated by a space
if (strcmp(token, "north") == 0){
//do function
}
}
You can keep using token = strtok(NULL, " "); until token = NULL signifying the end of a string
I have been trying to get a string input from a user using fgets
but fgets does not wait for input so upon investagation I learned of the gets function which seems to be working fine. My questions are: 1. Why does gets work when I input more than 10 characters if I declared an array of only ten elements. Here is my code
#include<stdio.h>
int main(void){
char name[10];
printf("Please enter your name: ");
gets(name);
printf("\n");
printf("%s", name);
return 0;
}
my input when testing: morethantenletters
will output: 'morethantenletters'
Surely, this should have caused some errors, no? Since name is only ten elements long.
2. My next question is that my code also works when I use gets(&name) instead of gets(name)-- I do not understand why. The &name is sending the address of name.while name is just sending the value of it, no?
That is exactly why you should always use fgets to replace gets. The array name has only 10 elements, but you are trying to store in it more than it's capable of. fgets prevents the program from buffer overflow, but gets doesn't.
It's undefined behavior when you are using gets in this way, don't use it.
Since name is only ten elements long.
Anything accepted more than 10 will be buffer overrun and may cause run time issues. So make sure your size is right. hint: Use getline or fgets instead.
while name is just sending the value of it, no?
For char arrays, name is also address to its starting position.
Right now i am doing an assignment but find it very hard to parse the user input in C. Here is kind of input user will input.
INSERT Alice, 25 Norway Drive, Fitzerald, GA, 40204, 6000.60
Here INSERT is the command (to enter in link list)
Alice is a name
25 Norway Drive is an address
Fitzerald is a city
GA is a state
40204 is a zip code
6000.60 is a balance
How can I use scanf or any other method in C to properly take this as input? The biggest problem in front of me is how to ignore these "," and store these values in separate variables of appropriate data types.
Thanks everyone, i have solve the issue and here is the solution:
pch = strtok(NULL, ","); pch =
substr(pch, 2, strlen(pch)); //substr is my custom funcition and i believe you can tell by its name what it is doing.
strcpy(customer->streetAddress, pch);
Fast easy method:
Use fgets() to get the string from the user;
and strtok() to tokenize it.
Edit
After reading your comment:
Use strtok() with only the comma, and then remove trailing and leading spaces from the result.
Edit2
After a test run, I noticed you will get "INSERT Alice" as the first token. So, after all tokens have been extracted, run strtok() again, this time with a space, on the first token extracted. Or, find the space and somehow identify the command and the name from there.
If your input data format is fixed you can use something quick and dirty using [s]scanf().
With input of:
INSERT Alice, 25 Norway Drive, Fitzerald, GA, 40204, 6000.60
You might try, if reading from stdin:
char name[80], addr[80], city[80], state[80];
int zip;
double amt;
int res = scanf("INSERT %[^,], %[^,], %[^,], %[^,], %d, %f\n",
&name, &addr, &city, &state, &zip, &amt);
Should return the number of items matched (i.e. 6).
scanf() may be a bit tricky in this situation, assuming that different commands with different parameters can be used. I would probably use fgets() to read in the string first, followed by the use of strtok() to read the first token (the command). At that point you can either continue to use strtok() with "," as the delimiter to read the rest of the tokens in the string, or you could use a sscanf() on the rest of the string (now that you know the format that the rest of the input will be in). sscanf() is still going to be a pain due to the fact that it appears that an unspecified number of spaces would be allowed in the address and possibly town fields.