Can't compare argv? - c

I have this code:
if (argv[i] == "-n")
{
wait = atoi(argv[i + 1]);
}
else
{
printf("bad argument '%s'\n",argv[i]);
exit(0);
}
When this code gets executed I get the following error:
bad argument '-n'
I seriously don't know why it does that. Can someone explain?

String comparisons need a function in C - usually strcmp() from <string.h>.
if (strcmp(argv[i], "-n") == 0)
{
wait = atoi(argv[i + 1]);
}
else
{
printf("bad argument '%s'\n",argv[i]);
exit(0);
}
The strcmp() function returns a negative value (not necessarily -1) if the first argument sorts before the second; a positive value (not necessarily +1) if the first arguments sorts after the second; and zero if the two values are equal.

The == operator does not work on the contents of strings because strings are effectively character pointers in this application, and the pointer get compared.
To compare the contents of strings use strcmp or strncmp.

You are comparing pointers (argv[i] and of "-n" are a char* and a const char*).
Use strcmp() instead.

What you're really doing here is pointer comparison. argv[i] is not a string, it's a pointer to a location in memory at which the actual string starts. Use strcmp().

You're comparing pointers, not string contents. argv[i] and "-n" are two different strings, stored at two different locations in memory, even if the characters inside the strings are equal.

In C, the operator == compares for equality.
Values of the same numeric type are compared the straightforward way (i.e. 2 + 2 == 4 is true).
Values of different integer (and non-integer numeric) types undergo some conversion. See elsewhere.
Pointers are equal if the point at the same address.
String literals are placed in memory not overlapping any other thing; including not overlapping anything pointed to by argv[i] (for i = 0 to argc).
So you're comparing two unequal pointers; that's why. You want to use if (!strcmp(argv[i], "-n")) { ... }.

int equal(char* stringa, char* stringb) {
while((*stringa) && (*stringb)) {
if(*stringa!=*stringb)
return FALSE;
stringa++;
stringb++;
}
return TRUE;
}
is also working for me

Related

How can I debug this basic OR program?

I am a beginner in C programming.
I have written a program which is not functioning due to its 'OR' functionality. Here is a working code snippet:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* englishTest = 'yup';
if ( (englishTest == 'yup') || (englishTest == 'yep') || (englishTest == 'yas') || (englishTest == 'yah') )
{
printf("You may pass \n");
}
else
{
printf("You shall not pass \n");
}
return 0;
}
This is supposed to be C, not a scripting language.
There are two problems in this code:
char englishTest = 'yup';
englishTest is declared as char which in C is an integer type. It can hold only one character but you attempt to store three characters in it.
What you probably meant is:
char englishTest[] = "yup";
Please note the square brackets that denote an array (of chars). The array size can be optionally specified between the brackets. It is not specified here and the compiler uses the smallest value that can hold the string used for initialization ("yup"). This smallest value is 4: there are 3 characters in "yup" but C strings are terminated with the NULL character ('\0').
The second issue in your code is the comparison of strings. The strings are not primitive types in C. They are arrays of characters. Directly comparing two strings using the comparison operators doesn't produce the result you expect. It compares the addresses in memory where the two strings are stored, not their characters.
The C standard library provides several functions to compare two strings. The most straightforward string comparison function is strcmp(). It returns 0 if the two strings are identical, a negative value if the first string comes before the second string in the dictionary order or a negative value otherwise.
Your comparison code should be (note the C strings are enclosed in double quotes ""):
if (strcmp(englishTest, "yup") == 0 || strcmp(englishTest, "yep") == 0 ||
strcmp(englishTest, "yas") == 0 || strcmp(englishTest, "yah") == 0)
P.S. The OR operators (||) do not break anything here.

Why directly comparing string fails, but succeeds using char* [duplicate]

