Using pointer in boolean expression of if statement - c

I am getting input as argv, argc and I want to return TRUE of FALSE according to the input. My code is :
int is_valid_regexp(const char* regexp);
int main(int argc, char *argv[])
{
if (!is_valid_regexp(argv[1])){
fprintf(stderr, "wrong regular expression format:%s", argv[1]);
return(EXIT_FAILURE):
}
return (EXIT_SUCCESS);
}
int is_valid_regexp(const char* regexp)
{
do{
if(*regexp == '\\')
return FALSE;
}while (regexp++ != '\0');
return TRUE;
}
The program executes and then stops working. I think something is wrong with if(*regexp == '\\') return FALSE - the program works well if I exclude that part. Does it have something to do with pointer problem?

}while (regexp++ != '\0');
Here, regexp is a POINTER, which is equal to address of area of memory. regexp++ just shift right on one position this pointer. As type of pointer is size_t (unsigned __int32) you go outside your string.
Use
`}while (*regexp++ != '\0');`
to solve your problem.

Related

Evaluation of expressions like if( argv[1][0] != ~'t')

I have to input a string to make the second if condition false and print "Correct!". Can it be done?
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
if(argc != 2) { // argc is how long argv is, including that path-to-self
puts("You need to give me exactly one argument!");
return -1;
}
// argv[1] represents the command line input you have given to the program. Which is a string or a char array.
if(argv[1][0] != ~'t' || argv[1][1] != ~'h' || argv[1][2] != ~'e') {
puts("noooo!");
return 0;
}
else printf("Correct!\n");
return 0;
}
If an argument is passed to the program (i.e. the first argc != 2 check doesn't fail) then the expression argv[1][0] != ~'t' will always be true (as well as the other checks but those won't be made because of short-circuit evaluation).
The expression ~'t' will first be converted to an int (see this reference for why, the same thing will happen to argv[1][0]). That means you will have ~0x00000074 (if using the ASCII alphabet and 32-bit int). That will evaluate as 0xffffff8b.
It doesn't matter what argument you give your program, argv[1][0] will never be equal to 0xffffff8b and so the condition is true.

Comparing C strings vs. string pointers for equality

So I am working on a project to create and use a shell. One thing that must be done is "|executable| -p |prompt| should allow the user to select an user-defined prompt. Otherwise, the default should be “257sh> ”. I wrote my code to do this however no matter what it keeps moving into the else statement. After some experimenting I know that my argv[1] == "-p" line is what is causing the issue, because without it the code works. The thing is that when I print out argv[1], it prints "-p" (assuming thats what I input). Here is my shell function.
void shellLoop(char *n)
{
char *line;
char **args;
int status;
char name = n;
do{
printf("%s>", n);
line = sysReadLine();
args = splitLine(line);
status = execute(args);
free(line);
free(args);
}while(status);
}
And here is my main function
int main(int argc, char *argv[])
{
if(argc == 3 && argv[1] == "-p"){
shellLoop(argv[2]);
}
else{
shellLoop("257sh");
}
return EXIT_SUCCESS;
}
When you do argv[1] == "-p" you compare two pointers, and two pointers that will never be the same.
To compare strings in C you use the strcmp function: strcmp(argv[1], "-p") == 0.
You can also use strncmp(char *str1,char *str2,int n) to compare the first n bytes of two strings.

How to check if a particular string is a numeric value of character value?

