Problem with strchr - c

I can't get why the following bit of C code doesn't work:
int obtainStringLength(char* str, char c1, char c2) {
char* firstOcurrence = strchr(str, c1);
char* endOcurrence = strchr(str, c2);
return 2+(endOcurrence - firstOcurrence) / sizeof(char*);
}
The idea is to find how many characters are between c1 and c2:
printf("%d\n", obtainStringLength("abc def ghi", 'a', 'i')); //should yield 11
Unfortunately, this is always printing 1. What is the problem? Shouldn't strchr work like C#'s string.IndexOf()?

Division by sizeof(char*)? That's incorrect - the result of subtracting two pointers is a numerical value (ptrdiff_t) corresponding to the number of values, not a pointer or difference of addresses.
There's also the off-by-one error in calculating the length. So that last line should look like:
return 1 + (endOcurrence - firstOcurrence);

Your return statement has several problems, due to not understanding pointer arithmetic.
Pointer subtraction already divides by the element size, and char* was the wrong type anyway.
And you should be adding 1, not 2.

Because each character occupies exactly sizeof (char) bytes; not sizeof (char*) bytes.
And sizeof (char) is, by definition 1, so you can omit it:
return 1 + (endOcurrence - firstOcurrence);

No, strchr() returns a pointer (the address of) the character being sought, or NULL if the character was not found.
That's very different from IndexOf().

Related

Function is returning a different value every time?

I'm trying to convert a hexadecimal INT to a char so I could convert it into a binary to count the number of ones in it. Here's my function to convert it into char:
#include <stdio.h>
#include <stdlib.h>
#define shift(a) a=a<<5
#define parity_even(a) a = a+0x11
#define add_msb(a) a = a + 8000
void count_ones(int hex){
char *s = malloc(2);
sprintf(s, "0x%x", hex);
free(s);
printf("%x", s);
};
int main() {
int a = 0x01B9;
shift(a);
parity_even(a);
count_ones(a);
return 0;
}
Every time I run this, i always get different outputs but the first three hex number are always the same. Example of outputs:
8c0ba2a0
fc3b92a0
4500a2a0
d27e82a0
c15d62a0
What exactly is happening here? I allocated 2 bytes for the char since my hex int is 2 bytes.
It's too long to write a comment so here goes:
I'm trying to convert a hexadecimal INT
int are stored as a group of value, padding (possible empty) and sign bits, so is there no such thing as a hexadecimal INT but you can represent (print) a given number in the hexadecimal format.
convert a ... INT to a char
That would be lossy conversion as an int might have 4 bytes of data that you are trying to cram into a 1 byte. char specifically may be signed or unsigned. You probably mean string (generic term) or char [] (standard way to represent a string in C).
binary to count the number of ones
That's the real issue you are trying to solve and this is a duplicate of:
How to count the number of set bits in a 32-bit integer?
count number of ones in a given integer using only << >> + | & ^ ~ ! =
To address the question you ask:
Need to allocate more than 2 bytes. Specifically ceil(log16(hex)) + 2 (for 0x) + 1 (for trailing '\0').
One way to get the size is to just ask snprintf(s, 0, ...)
then allocate a suitable array via malloc (see first implementation below) or use stack allocated variable length array (VLA).
You can use INT_MAX instead of hex to get an upper
bound. log16(INT_MAX) <= CHAR_BIT * sizeof(int) / 4 and the
latter is a compile time constant. This means you can allocate your string on stack (see 2nd implementation below).
It's undefined behavior to use a variable after it's deallocated. Move free() to after the last use.
Here is one of the dynamic versions mentioned above:
void count_ones(unsigned hex) {
char *s = NULL;
size_t n = snprintf(s, 0, "0x%x", hex) + 1;
s = malloc(n);
if(!s) return; // memory could not be allocated
snprintf(s, n, "0x%x", hex);
printf("%s (size = %zu)", s, n);
free(s);
};
Note, I initialized s to NULL which would cause the first call to snprintf() to return an undefined value on SUSv2 (legacy). It's well defined on c99 and later. The output is:
0x3731 (size = 7)
And the compile-time version using a fixed upper bound:
#include <limits.h>
// compile-time
void count_ones(unsigned hex) {
char s[BIT_CHAR * sizeof(int) / 4 + 3];
sprintf(s, "0x%x", hex);
printf("%s (size = %zu)", s, n);
};
and the output is:
0x3731 (size = 11)
Your biggest problem is that malloc isn't allocating enough. As Barmar said, you need at least 7 bytes to store it or you could calculate the amount needed. Another problem is that you are freeing it and then using it. It is only one line after the free that you use it again, which shouldn't have anything bad happen like 99.9% of the time, but you should always free after you know you are done using it.