This question already has answers here:
Using the equality operator == to compare two strings for equality in C [duplicate]
(9 answers)
Closed 8 years ago.
In the following working code; instead of using *tofind, if I directly use the comparison
if(*argv[i] == "and")
it fails.
Why would that be?
/**
* Find index of the word "and"
* ./a.out alice and bob
*/
int main(int argc, char **argv) {
int i = 0;
char *tofind = "and";
while (argv[i] != NULL) {
if(*argv[i] == *tofind) {
printf("%d\n", i + 1);
break;
}
++i;
}
return 0;
}
if(*argv[i] == "and") shouldn't compile, I think you mean if (argv[i] == "and"), that would compare the pointers of the two, not the string content.
if (*argv[i] == *tofind) doesn't work as you expected either, it only compares the first character.
To compare strings, use strcmp():
if (strcmp(argv[i], tofind) == 0)
A "char*" is officially a pointer to a single char, for example to find points to a letter 'a'. You know that there are two more chars and a nul char, but officially it points to a single char.
Therefore, *argv[i] is the first character of an argument, and *tofind is always the letter 'a', so your code checks if the first character of an argument is an 'a'. Look at the strcmp function, which compares whole strings.
look at the type of
*argv[i] //its type is char
and of "and"
"and" //its type is const char * as it is decayed into pointer
so thats why you are unable to compare them.
while the type of
*tofind
is char and you can now compare the two.for more details see FAQs section 6.

Begginger, string in switch in C with sourcecode. Possible?

So basically I wanted to create a program in C, in wich you would input 2 character long string (mix of letter and noumber ex.r1,u2,i3,i4,r6) to be the input in my program. Later I want to put this string in SWITCH. Is this possible?
Here's my simple sourcecode. Please correct me on any mistakes :)
#include <stdio.h>
int main(void)
{
char string[2];
scanf("%s", &string);
switch (string)
{
case 'u1' :printf("%s\n", string);break;
default :printf("ERROR");break;
}
return 0;
}
Create a code based on the string and switch on that.
#define Code(a,b) (a + 256*b)
char string[3]; // 3 not 2
if (scanf("%2s", string) != 1) { // No &
Handle_Error();
}
int scode = Code(string[0], string[1]);
switch (scode) {
case Code('u', '1') : printf("%s\n", string); break;
case Code('r', '2') : printf("r2\n"); break;
...
default :printf("ERROR");break;
}
A switch(x) needs an integer value for x and string is an array. So the original approach will not work.
The program can use an integer based on the string for x and use the same method for generating the case values. Since there is only the first 2 char of the string are of interest, the int value is unique.
No, this is not possible. Switch only works with integral types in C (int, short, long, etc, as well as types defined with enum).
You can however use a simple if-else construct to get the same behavior:
if (strcmp(string, "ui" ) == 0) //test for string equality
{
printf("%s\n", string);
}
else
{
printf("ERROR")
}
We use strcmp instead of == because we are dealing pointers which almost certainly not compare equal even when the two strings have the same content.
strcmp(str1, str2) == 0 is the standard idoim in C for comparing two strings.
strcmp returns an integer representing how two strings compare to each other. 0 means they are equal, a negative number means that the first string is lexographically "less than" the second, and a positive number means that the first string is lexographically "greater than" the second. More info can be found here.
A switch won't work here.
You need to use an if/else if construct and strcmp to compare the strings.
Also, you need at least 3 characters in your input array so that it can hold the two input characters and the terminating null character.
Of course, such a small buffer can easily overflow.

C Programming : pointers/char array