I would like to understand how to validate a string input and check whether the entered string is Numeric or not? I belive isdigit() function is the right way to do it but i'm able to try it out with one char but when it comes to a string the function isn't helping me.This is what i have got so far,Could any please guide me to validate a full string like
char *Var1 ="12345" and char *var2 ="abcd"
#include <stdio.h>
#include <ctype.h>
int main()
{
char *var1 = "hello";
char *var2 = "12345";
if( isdigit(var1) )
{
printf("var1 = |%s| is a digit\n", var1 );
}
else
{
printf("var1 = |%s| is not a digit\n", var1 );
}
if( isdigit(var2) )
{
printf("var2 = |%s| is a digit\n", var2 );
}
else
{
printf("var2 = |%s| is not a digit\n", var2 );
}
return(0);
}
The program seems to be working fine when the variables are declared and initialized as below,
int var1 = 'h';
int var2 = '2';
But i would like to understand how to validate a full string like *var =" 12345";
Try to make a loop on each string and verify each char alone
isdigit takes a single char, not a char*. If you want to use isdigit, add a loop to do the checking. Since you are planning to use it in several places, make it into a function, like this:
int all_digits(const char* str) {
while (*str) {
if (!isdigit(*str++)) {
return 0;
}
}
return 1;
}
The loop above will end when null terminator of the string is reached without hitting the return statement in the middle, in other words, when all characters have passed the isdigit test.
Note that passing all_digits does not mean that the string represents a value of any supported numeric type, because the length of the string is not taken into account. Therefore, a very long string of digits would return true for all_digits, but if you try converting it to int or long long you would get an overflow.
Use this
int isNumber(const char *const text)
{
char *endptr;
if (text == NULL)
return 0;
strtol(text, &endptr, 10);
return (*endptr == '\0');
}
then
if (isNumeric(var1) == 0)
printf("%s is NOT a number\n", var1);
else
printf("%s is number\n", var1);
the strtol() function will ignore leading whitspace characters.
If a character that cannot be converted is found, the convertion stops, and endptr will point to that character after return, thus checking for *endptr == '\0' will tell you if you are at the end of the string, meaning that all characters where successfuly converted.
If you want to consider leading whitespaces as invalid characters too, then you could just write this instead
int isNumber(const char *text)
{
char *endptr;
if (text == NULL)
return 0;
while ((*text != '\0') && (isspace(*text) != 0))
text++;
if (*text == '\0')
return 0;
strtol(text, &endptr, 10);
return (*endptr == '\0');
}
depending on what you need, but skipping leading whitespace characters is to interpret the numbers as if a human is reading them, since humans "don't see" whitespace characters.

While loop not stopping when arguments are equal [duplicate]

This question already has answers here:
How to compare strings in an "if" statement? [duplicate]
(5 answers)
Closed 8 years ago.
I am running this program with with ./crack 50yoN9fp966dU
50yoN9fp966dU is crimson encrypted. which is on the word list. My program is as follow:
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if(argc > 2)
{
printf("Invalid Argument \n");
return 1;
}
else
{
FILE *fp1;
fp1 = fopen("/usr/share/dict/words", "r");
char line[9];
while (fgets(line, 9, fp1) != NULL)
{
char *EncryptLine1;
char *EncryptLine2;
printf("%s", line);
EncryptLine1 = crypt(line, "50");
if(argv[1] == EncryptLine1)
{
printf("%s \n", line);
}
EncryptLine2 = crypt(line, "HA");
if(argv[1] == EncryptLine2)
{
printf("%s \n", EncryptLine2);
}
}
}
}
If I add a printf("%s", EncryptLine1), I see the argv[1], i.e 50yoN9fp966dU, but the loop continue and does not print the answer.
You are doing pointer comparison instead of contents (pointed data) comparison.
Change this:
if (argv[1] == EncryptLine1)
To this:
if (strcmp(argv[1],EncryptLine1) == 0)
And this:
if (argv[1] == EncryptLine2)
To this:
if (strcmp(argv[1],EncryptLine2) == 0)
You have some problems in your code:
You blithely assume argc will never be smaller than 2. Check for unequal 2 instead of bigger two in your first condition.
Anyway, if you return out of an if-block, using else and doing deeper nesting is really superfluous.
Strings cannot be compared with ==, use strcmp.:
if( ! strcmp(argv[1], EncryptLine1))
You need to add a break to break out of the loop or a return to leave the function in your conditional block after printing success, if you want to end the loop there.
if( ! strcmp(argv[1], EncryptLine1)) {
printf("%s \n", line);
break;
}
BTW: Why don't you reuse EncryptLine1 (not that you need any temporary at all there)?
argv[1], EncryptLine1 and EncryptLine2 are all char*s. operator== on two char*s simply checks to see if they are pointing to the same memory location. What you want is to compare the contents of the strings they represent. So, the ifs should look like this:
if(!strcmp(argv[1], EncryptLine1))