What does the 2nd argument in strtoul() function do?

According to this document,
The second argument (char **endptr) seems to be a waste of space! If
it is set to NULL, STRTOL seems to work its way down the string until
it finds an invalid character and then stops. All valid chars read are
then converted if the string starts with an invalid character the
function returns ZERO (0).
It means that the following code should detect 2 as the hex number:
int main()
{
char * string = "p1pp2ppp";
unsigned integer = strtoul(string, NULL, 16);
printf("%u", integer);
return 0;
}
but, it is returning zero.
Why?
The man page says the following about the second argument:
If endptr is not NULL, strtol() stores the address of the first
invalid character in *endptr. If there were no digits at all,
strtol() stores the original value of nptr in *endptr (and
returns 0). In particular, if *nptr is not '\0' but **endptr is
'\0' on return, the entire string is valid.
For example:
char str[] = "123xyz45";
char *p;
long x = strtol(str, &p, 10);
printf("x=%ld\n", x);
printf("p - str = %d\n", p - str);
printf("*p = %c\n", *p);
printf("p (as string) = %s\n", p);
Output:
x=123
p - str = 3
*p = x
p (as string) = xyz45
We can see that when strtol returns p points to the first character in str that cannot be converted. This can be used to parse through the string a bit at a time, or to see if the entire string can be converted or if there are some extra characters.
In the case of your example, the first character in string, namely "p" is not a base 10 digit so nothing gets converted and the function returns 0.
Why?
It's returning 0 because "p..." does not follow any rules about integer representation. The 2nd argument is not relevant for your question.
The char **endptr argument in all the strto* functions is intended to receive the address of the first character that isn’t part of a valid integer (decimal, hex, or octal) or floating point number. Far from useless, it’s handy for checking invalid input. For example, if I meant to type in 1234 but fat-fingered something like 12w4, strtoul will return 12 and set the endptr argument to point to w.
Basically, if the character endptr points to isn’t whitespace or 0, then the input should most likely be rejected.

Can i assign a integer to a character pointer array?

