I want to store an array to element. So i used 2-D array, but seems it is not working. In this case i am getting 5 IEEE address which is array of 8 bytes. I want to store one by one according to which address in coming first
char a[5][8];
int i = 0;
if(data)
{
a[i] = es->ieee;
i++;
}
//it will receive 5 different address
I need to compare those IEEE address with already store IEEE address,for example there are 5 IEEE address
char First[8] = "0x32441";
char Second[8] = "0x42421";
if(a[1] == First)
{
printf("it is matching in First");
}
Can any one help me out
Let's call these "strings", since that seems to be how you think of them, despite that you say otherwise.
In C, a string is an array of char that ends with a char whose value is 0.
Strings are "assigned" (copied) with strcpy(), since you cannot directly assign an entire array, usually.
This would mean that your initial example probably should be something like:
if(data)
strcpy(a[i++], es->ieee);
it's hard to be sure, since you don't tell us what es is.
Also, strings are compared with the strcmp() function, you cannot use == to compare strings directly (since they are arrays, and arrays cannot be compared with == either).
This means that the second snippet should be:
if(strcmp(a[1], First) == 0)
printf("it is matching First\n");
C does not have array assignment. You need to use memcpy (or possibly strncmp, this seems one of the rare cases where it is actually appropriate function):
char a[5][8];
int i = 0;
if(data)
{
memcpy(a[i], es->ieee, 8);
i++;
}
And C does not support comparing arrays with operators either, so use memcmp function (or possibly strncmp, depending if you have null terminated strings or not):
char First[8] = "0x32441";
char Second[8] = "0x42421";
if(memcmp(a[1], First, 8) == 0)
{
printf("it is matching in First");
}
Related
I wrote a program that changes the order of any given array and now I wanted to print it. Often, I just use a for-loop for integers, chars and all the other types, because it looks like that this works every time. Nevertheless, I am curious about the short version and I would like to know when I can use it. At the moment it just prints stuff from a random place.
#include <stdio.h>
int main() {
int array1[] = { 4, 5, 2, 7, 5, 3, 8 };
int laenge = sizeof(array1) / sizeof(array1[0]);
printf("%d\n", laenge);
int array2[laenge];
for (int i = 0; i < laenge; i++) {
array2[laenge - 1 - i] = array1[i];
}
printf("%d\n\n", array2);
for(int j = 0; j < laenge; j++) {
printf("%d", array2[j]);
}
return 0;
}
When you say,
Nevertheless, Im curious about the short version and I would like to know when I can use it.
, I take you to be asking about this:
printf("%d\n\n", array2);
The short answer is "never".
A longer answer is that
the C standard library does not provide any functions for producing formatted output of whole arrays (except the various flavors of C strings as a rather special case), and in particular, printf does not provide such a facility; and
the particular printf call you present has undefined behavior, and even on its face does not mean what it sounds like you think it means. It is attempting to print a pointer (to the first element of array array1) as if that pointer were an int.
Often, I just use a for-loop for integers, chars and all the other types, because it looks like that this works every time.
If the loop uses the correct iteration and the body converts the array contents appropriately to a valid stream, it should work every time.
Nevertheless, I am curious about the short version and I would like to know when I can use it.
The only type of array for which printf has built-in support is arrays of char. If the array is null terminated, %s will print it, if it is not, %.*s can be used and the number of elements must be passed before the array pointer as an int argument.
Other types are not supported by default. Using a loop is the only portable solution.
At the moment it just prints stuff from a random place.
printf("%d\n\n", array2) has undefined behavior because %d expects an int argument and you pass a pointer to int. printf will retrieve an int value from the place where the code would have provided an int argument, array2 is passed as a pointer, possibly in a different place and with a different representation, so the output if any will be meaningless and the program could misbehave in other unpredictable ways.
There is no "short version" - except for strings, there's no format specifier for printf that will print the entire contents of an array at once.
There are a couple of reasons for this:
Arrays don't store any metadata about their size or type; when you declare an array like int a[N];, what you get in memory looks like +---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
No storage is allocated for anything other than the array elements themselves;
Under most circumstances, array expressions "decay" to pointers to their first element - when you called printf("%d\n\n", array2);
it was equivalent to calling it asprintf("%d\n\n", &array2[0]);
What printf received was not the contents of the array, but only a pointer to its first element. The %d conversion specifier expects its corresponding argument to be an int, so it will do its best to interpret that pointer value as an int, but the behavior is undefined and you can get anything from garbled output to having your program crash outright.
%s works for strings because it gets the address of the first character, then prints successive characters until it sees the zero terminator - its behavior is sort of like the following:
while ( *p )
putchar( *p++ );
This won't work for arrays where 0 can be a valid, in-band value, and again arrays don't know how big they are at runtime. So there's no good way to print the contents of an array with a single printf call.
That's just how C is. There are valid reasons for why the language works this way, but it means you don't have those sorts of conveniences.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C/C++: switch for non-integers
C/C++ switch case with string
I am passing a string to a function get_band(char *str)
Then I am comparing the passed argument with a specific string
if(strcmp(str, "auto"))
{
//do something
}
My question is - since i have many number of strings to compare, how can i use switch statement instead of if/else, since switch statement supports only integral type.
Short answer: you can't.
Long answer: this question is a duplicate of C/C++ switch case with string.
You could do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *words[] = {"one", "two", "four"}; // words is an array of pointers to char
void f(char *str);
int main(void) {
f("two");
return 0;
}
void f(char *str) {
int i;
for (i = 0; i < sizeof words/sizeof words[0]; i++) {
if (!strcmp(str, words[i])) {
/* Do something */
}
}
}
No, switch only works for integers.
If you want to optimize, you can use some data structure to determine if the string is any of the known strings. For example:
hash table
trie
some self-balancing binary search tree, like AVL tree or red-black tree
To make use of such a data structure, assign each known string a constant integer (e.g. define or enum); given a string, you can use the data structure to map it to some number of a known string (possibly with some number meaning "unknown"). Then you can use a switch on this number and do whatever you want for each case.
You can find an existing implementation of any of the above, but if you're new to C, it might be beneficial to implement it yourself.
A switch statement branches based on evaluating the following expression.
In your case, strcmp only promises to return less than zero, zero, or greater than zero. Even if you assume that means -1, 0, and 1 (respectively), that would mean you would only have 3 values you could choose from in your switch cases. [And that is not a safe assumption, by the way ...]
Instead, if your strings are taken from a closed set of strings (i.e. can only have one of set of values), you could tokenize the string. There are actually programs to do this for you, i.e. turns strings into tokens. (See flex(1).) This would mean that each string you expected would have some unique value, and you could switch on that value.
If this is too much trouble, just use the method you used in your question, i.e.:
if (strcmp("some string", str) == 0) {
// handle some string
} else if strcmp("some other string", str) == 0) {
// handle alternate case here
...
} else {
// handle error/default case here
}
Consider changing the logic of your program to use enums instead of strings. You can then use an array look up to map the integer enums to the corresponding string for display and logging purposes. The other options including hash etc have been covered.
The switch statement in C / C++ accepts only three case types : integers, characters and enumerated data types (which is effectively another way of saying integer). Characters also reduce to integers when evaluated as ascii codes.
#Nikolai N Fetissov made a good suggestion : switch on a hash of the string :
#define hashOfString1 <integer hash goes here>
#define hashOfString2 <integer hash goes here>
#define hashOfString3 <integer hash goes here>
. . .
switch (hashMyString("MyString")) {
case hashOfString1:
/* do this */
break;
case hashOfString2:
/* do that */
break;
case hashOfString3:
/* do other */
break;
default:
/* default behavior */
break;
}
I have this C function which attempts to tell me if a sub string is contained in a string.
int sub_string(char parent [1000], char child [1000]){
int i;
i = 0;
int parent_size = (int) strlen(parent);
int child_size = (int) strlen(child);
char tempvar [child_size];
int res;
res = 1;
while(i<(parent_size - child_size + 1) && res != 0){
strncpy(tempvar, parent + i, child_size);
if(strcmp(tempvar, child)==0){
res = 0;
}
i++;
memset(tempvar, 0, child_size);
}
memset(tempvar, 0, sizeof(tempvar));
return res;
}
Now the strange thing is, when I pass a string "HOME_DIR=/tmp/" and "HOME_DIR" it returns a 0 the first time round, but after I call this function again, it returns a 1 to say it hasn't found it!!
I am guessing this is a memory issue, but I can't tell where, I would appreciate any help on this.
Is there any reason you can't use the strstr function? Otherwise there are some things you should clean up in your code. For starters since you are limiting the length of the arrays coming in to 1000 characters you should use strnlen instead of strlen with a limit of 1000. You should also create you should zero out the tempvar array before you start copying into it. If parent is not null terminated you could run off the end of the array in your while loop. I would also suggest using strncmp and giving a length limit (in general if you are using the C string library you should use the 'n' version of the functions i.e. strnlen instead of strlen so that you put a bounding length on the operation, this helps to protect buffer overflows and potential security holes in your code).
I have noticed some issues with this program:
Use pointers instead of fixed char arrays. This is more space optimal. So your function definition becomes int sub_string(char *parent, int parent_len, char *child, int child_len). Please note that since I pass pointers I also need to pass the length of the string so I know how much to traverse. So now you access your string like so *(parent+i) in a loop.
i<(parent_size - child_size + 1) This condition looks a bit dicey to me. Let's say parent is 100 in len & child is 75. so this expression becomes i<26. Now your loop will terminate when i>26. So tempvar would have the parent_string till index 25. So how does this work again?
One problem is:
char tempvar [child_size];
strcmp below will compare child_size+1 characters (incl. terminating '\0'), therefore its undefined behaviour.
Do you know the C-standard functions strstr and strncmp?
sizeof(tempvar) does not return child_size.
Is there a way to know whether the element in a string in C has a value or not? I have tried using NULL, '', and ' ', but they don't seem to be working. I need to shift the characters down to index 0 without using stdlib functions.
#include <stdio.h>
int main()
{
char literal[100];
//literal[99] = '\0'
literal[98] = 'O';
literal[97] = 'L';
literal[96] = 'L';
literal[95] = 'E';
literal[94] = 'H';
int index = 0;
while(literal[index] != '\0')
{
if(literal[index] == NULL) // does not work
printf("Empty");
else
printf("%c", literal[index]);
++index;
}
getchar();
return 0;
}
No. Since literal has automatic storage, its elements will not be initialized, the values in the array is undefined.
You could initialize every element to something special and check for that value.
e.g. you could change
char literal[100];
char literal[100] = {0};
to initialize every element to 0.
You'd have to change your while loop termination check to
while(index < 100) {
if(literal[index] == 0)
printf("Empty");
...
}
}
That might not be optimal if you need to perform more string manipulation on the array though, as 0 now means empty element and also 'end of string'.
No, you can't do that. This is because it will have a value - there is just no way of knowing what that value is. This is why it is essential to initialise things to known values.
C does not default initialize anything. Therefore the contents in your string are whatever garbage was in that memory by whatever last used it on the stack. You need to explicitly set each literal value to a value that means "unset" to you.
No, there is no way of knowing what value the array has. You can, however, initialize it with a chosen "default" value of your choice and later check against that.
You need to set the end of the string to 0 (zero) or '\0' - C only does this for you automatically for string literals, not local variables on the stack
Try
memset(&literal, 0, 100);
Or just uncomment your line that sets literal at index 99 to '\0'
A c string is just a bunch of memory locations and a convention that '\0' marks the end. There is no compiler enforcement, and no attached meta data (unless you build a structure to provide it).
Every cell in memory, always has a value, so every string always has a value, you just can't guarantee that it is sensible or even that it ends in the allotted space.
Insuring that there is meaningful data in there is your responsibility, which suggests that you should initialize all strings either at declaration time or immediately after allocation. Exception to the rule are rare and are undertaken at your own risk.
No, that is undefined behaviour as the runtime, for all we care could shove in a few binary ASCII characters, you really do not want to get into that. The best way to deal with it is to use a for loop and iterate through it or use calloc which initializes a pointer but sets it to 0.
for (i = 0; i < 100; i++) literal[i] = '\0';
OR
char *literalPtr = (char*)calloc(100, sizeof(char)); // Array of 99 elements plus 1 for '\0'
There is absolutely no guarantee in doing that. Hence it would be classified as undefined behaviour as it is dependent on the compiler and runtime implementation.
Hope this helps,
Best regards,
Tom.
When I make a call to the C string compare function like this:
strcmp("time","time")
It returns 0, which implies that the strings are not equal.
Can anyone tell me why C implementations seem to do this? I would think it would return a non-zero value if equal. I am curious to the reasons I am seeing this behavior.
strcmp returns a lexical difference (or should i call it "short-circuit serial byte comparator" ? :-) ) of the two strings you have given as parameters.
0 means that both strings are equal
A positive value means that s1 would be after s2 in a dictionary.
A negative value means that s1 would be before s2 in a dictionary.
Hence your non-zero value when comparing "time" and "money" which are obviously different, even though one would say that time is money ! :-)
The nice thing about an implementation like this is you can say
if(strcmp(<stringA>, <stringB>) > 0) // Implies stringA > stringB
if(strcmp(<stringA>, <stringB>) == 0) // Implies stringA == stringB
if(strcmp(<stringA>, <stringB>) < 0) // Implies stringA < stringB
if(strcmp(<stringA>, <stringB>) >= 0) // Implies stringA >= stringB
if(strcmp(<stringA>, <stringB>) <= 0) // Implies stringA <= stringB
if(strcmp(<stringA>, <stringB>) != 0) // Implies stringA != stringB
Note how the comparison with 0 exactly matches the comparison in the implication.
It's common to functions to return zero for the common - or one-of-a-kind - case and non-zero for special cases. Take the main function, which conventionally returns zero on success and some nonzero value for failure. The precise non-zero value indicates what went wrong. For example: out of memory, no access rights or something else.
In your case, if the string is equal, then there is no reason why it is equal other than that the strings contain the same characters. But if they are non-equal then either the first can be smaller, or the second can be smaller. Having it return 1 for equal, 0 for smaller and 2 for greater would be somehow strange i think.
You can also think about it in terms of subtraction:
return = s1 - s2
If s1 is "lexicographically" less, then it will give is a negative value.
Another reason strcmp() returns the codes it does is so that it can be used directly in the standard library function qsort(), allowing you to sort an array of strings:
#include <string.h> // for strcmp()
#include <stdlib.h> // for qsort()
#include <stdio.h>
int sort_func(const void *a, const void *b)
{
const char **s1 = (const char **)a;
const char **s2 = (const char **)b;
return strcmp(*s1, *s2);
}
int main(int argc, char **argv)
{
int i;
printf("Pre-sort:\n");
for(i = 1; i < argc; i++)
printf("Argument %i is %s\n", i, argv[i]);
qsort((void *)(argv + 1), argc - 1, sizeof(char *), sort_func);
printf("Post-sort:\n");
for(i = 1; i < argc; i++)
printf("Argument %i is %s\n", i, argv[i]);
return 0;
}
This little sample program sorts its arguments ASCIIbetically (what some would call lexically). Lookie:
$ gcc -o sort sort.c
$ ./sort hi there little fella
Pre-sort:
Argument 1 is hi
Argument 2 is there
Argument 3 is little
Argument 4 is fella
Post-sort:
Argument 1 is fella
Argument 2 is hi
Argument 3 is little
Argument 4 is there
If strcmp() returned 1 (true) for equal strings and 0 (false) for inequal ones, it would be impossible to use it to obtain the degree or direction of inequality (i.e. how different, and which one is bigger) between the two strings, thus making it impossible to use it as a sorting function.
I don't know how familiar you are with C. The above code uses some of C's most confusing concepts - pointer arithmetic, pointer recasting, and function pointers - so if you don't understand some of that code, don't worry, you'll get there in time. Until then, you'll have plenty of fun questions to ask on StackOverflow. ;)
You seem to want strcmp to work like a (hypothetical)
int isEqual(const char *, const char *)
To be sure that would be true to the "zero is false" interpretation of integer results, but it would complicate the logic of sorting because, having established that the two strings were not the same, you would still need to learn which came "earlier".
Moreover, I suspect that a common implementation looks like
int strcmp(const char *s1, const char *s2){
const unsigned char *q1=s1, *q2=s2;
while ((*q1 == *q2) && *q1){
++q1; ++q2;
};
return (*q1 - *q2);
}
which is [edit: kinda] elegant in a K&R kind of way. The important point here (which is increasingly obscured by getting the code right (evidently I should have left well enough alone)) is the way the return statement:
return (*q1 - *q2);
which gives the results of the comparison naturally in terms of the character values.
There's three possible results: string 1 comes before string 2, string 1 comes after string 2, string 1 is the same as string 2. It is important to keep these three results separate; one use of strcmp() is to sort strings. The question is how you want to assign values to these three outcomes, and how to keep things more or less consistent. You might also look at the parameters for qsort() and bsearch(), which require compare functions much like strcmp().
If you wanted a string equality function, it would return nonzero for equal strings and zero for non-equal strings, to go along with C's rules on true and false. This means that there would be no way of distinguishing whether string 1 came before or after string 2. There are multiple true values for an int, or any other C data type you care to name, but only one false.
Therefore, having a useful strcmp() that returned true for string equality would require a lot of changes to the rest of the language, which simply aren't going to happen.
I guess it is simply for symmetry: -1 if less, 0 if equal, 1 if more.