strlen inconsistent with zero length string

I'm creating a DataStage parallel routine, which is a C or C++ function that is called from within IBM (formerly Ascential) DataStage. It is failing if one of the strings passed in is zero length. If I put this at the very first line of the function:
return strlen(str);
then it returns 0 for the calls that pass in empty values into str. If I put this at the first line, however...
if (strlen(str)==0) {return 0;}
then it does not return and goes into an infinite loop
I'm baffled - it works fine in a test harness, but not in DataStage.
Maybe there is something odd about the way DataStage passes empty strings to C routines?
int pxStrFirstCharList(char *str, char *chars )
{
if (strlen(str)==0) {return 0;}
if (strlen(chars)==0) {return 0;}
int i = 0;
//Start search
while (str[i]) //for the complete input string
{
if (strchr(chars, str[i]))
{
return i+1;
}
++i;
}
return 0;
}
There is a builtin function for what you are doing, it's called strcspn. This function takes two strings, and searches the first one for the first occurance of any of the characters of the second string.
I suggest using that than RYO...
http://www.cplusplus.com/reference/clibrary/cstring/strcspn/
How about this?
int pxStrFirstCharList(char *str, char *chars )
{
if (str && chars && (0 != strlen(str)) && (0 != strlen(chars)))
{
int i = 0;
//Start search
while (str[i]) //for the complete input string
{
if (strchr(chars, str[i]))
{
return i+1;
}
++i;
}
}
return 0;
}
Also, I don't quite get the point of the while loop ... (and no, I don't mean that this could be written as for). What I mean is that on one hand you are doing a search (strstr) that itself will be implemented as a loop and still you have some outer loop. Could it be that you actually wanted to have chars in its place, i.e.:
int pxStrFirstCharList(char *str, char *chars )
{
if (str && chars && (0 != strlen(str)) && (0 != strlen(chars)))
{
int i = 0;
//Start search
while (chars[i]) //for the complete input string
{
if (strchr(str, chars[i]))
{
return i+1;
}
++i;
}
}
return 0;
}
...? That is, look for each of the characters within chars inside the string denoted by str ...
If NULL is not explicitly part of the game, at least during development phase, it's always a good idea to add a precondition check on pointers received by a function:
int pxStrFirstCharList(char *str, char *chars )
{
if (!str)
return -1;
if (!chars)
return -2;
....
(The negative values -1 and -2 than tell the caller that something went wrong)
Or doing it in a more relaxed way, silently accepting NULL pointer strings as ""-string:
int pxStrFirstCharList(char *str, char *chars )
{
if (!str)
return 0;
if (!chars)
return 0;
...
If you are the only one using this API you could #ifndef BUILD_RELEASE these checks away for a release build if anything is tested stable.
I guess it is the strlen's issue when the length of the string is 0. For example,
char s1[0];
char *s2="a";
printf("%d %s\n", sizeof(s1), s1);//0 #
printf("%d %s\n", strlen(s1), s1);//3 #
printf("%d %s\n", sizeof(s2), s2);//8 a
printf("%d %s\n", strlen(s2), s2);// 1 a
You will get a weird answer for using strlen and you can check its source code in detail(https://code.woboq.org/userspace/glibc/string/strlen.c.html). In nutshell, you can use sizeof instead of strlen for char string or avoid 0 length case by using strlen.

Resources