int k=5;
char* result = (char *)malloc(100 * sizeof(char));
result[count] = k;
Considering the above code, if I print the contents of result[count] it prints smiley symbols. I tried like below,but of no use.
result[count]=(char)k;
Can anyone help me?
I am percepting that malloc(100*sizeof(char)) will create 100 blocks each of size of character contiguously. Please correct me if I am wrong?
I'll disregard all the fluff about arrays and malloc as it is irrelevant to the problem you describe. You seem to essentially be asking "What will this code print:"
char c = 5;
printf("%c", c);
It will print the symbol 5 in your symbol table, most likely a non-printable character. When encountering non-printable characters, some implementations choose to print non-standard symbols, such as smileys.
If you want to print the number 5, you have to use a character literal:
char c = '5';
printf("%c", c);
or alternatively use poor style with "magic numbers":
char c = 53; // don't write code like this
printf("%c", c);
It is a problem of character representation. Let's begin by the opposite first. A char can be promoted to an int, but if you do you get the representation of the character (its code). Assuming you use ASCII:
char c = '5';
int i = c; // i is now 0x35 or 53 ASCII code for '5'
Your example is the opposite, 5 can be represented by a char, so result[count] = k is defined (even if you should have got a warning for possible truncation), but ASCII char for code 5 is control code ENQ and will be printed as ♣ on a windows system using code page 850 or 437.
A half portable (not specified, but is known to work on all common architectures) way to do the conversion (int) 5 -> (char) '5' is to remember that code '0' to '9' are consecutive (as are 'A' to 'Z' and 'a to 'z'), so I think that what you want is:
result[count] = '0' + k;
First, let's clean up your code a bit:
int k=5;
char* result = malloc(100);
result[count] = k;
sizeof(char) is always equal to 1 under any platform and you don't need to cast the return of malloc() in C.
This said, as long as your count variable contains a value between 0 and 99, you're not doing anything wrong. If you want to print the actual character '5', then you have to assign the ASCII value of that character (53), not just the number 5. Also, remember that if that array of chars has to be interpreted as a string, you need to terminate it with '\0':
int k=5, i;
char* result = malloc(100);
for (i=0; i<98; i++) {
result[i] = ' ';
}
result[98] = 53;
result[99] = '\0';
printf("%s\n", result);
The elements in the array you're trying to allocate are all the size of a char, 1 byte. An int is 4 bytes thus your issues. If you want to store ints in an array you could do:
int result[100];
Followed by storing the value, but honestly from the way your questioned is posed I don't know if that's actually what you're trying to do. Try rephrasing the post with what you're trying to accomplish.
Are you trying to store 5 as a character?

questions about a particular string within printf

I found this C language fragment:
printf("[%d] %.*s\n", cnt++, temp - field, field);
where temp and field are char * and cnt is an integer.
But I don't understand the use of %.*s in format string within printf.
Can-please-any of you help me ?
You can use .* in printf to specify that the precision is to be given as an argument. In your case, that argument is temp - field, the difference between the two pointers.
From some documentation:
.*: The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.
So, in your case, field has the value and temp-field its precision.
These percentage-sign symbols, for future reference are called format specifiers. (In fact I found the answer to this question by googling just that.)
There are two parts for this answer,
That line is doing pointer arithmetic, a way to calculate the length of a string; based on a convention used in your application perhaps.
char *string = "abcdef";
char *p1 = string + 3; // def
char *p2 = string + 4; // ef
printf("%s - %s = %d\n", p1, p2, (int) (p1 - p2));
output
0x400709 - 0x40070a = -1
Note that p2 is a shorter string, but a bigger pointer.
.number is used to specify the precision of integers or the length of a string.
// number precision
printf("%.2f\n", 100.12345); // 100.12
char *string = "abcdef";
// print the first 3 characters only
printf("%.3s\n", string); // abc
// print the first X characters
int dynamicLength = 2;
printf("%.*s\n", dynamicLength, string); // ab
Note that by using .* what you are saying is:
I won't know the precision until the program is running.

dont understand with func printf in C

This code:
char arr1[20] = "fedcba";
char *ptr;
ptr = &arr1[2];
puts(arr1);
printf("%d\n",*arr1 - *ptr);
printf("%d\n",arr1 - ptr);
I understand that the first printing puts the string.
printf I - what is supposed to print? It says * arr1 - * ptr?
printf II - What is the difference between one and two?
The first prints the difference between 2 chars:
The second prints the difference between 2 pointers.
*arr1 dereferences a char* and returns the first character, which is 'f'.
ptr = &arr1[2]; will make ptr point to "dcba". It takes the address of the third character in arr1. *ptr returns 'd'.
So the first printf returns the difference between characters f and d - which is 2.
The second one is the difference between the two pointers. It's legal since they both point inside the same character array. It's the same as arr1 - &arr[2] which will most likely be -2, since arrays are stored continuously in memory.
printf("%d\n",*arr1 - *ptr);
This prints the result of the first character of arr1 minus the first character of ptr.
Here is clearer version that does the same thing: printf("%d\n",arr1[0] - ptr[0]);
printf("%d\n",arr1 - ptr);
This prints the pointer difference between arr1 and ptr, which is 2.
Essentially the property holds that: (a[x] - a) is equivalent to x
Just add these two lines to your program for better understanding...
printf("\n%d AND %d... %c",arr1, *arr1, *arr1);
printf("\n%d AND %d... %c",ptr, *ptr, ptr[0] ); //ptr[0] == *ptr
Hope this helps...

Resources