I'd like to be able to compare a character on stdin with a characters of my specification. The purpose of this is to filter out every other input as wrong, while maintaining only the specified single chars as commands. Like on stdin "nn" or "qddaw" -> wrong go again but "n" make something useful.
Here is what I have in mind "code-wise":
if (input does not contain 'c' or 's' or 'q' or 'n') {
printf("some kind of error");
}
Well I tried to create an array with specified characters like array[] = {'a', 'b', 'c'} so I could be able to compare it with a string on the stdin with function strncmp.. like
char c[256];
scanf("%s", c)
if (strncmp(array, c, 1) != 0) printf("error");
but it doesn't seem to work. Any suggestions?
Edit1: Here is actual piece of code:
char c[256];
char* s = "nsrld";
char* quiter = "q";
do
{
printf(">");
scanf("%s", c);
if (only when there is no 'n' or 's' or other char from char* s on input)
{
errorHandle(ERROR_WRONG_CMD);
}
scanf("%*[^\n]"); scanf("%*c");
} while (strcmp(c,quiter) != 0);
as you can see I handled the 'q' thing quite well, but multiple chars are pain in the ass. Thanks for any advice.
Edit 2: or in other words I need a function which will compare input with a set of given characters and only if there is one OR another (like 'q' or 's' the function will pass (but not if there are characters together like 'qs')
I didn't make myself clear enough. What I need is input "type what ever you want" like "wwqwqe" and do the error unless the input is just 'c' or just 's' (and a few more).
char usersInput[200] = ""; /* A buffer to hold the input values */
char *result = gets(usersInput); /* Fill the buffer from stdin */
if (result != NULL) /* If we got something */
{
if (strlen(usersInput) == 1) /* the input must be exactly 1 character */
{
char ch = usersInput[0];
if (strchr(ch, "csqn") == NULL) /* It must be a valid values */
{
printf("Evil Bad Character <%c>\n", ch);
}
else
{
/* Do stuff with the known valid input value ch */
}
}
else
{
puts("The input value must be exactly 1 character\n");
puts("and must be 'c', 's', 'q' or 'n'");
}
}
else
{
puts("EOF or ERROR while reading stdin\n");
}
This should do the job.
One warning. gets is not smart enough to know that usersInput is 200 characters long.
It will gleefully let you type in 201 characters or more, which overwrites other characters in memory. That sort of thing can lead to hard-to-find bugs.
int ch = getchar();
if (ch != EOF)
{
if (strchr("csqn", ch) == NULL)
{
printf("Evil Bad Character <%c> in Hex %02X\n", ch, ch);
}
else
{
/* Do stuff with ch */
}
}
else
{
printf("EOF on input\n");
}
char c = getchar();
switch (c) {
case 'c':
case 's':
case 'q':
case 'n':
do_something();
break;
default:
print_error();
};
The above code should work. I don't know why your if statement wasn't working. Generally a switch works well in this type of scenario too.
Your first solution should work. If that's the exact same code you posted - then your problem might because the printf needs a newline at the end to flush to console.
I have thought the string as sets... So if the intersection of them is the void set then we will fail -> printf("Error")... otherwise the output is none...
#include <stdio.h>
#include <string.h>
int intersection(char* source, char* search)
{
int i,j;
for(i = 0; i < strlen(search); i++)
if(strchr(source,search[i]))j++;
if(j != strlen(search))return 0;
else return 1;
}
int main()
{
char *letters = "eo";
char *p = "hello";
int e = intersection(p,letters);
if(e==1)puts("Non Void");
else puts("Void");
}
While it looks as if you've got a solution, it might be worth mentioning that what you're asking for doesn't sound as if it's all that far away from the standard 'getopt' functionality... See http://www.gnu.org/software/libc/manual/html_node/Getopt.html for example.
This worked for me:
char c[256];
char* s = "nqsrld";
char* quiter = "q";
do
{
printf(">");
scanf("%s", c);
if ((strpbrk(s, c) == 0) || (strlen(c) >= 2))
{
errorHandle(ERROR_WRONG_CMD);
}
scanf("%*[^\n]"); scanf("%*c");
} while (strcmp(c,quiter) != 0);
Thanks to everyone for their help.
Write a function
int IsGood(int c)
{
if(c=='a'||c=='b'||c=='c')
return 1;
else
return 0;
}
Related
I m trying to do this little programm with defensive programming but its more than difficult for me to handle this avoiding the Loop-Goto as i know that as BAD programming. I had try with while and do...while loop but in one case i dont have problem. Problem begins when i m going to make another do...while for the second case ("Not insert space or click enter button"). I tried and nested do...while but here the results was more complicated.
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i;
int length;
char giventext [25];
Loop:
printf("String must have 25 chars lenght:\n");
gets(giventext);
length = strlen(giventext);
if (length > 25) {
printf("\nString has over %d chars.\nMust give a shorter string\n", length);
goto Loop;
}
/* Here i trying to not give space or nothing*/
if (length < 1) {
printf("You dont give anything as a string.\n");
goto Loop;
} else {
printf("Your string has %d\n",length);
printf("Letter in lower case are: \n");
for (i = 0; i < length; i++) {
if (islower(giventext[i])) {
printf("%c",giventext[i]);
}
}
}
return 0;
}
Note that your code is not defensive at all. You have no way to avoid a buffer overflow because,
you check for the length of the string after it has been input to your program so after the buffer overflow has already occurred and
you used gets() which doesn't check input length and thus is very prone to buffer overflow.
Use fgets() instead and just discard extra characters.
I think you need to understand that strlen() doesn't count the number of characters of input but instead the number of characters in a string.
If you want to ensure that there are less than N characters inserted then
int
readinput(char *const buffer, int maxlen)
{
int count;
int next;
fputc('>', stdout);
fputc(' ', stdout);
count = 0;
while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n')) {
// We need space for the terminating '\0';
if (count == maxlen - 1) {
// Discard extra characters before returning
// read until EOF or '\n' is found
while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n'))
;
return -1;
}
buffer[count++] = next;
}
buffer[count] = '\0';
return count;
}
int
main(void)
{
char string[8];
int result;
while ((result = readinput(string, (int) sizeof(string))) == -1) {
fprintf(stderr, "you cannot input more than `%d' characters\n",
(int) sizeof(string) - 1);
}
fprintf(stdout, "accepted `%s' (%d)\n", string, result);
}
Note that by using a function, the flow control of this program is clear and simple. That's precisely why goto is discouraged, not because it's an evil thing but instead because it can be misused like you did.
Try using functions that label logical steps that your program needs to execute:
char * user_input() - returns an input from the user as a pointer to a char (using something other than get()! For example, look at scanf)
bool validate_input(char * str_input) - takes the user input from the above function and performs checks, such as validate the length is between 1 and 25 characters.
str_to_lower(char * str_input) - if validate_input() returns true you can then call this function and pass it the user input. The body of this function can then print the user input back to console in lower case. You could use the standard library function tolower() here to lower case each character.
The body of your main function will then be much simpler and perform a logical series of steps that tackle your problem. This is the essence of defensive programming - modularising your problem into separate steps that are self contained and easily testable.
A possible structure for the main function could be:
char * user_input();
bool validate_input(char *);
void str_to_lower(char *);
int main()
{
char * str_input = user_input();
//continue to get input from the user until it satisfies the requirements of 'validate_input()'
while(!validate_input(str_input)) {
str_input = user_input();
}
//user input now satisfied 'validate_input' so lower case and print it
str_to_lower(str_input);
return 0;
}
I had a program to check user input and make sure it's only integer and not character. In my main function, do while loop only executes once when the input is incorrect. But I want it to keep it executing until the user enter a valid input. My doAgain() function is to ask if the user want to Try again or not. The problem is with doAgain() function. It only executes once if leave it in the if statement. Everything works fine except this glitch. However, when i remove it, the loop keep executing until the user enter valid input like i wanted it to, but then doAgain() function would be useless
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* get boundary */
char* getBoundary(char str[]){
int i;
char c;
str = (char*) malloc(sizeof(char));
for (i = 0; (c = getchar()) != '\n'; i++) // The loop stop running after the second time
{
str = (char *) realloc(str, sizeof(char) + i);
str[i] = c;
}
str[i] = '\0';
return str;
}
/* check for valid string */
int checkStr(const char *check)
{
unsigned i;
size_t len = strlen(check);
for (i = 0; i < len; i++)
if(isalpha(check[i]))
{
printf("Invalid integer formatt!!!");
return 0;
}
return 1;
}
/* Ask if do again */
int doAgain(void)
{
char ans, c;
do {
printf("Do you want to try again?: ");
scanf(" %c", &ans);
switch (ans)
{
case 'y':
case 'Y':
case 'n':
case 'N':
return (ans == 'y') || (ans == 'Y') ? 1 : 0;
break;
default:
printf("Invalid answer!!! answer 'y' and 'Y' or 'n' and 'N' only\n");
do { /* flush input stream */
c = getchar();
}while (c != '\n');
}
}while (1);
}
/* Main */
int main(void)
{
char *l_boundRow;
l_boundRow = NULL;
do {
printf("Enter lower bound row: ");
l_boundRow = getBoundary(l_boundRow);
if (!checkStr(l_boundRow) && doAgain()) // problem start here, it works if I remove doAgain() function
continue; // if the string is invalid, the program asks user if they want to try again
else
break;
}while (1);
free(l_boundRow);
return 0;
}
Revised answer
The immediate problem is that when doAgain() exits with y or n, it doesn't read the newline after those characters, so when it re-enters getBoundary(), the first character it reads is whatever was after the y or n which was probably a newline, which terminates the input line. You need to gobble the rest of the line on a valid input as well as on the invalid ones.
This code mostly works — it is leak free, too (at least under my casual testing).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char* getBoundary(void);
int checkStr(const char *check);
int doAgain(void);
/* get boundary */
char* getBoundary(void)
{
int i;
int c;
char *str = (char*) malloc(sizeof(char));
for (i = 0; (c = getchar()) != '\n' && c != EOF; i++)
{
str = (char *) realloc(str, 2 + i);
str[i] = c;
}
str[i] = '\0';
return str;
}
/* check for valid string */
int checkStr(const char *check)
{
unsigned i;
size_t len = strlen(check);
for (i = 0; i < len; i++)
{
if (!isdigit(check[i]))
{
printf("Invalid integer format (%s)!!!\n", check);
return 0;
}
}
return 1;
}
static int gobble(void)
{
int c;
while ((c = getchar()) != EOF && c != '\n')
;
return c;
}
/* Ask if do again */
int doAgain(void)
{
char ans;
int c;
do {
printf("Do you want to try again?: ");
scanf(" %c", &ans);
switch (ans)
{
case 'y':
case 'Y':
c = gobble();
return 1;
case 'n':
case 'N':
c = gobble();
return 0;
default:
{
printf("Invalid answer!!! answer 'y' and 'Y' or 'n' and 'N' only\n");
c = gobble();
if (c == EOF)
{
printf("EOF detected\n");
return 0;
}
}
}
} while (1);
}
/* Main */
int main(void)
{
char *l_boundRow;
l_boundRow = NULL;
do {
printf("Enter lower bound row: ");
l_boundRow = getBoundary();
if (checkStr(l_boundRow))
break;
if (!doAgain())
break;
free(l_boundRow);
}while (1);
printf("Final bound row: %s\n", l_boundRow);
free(l_boundRow);
return 0;
}
If you select not to try again after an invalid input, the last invalid value is printed as the 'Final bound row'. You can easily hack the code to avoid that problem.
Incidentally, when I first compiled your code, I only got 3 warnings from it under my default stringent options — because I demand prototypes before (non-static) function definitions. That's extremely good; well done. Few people write code that's posted on SO that passes that level of scrutiny with as few complaints.
If it were my code, I would have few if any do … while loops (none in this code). They are occasionally useful, but occasionally is the operative term. Generally, it is best to use a top-testing while loop, or an explicit for loop.
Original answer
A real problem, but not the one immediately causing trouble.
In the code in getBoundary(), you first allocate one character. Then, in the body of the loop, you reallocate i + 1 characters. On the first iteration, you reallocate 1 byte; then 2, etc. And then when you exit the loop, you write one beyond the last character that was allocated, which leads to undefined behaviour. You need to use i + 2 as the size to reallocate. (There are those who'd rail against you for using sizeof(char) since that is guaranteed to be 1.)
That is probably the source of your trouble; writing beyond the end of an allocated buffer can easily lead to crashes.
If you ran the code under valgrind, it would tell you about this mistake.
Separately, it is not a good idea to allocate one more byte each time around the loop. It would be better to allocate, say, 20 bytes (big enough to hold any 64-bit integer value), or to double the size on each iteration when you need more space. It isn't going to be time critical in this context, but it can become a problem in bigger programs.
Note too that your checkstr() function only detects alpha characters; punctuation and control characters will also not convert to an integer. You should check that each character is a digit (isdigit(check[i])), and you might have to worry about plain char being signed — so isdigit((unsigned char)check[i]) is better still. Similar comments apply to the other isuvwxyz() functions.
In doAgain(), you should use int c; instead of char c; and you should check for EOF as well as newline. If you detect EOF, the answer is 'no' and you should return that.
Also, in your getBoundary() function again, you have:
str = (char *) realloc(str, sizeof(char) + i);
There are those who would castigate you for the cast; I am not of the mindset that does that. But be aware that you will get criticism for doing so from many people who answer questions on C at SO.
More significantly, you should not write the realloc() code this way. The idiom:
ptr = realloc(ptr, new_size);
leaks memory if the allocation fails. You've just had the only pointer to the memory wiped out with NULL, even though realloc() promises that it did not free the old memory. You should use:
void *new_ptr = realloc(ptr, new_size);
if (new_ptr == NULL)
…handle out of memory condition…ptr is still valid!
ptr = new_ptr;
You should also always check that memory allocations succeed. If they fail, you end up dereferencing a null pointer, which leads to crashes.
I'm trying to write a code that asks the user to enter a string and takes of all characters except the alphabetical.
Now i did it myself and it doesn't seem to work properly. I'm new to strings so i'm trying to understand and master strings. I tried to use gdb on mac but i don't have all the functions to understand this.
Could you please help?
What the code must do: User inputs (for example): h**#el(l)o&^w
and the output is hello.
here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int i;
int seen = 0;
printf("Enter String: ");
scanf("%s", string);
for (i=0; string[i]!='\0'; i++)
{
if (((string[i]<='a' || string[i]>'z')&&(string[i]<='A' || string[i]>'Z')) ||string[i]!='\0')
{
seen = 1;
}
else
seen = 0;
}
if (seen==0)
{
printf("%s", string);
}
}
well, your code has a couple of important problems:
you're not checking boundaries when iterating… what if I type in a 101 characters string? and a 4242 characters string?
next problem, is that scanf("%s", …) is considered dangerous, for the same reasons
so basically, what you'd want is to use fgets() instead of scanf().
But why not just get the input character by character, and build a string that has only the chars you want? It's simpler and flexible!
basically:
#include <ctype.h>
int main() {
char* string[100];
int i=0;
printf("Enter your string: ");
do {
// getting a character
char c = getchar();
// if the character is alpha
if (isalpha(c) != 0)
// we place the character to the current position and then increment the index
string[i++] = c;
// otherwise if c is a carriage return
else if (c == '\r') {
c = getchar(); // get rid of \n
// we end the string
string[i] = '\0'
}else if (c == '\n')
// we end the string
string[i] = '\0';
// while c is not a carriage return or i is not out of boundaries
} while (c != '\n' || i < 100);
// if we've got to the boundary, replace last character with end of string
if (i == 100)
string[i] = '\0';
// print out!
printf("Here's your stripped string: %s\n", string);
return 0;
}
I did not run it on my computer because it's getting late, so my apologies in case of mistakes.
Addendum:
wee the program skips my statement and shuts down
that's because your condition is inversed, and remove the \0 condition, as it will always happen with the scanf() that always append \0 to the string to end it. Try exchanging seen = 1 and seen = 0 or try using the following condition:
if ((string[i]>='a' && string[i]<='z')||(string[i]>='A' && string[i]<='Z')))
seen = 1;
else
seen = 0;
or simply, use ctypes's isalpha() function, like in our two examples!
No part(remove the extra characters) to change the string in your code.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *filter(char *string, int (*test)(int)) {
char *from, *to;
for(to = from = string;*from;++from){
if(test(*from))
*to++ = *from;
}
*to = '\0';
return string;
}
int main(){
char string[100];
printf("Enter String: ");
scanf("%99s", string);
printf("%s\n", filter(string, isalpha));
return 0;
}
I have the following code in C:
#include "stdafx.h"
#include <stdlib.h>
#include <cstring>
#include <ctype.h>
int main()
{
char buffer[20];
int num;
bool valid = true;
printf("Please enter a number\n");
fgets(buffer, sizeof(buffer), stdin);
printf("\n\n");
if(!isdigit(buffer[0])) //Checking if the first character is -
{
if(buffer[0] != '-')
{
valid = false;
}
else
{
if(!isdigit(buffer[1]))
{
valid = false;
}
}
}
char *pend = strrchr(buffer, '\n'); //Replacing the newline character with '\0'
if (pend != NULL)
{
*pend = '\0';
}
for (int i = 1; i < strlen(buffer); i++) //Checking that each character of the string is numeric
{
if (!isdigit(buffer[i]))
{
valid = false;
break;
}
}
if(valid == false)
{
printf("Invalid input!");
}
else
{
num = atoi(buffer);
printf("The number entered is %d", num);
}
getchar();
}
Basically, the code ensures that the user input is a positive or negative whole number. No letters, floating point numbers etc. are allowed.
The code works perfectly and does its job well.
However, the code is too long and I have to implement it in a number of programs. Is there a simple way to perform all of the above in C? Maybe a shorter alternative that ensures that the input is:
i) not a letter
ii) a positive or negative WHOLE number
bool valid = false;
char *c = buffer;
if(*c == '-'){
++c;
}
do {
valid = true;
if(!isdigit(*c)){
valid = false;
break;
}
++c;
} while(*c != '\0' && *c != '\n');
Note: this will not handle hex values, but will pass octal (integers starting in 0)
I also have to agree that this should be placed in a common library and called as a function.
Although some people have pointed out that strtol may not give you the errors you need, this is a very common type of thing to do, and therefore it does exist in the standard library:
http://www.cplusplus.com/reference/cstdio/sscanf/
#include <stdio.h>
// ....
valid = sscanf (buffer,"%d",&num);
Another comment is that you should not be afraid of writing complicated and useful code, and modularizing it. Create a library for the input parsing routines you find useful!
I have this function which is a menu. After compiling, the following error keeps showing up: error: comparison between pointer and integer [enabled by default]. why is this happening?
char choice;
printf ("Welcome to the Customer menu! \n");
printf ("Please select option from below\n");
printf ("a. Add customer\n");
printf ("b. Modify customer\n");
printf ("c. List customers\n");
printf ("d. Go back to main menu");
while ((gets(&choice)) != 'q')
{
if (choice == '\n')
continue;
switch (choice)
{
case 'a' : add_customer();
break;
case 'b' : printf ("products_main ()");
break;
case 'c' : printf ("orders_main ()");
break;
default : printf ("Invalid input. Please enter an option from the above menu\n");
continue;
}
printf ("END PROGRAM");
Thank you!!
The gets() function returns a char *, whereas you're comparing that return value to a char:
if (gets(&choice)) != 'q')
Also note that this is wrong in two levels, since gets() reads from stdin until it encounters a newline, so if you pass it the address of one char, it will likely cause a buffer overrun error. Why not use fgets() instead?
char buf[128];
fgets(buf, sizeof(buf), stdin);
if (buf[0] == 'q') {
/* etc */
}
You can't use gets() to do that, and afterall gets() is very dangerous, doesn't checks how much characters to read so can cause a very bad runtime buffer overflow.
You should use fgets() like H2CO3, it has a limit of characters to read, so is more secure.
char * input(const char *message, size_t quantity)
{
const int BUFFER_SIZE = 512;
char buf[BUFFER_SIZE], *res = NULL;
if(quantity > BUFFER_SIZE || quantity == 0)
quantity = BUFFER_SIZE - 1;
if(message)
printf("%s",message);
if(fgets(buf, quantity + 1, stdin) > 0)
{
char *end = strchr(buf, '\n');
if(end){
*end = '\0';
}
res = malloc(strlen(buf) + 1);
if(!res)
{
fprintf(stderr, "input(): MEM alloc error\n");
return NULL;
}
strcpy(res, buf);
}
return res;
}
Try with that function, just pass the message you want, and the exact quantity of characters of input that you want. :)
If you want to try it alone, here you have a test program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char * input(const char *message, size_t quantity)
{
const int BUFFER_SIZE = 512;
char buf[BUFFER_SIZE], *res = NULL;
if(quantity > BUFFER_SIZE || quantity == 0)
quantity = BUFFER_SIZE - 1;
if(message)
printf("%s",message);
if(fgets(buf, quantity + 1, stdin) > 0)
{
char *end = strchr(buf, '\n');
if(end){
*end = '\0';
}
res = malloc(strlen(buf) + 1);
if(!res)
{
fprintf(stderr, "input(): MEM alloc error\n");
return NULL;
}
strcpy(res, buf);
}
return res;
}
int main()
{
char *a = input("Input:", 4);
if(a)
{
printf("%s\n",a);
free(a);
return 0;
}
printf("Got NULL input\n");
return -1;
}
When you have a doubt about a particular function, what are their arguments, their return value, you could look it up in Google, and you will find plenty of examples and the function definition. With the time you will learn to easily understand the definitions and memorize some function names and their parameters.
Good Luck!
This line:
while ((gets(&choice)) != 'q')
gets() reads a string, not a char, and returns that string (i.e. it fills a buffer you pass to it via the char pointer). You then compare the pointer returned (which is the same as the one you passed in) with a char.
You probably just want to read a single character. If you want a whole string, you need to read it into a char array, and not pass the address of a single char.
After doing some reading I found that including
#include <unistd.h>
helps get ride of the warning. I'm new to unix c and I've never seen it before. I'm also still testing my code so I'll get back to you when I figure out if this works or not.
Hope this helps.
In the end the warning came back and it ended up going in an infinite loop so something is wrong with my logic.
Sorry I wasn't any help.