I have a project that entails us as a programmer, to translate a line of assembly language into machine language and calculate the decimal. We have our own sample computer with opcodes to make it simpler to calculate. My question is if the following function does what I aim to do.
In the main function, I have an array of chars labeled char binary[3] since the value returned will be three bits. Also, in the function is a char opcode[MAXLINELENGTH] which reads in from a file properly the opcode line so I point to it with *string within the function. Will this correctly find the match and fill the binary array in main with the proper 3 digit bit code?
//function should return true if the proper binary output was successfuly copied with the matching opcode
int opcodeBinary(char *string,char *binary){
if(strncmp(*string,"add"){
*binary="000";
return 1;
}
else if(strncmp(*string,"nand"){
*binary="001";
return 1;
}
else if(strncmp(*string,"lw"){
*binary="010";
return 1;
}
else if(strncmp(*string,"sw"){
*binary="011";
return 1;
}
else if(strncmp(*string,"beq"){
*binary="100";
return 1;
}
else if(strncmp(*string,"jalr"){
*binary="101";
return 1;
}
else if(strncmp(*string,"halt"){
*binary="110";
return 1;
}
else if(strncmp(*string,"noop"){
*binary="111";
return 1;
}
else{
return 0;
}
}
No -- in fact, it shouldn't even compile. (Did you try compiling your code before posting it here?)
strncmp and strcmp return 0 if the strings are equal (and strncmp takes three arguments, not two!). To compare two strings for equality, you want something like:
if (strncmp(string, "nand", 4) == 0) {
...
Or, more simply:
if (strcmp(string, "nand") == 0) {
...
Since the string literal "nand" sets a limit on the number of characters to be compared, there's not much point in using strncmp rather than strcmp`.
Both arguments to strcmp (or the first two arguments to strncmp) are of type char*. string is already of type char*; assuming it points to (the first character of) a string, just pass string, not *string, as the first argument to strcmp.
*binary = "000"; shouldn't even compile. binary = "000"; would compile, but it wouldn't do what you want; it's a pointer assignment, and it only affects the value of binary, which is local to your function; there's no visible effect once the function returns.
You can either make the second argument to your function a char**; then the caller can do something like:
char *binary;
if (opcodeBinary(some_string, &binary) {
/* binary now points to a string like "000" */
}
Or the caller can allocate space for the string:
char binary[5]; /* or whatever size you need */
and then inside your function, replace the assignment by a call to strcpy:
strcpy(binary, "000");
You can't return an array from a function; there are several ways you can accomplish the same thing indirectly, but they're all somewhat tedious.
Your function opCodeBinary does not typecheck. When assigning *binary="000", the left hand side is an lvalue of type char and the right hand side is a char*. The same is true for the first operand to strncmp. You should not prepend a * when using strings in C.
What I assume you are required to do is to generate the binary opcode that corresponds to an assembly command. You should read the command from string and write the opcode to binary. There are several things that you do wrong here:
You don't have a way to move the pointers string and binary, as you consume characters from your input and produce new binary opcodes to your output. This would be useful if you were to call the function opCodeBinary repeatedly.
I would suggest that you use double pointers for both parameters to opCodeBinary.
I assume you should not produce opcode 000 in ASCII representation (that is, the string "000") but one byte that contains it in binary form (or, worse, just three bits).
I'd suggest the following for your opCodeBinary function. It correctly resolves (1) and (2) above, but it assumes that each opcode goes to one or more (full) bytes in your binary.
int opCodeBinary (char **string, char **binary)
{
if (strncmp(*string, "add", 3) == 0) {
*string += 3;
*(*binary)++ = '\x00';
return 1;
}
...
}
using wrong strcnmp:
Passing character(dereferenced char pointer) instead of char pointer(string)
you need to pass the number of characters to compare, as a third argument.
Recommendation: Use a hash, to map keywords to binary codes

Using "strcmp" on specific members of a character array in c

I have a binary search function I am passing a pointer character array, the length of that array, a search pointer character array and another counter for something else.
int binarySearch(char* charArray, int len, char* searchItem, int counter)
{
int position;
int begin = 0;
int end = len-1;
int cond =0;
while(begin <= end)
{
position = (begin + end)/2;
// searchItem is a pointer array and the value I want to compare to is
// at the index of counter (determined outside of this function)
if((cond = strcmp(&charArray[position], &searchItem[counter])) == 0)
{
return position;
}
else if(cond < 0){
begin = position + 1;
}
else
end = position - 1;
}
return -1;
}
From here, going through the code by hand seems to make me want to think it should work fine, however it doesn't. I think I'm getting thrown off somewhere along the lines of my pointers and how I'm referring to them so the wrong data is being compared.
I've looked at it for too long now... really need some help here.
It is not very clear what is being searched in what. But I'm guessing that you are searching for a character in a sorted character array. If that is the case, you can't use a strcmp. Instead you can do:
if(cond = (charArray[position] - *searchItem) == 0)
strcmp assumes that the strings being compared are zero-terminated, and exactly equal length. Therefore, strlen(&charArray[position]) has to equal strlen(&searchItem[counter]). That means position == strlen(&charArray[0]) - strlen(&searchItem[counter]). You don't need to search at all. Either the suffix of charArray matches or it doesn't.
But that's probably not what you intended. What are you trying to achieve?
Are the strings to be compared all of the exact same length? Your code is assuming so. If not, you'll want to use strncmp( ), not strcmp().
strcmp compares all the characters in a char* up to the trailing '\0' character. So you cannot compare single characters (basically you always need two, the character and the trailing '\0') and you cannot compare parts of a string unless you insert a '\0' at the location up to which you want to perform the comparison.
Just for clarity, properly zero terminated strings (last character is '\0') are important for strcmp. strcmp compares two character arrays from the start up to the '\0' character and returns an appropriate comparison value (<0, =0, >0). And of course, both character arrays have to be the same length.
If these are ASCII strings and should be sorted in alphabetic order, I believe it should be
else if(cond < 0){
end = position - 1;
}
else
begin = position + 1;
}
I'm not certain how you wish to sort them though?

Resources