I am not a C developer or know much about C but I came across this C interview question:
int toto(char *a, char *b){
while(*a++ == *b++);
return(*a == 0 && *b == 0);
}
I spent a good amount of time trying to figure it out and after reading a few things online I kind of grasped what it is trying to do but there are still some weird behaviours that arise.
From what I understand (please correct me if I'm wrong), this piece of code will go through two strings (char arrays) and determine whether they are equal up until the last character and returns true only if the last character is different. return (*a == 0 && *b == 0) checks for the 0 integer that all strings end with in C. This only happens after the loop has exited i.e when two characters aren't equal before the increment happens; so if the last two characters are not equal, it will increment them to the 0 int and go through to the return statement. I also noticed that that if the strings differ by 1 then it still returns true if the strings are equal up until n-1 for example:
char a[] = "ggr"
char b[] = "ggre"
//returns 1
char a[] = "ggr"
char b[] = "ggf"
//returns 1
I found this behaviour peculiar but the test case that I can't understand is the following:
char a[] = "abcd";
char b[] = "abcd";
//returns 1
char a[] = "abc"
char b[] = "abc"
//returns 0
I understand why abc returns false but I have no idea why it wouldn't return the same for abcd. To me, it seems like it treats strings of different lengths differently but the code doesn't seem to care about the length.
Can anyone explain what the code intends to do and why the code behaves differently when given different lengths of strings. I have a feeling it has to do with the order of precedence for certain operators but I couldn't find an answer.
Edit: It seems the code supplied by the interview is buggy on purpose, I was under the impression that the code is valid.
Your code has undefined behavior. It will eventually access memory beyond the null terminated char array. This code is wrong in that sense.
The correct implementation would be something like
int toto(char *a, char *b){
while(*a && *b && *a == *b) a++,b++;
return (*a - *b)?0:1;
}
Because it has a bug. If the two strings are exactly equal until the end of either string, then you will iterate past the end of the string. You will then have undefined behaviour, meaning sometimes it can work, or sometimes it could crash (or do a plethora of other things). Consider adding this to your function:
int counter = 0;
while(*a++ == *b++) {
printf("Count %d\n", ++counter);
}
Live example.
You will note it could print:
Count 1
Count 2
Count 3
Count 4
Which means your return line (return(*a == 0 && *b == 0);) will be dereferencing past the end of the string (i.e. on the 5th string character).
Related
There is this problem on LeetCode that I can not get to work in C/C++
The idea is to reverse an array in its place (using no other additional array) using recursion.
The link is : https://leetcode.com/explore/learn/card/recursion-i/250/principle-of-recursion/1440/
The solution is done in Java or Python.
I tried implementing the solution in C but I always get the original array, my code is as follows:
void reverseString(char* s, int sSize){
if(!s)
return;
reverseString(s+1,sSize-1);
s[sSize] = *s;
}
There is something I am not accounting for. Please let me know how would you solve it, and if possible why this is not working. Thanks.
I'll take a stab at this.
The general idea for a recursive solution is for each call to get a pointer to the start of a string, and how many characters to look at, and this walks its way to the middle of the string.
void reverseString(char *start, int n)
{
if (n <= 1) return;
char tmp = start[0];
start[0] = start[--n]; // the nth character is start[n-1]
start[n] = tmp;
reverseString(++start, --n);
}
On each recursive call, the starting string pointer is incremented by one, and the length decreased by two.
FIRST CALL: v v
hello, world
SECOND CALL: ^ ^
The common danger area is making sure it does the right thing with even and odd-length strings.
This method is a bit simpler with just two parameters, and - as some might say - a bit more elegant :-) even if the ++ and -- could be considered tricky (one increment and two decrements).
EDIT: This version is also tail recursive, which can lead to certain optimizations by internally turning it into a loop.
Solution (thank you to the folks in the comments):
void reverse(char * str, int len)
{
char tmp;
if (len <= 1)
return;
tmp = str[0];
len--;
str[0] = str[len];
str[len] = tmp;
str++;
reverse(str, len-1);
}
Call this function with your initial string and 0 as arguments:
char str[] = "Ding dong";
reverse(str, 0, strlen(a));
void reverse_string(char *x, int start, int end)
{
char ch;
if (start >= end)
return;
ch = *(x+start);
*(x+start) = *(x+end);
*(x+end) = ch;
//Function calling itself: Recursion
reverse_string(x, ++start, --end);
}
In this function we are passing the string, the starting index and the ending index.... The recursion will continue till start>=end i.e. till the center of the string appears..... And everytime it will swap the 2 indexes i.e. from the start and from the end...
I have a problem when I try to compare the content of two char arrays.
Sometimes
If the string is less than the actual size of the array, in it there is no sequence of '\0' but often there are unexpected characters (in the xcode debug there was the '\x01' character and in the control loop I use To check if a memory cell of the array was the same as the other, it was not the same). So to overcome this problem I decided to force the user to write the array content exactly as array size(-1): ex. array[3], the users write "hi" (without the ""). So I was wondering if there is a way to compare the two strings (I'm not talking about length but content) without fully filling the array in order to compare the content ofenter code here the two arrays through a simple cycle. (I was thinking of initializing the vector with \ 0 but I do not know if there can be problems)
thanks for the answers
this is an example of the code
}while(sent !=1);
for(contatore=0; contatore<MAXNOME; contatore++){
if(UserName[contatore] == persona.username[contatore]){
controlloUsr++;
}
}
for(contatore=0; contatore<MAXNOME; contatore++){
if(password[contatore] == persona.password[contatore]){
controlloPsw++;
}
}
if(controlloUsr == MAXNOME && controlloPsw == MAXPSW){
return 1;
} else {
return 0;
}
I'm not sure if that's what you're asking, but there is no way to browse an array of chars in C without giving the code a stop sequence, like a \0, or you will browse it forever (well, until a wild segfault appear...)
You can write your own strncmp function for this, something like :
int my_strncmp(char *str1, char *str2, size_t max, char c)
{
size_t n = 0;
while (n < max)
{
if ((str1[n] != str2[n]) || (str1[n] == c) || (str2[n] == c))
return 0;
n++;
}
return 1;
}
This will return 0 if your char c is met, or if the strings are different, or 1 if the string are the same until max char. Just be sure that one of the two conditions is met or you code will crash into a segfault / have undefined behavior, since you will browse out of your allowed memory range.
the function strcmp() and the strncmp() are made for this exact operation,.
You can read the man page for those two functions for all the details.
I am trying to count the number of elements in an array using C. I tried out the following code. But it just returns 83 every time I run the program. What I mean by to count the number of elements is that I need to know the number of elements that we have entered and not the size of the array.
#include<stdio.h>
#include<stdlib.h>
main(){
int a[100], j = 0, i;
a[0] = '0';
a[1] = '1';
a[2] = '2';
a[3] = '3';
a[4] = '4';
a[5] = '5';
for(i=0; i<100; i++){
if(a[i] == '\0'){
}
else
j = j + 1;
}
printf("%d", j);
system("pause");
}
Arrays in C are a fixed size. They do not expand. Your array has two entries; writing to array[2], array[3], etc. invokes undefined behaviour. In other words, it's invalid code.
If you want to be able to insert an arbitrary number of elements, you will need to use dynamically-allocated memory, manually track how many elements you've inserted, and use realloc when you need to resize.
Since the OP amended his code, here is a more correct reply:
This code works 'by chance', since you didn't initialize the array previously.
It's just 'luck', that somewhere in there, the value 0 comes up.
The declaration of an array does NOT zero it.
Use:
memset(a, 0, 100);
For that. That way, the first 'not overwritten' byte will return '0'.
Reference: http://www.cplusplus.com/reference/clibrary/cstring/memset/
Alternatively, you have to set the 'delimited' manually by adding a[x] = 0;
Now, I know you specifically asked for a 'C' solution, but if you would like to consider using a C++-Compiler, I suggest looking at the stl of C++.
Here's a link to get you started: http://www.cplusplus.com/reference/stl/list/
It's initialized as:
list<char>List;
List.push_back(1);
List.push_back(2);
List.push_back('a');
int j = List.size(); //Returns '3'
do this instead:
main(){
int a[100] = {0};
int j = 0;
int i = 0;
// other stuff
Update based on new code:
In general, you will need a way to identify the end of your array in order to do a correct count. For strings the '\0' is used generally. For other data types you have to come up with your own value to check.
For your specific code example above:
You need to insert a \0 yourself into your array in the last position so that your count will work. (When you create a string like "hello", the '\0' gets automatically put in for you at the end of the string, but not if you create a string character by character).
Alternatively, check for the character '5' to find the end of your current array of characters.
Also, you should break out of the loop once you found the last character, otherwise you are going past the end of the array and will most likely crash (again, if you don't it's sheer luck). I.e., something like:
if(a[i] == '\0'){
break;
}
will work if you do:
a[6] = '\0';
before.
Since C doesn't check array bounds, it might appear that with your current code you seemingly get away with this, but it's sheer luck that the program doesn't crash and may change from run to run. In other words, this is undefined behavior.
Finally, you can of course also use strlen() if you are dealing with strings.
I'm fairly new to C programming but trying my best to understand it. I have two dynamic strings that are populated from two plain text files. One being a form of a dictionary, and the other one just a user input. What I want to get is binary search each user input word in the dictionary and find out if it is present (sort of a spell checker I guess).
I'm stuck on my binary search function:
char **dictElem;
int dictSize;
char **inputElem;
int binsearch(const char *val){
int pos;
int beg=0;
int end=dictSize-1;
int cond=0;
while (beg<=end){
pos=(beg+end)/2; //Jump in the middle
if ((cond=strcmp(dictElem[pos],val)) == 0)
return pos;
else if (cond<0)
beg=pos+1;
else
end=pos-1;
}
return 0;
}
Both dictElem and inputElem were already read by other methods and (let's say) both [0] elements are equal strings "aa".
However after I run the binsearch(inputElem[0] it always returns 0. I tried just strcmp(dictElem[0],inputElem[0]) and it returns 1.
Where am I going wrong? Is it comparing char** and char*?
UPD:
Function that's loading the dictElem
void readd(FILE *file){
int i=0,size=0; /* local size */
char line[1024]; /* Local array for a single word read */
printf("Loadingn dict...\n");
while ((fgets(line,sizeof(line),file))!=NULL){
dictElem=(char**)realloc(dictElem,(size+1)*sizeof(char *));
dictElem[size++]=strdup(line);
}
printf("Total elements loaded: %d\n",size);
}
Function that reads a user file is very similar, just a little different format.
The problem with your code is in this line if ((cond=strcmp(dictElem[pos],val) == 0)). This line of code assigns the result of expression strcmp(dictElem[pos], val) == 0 to the variable cond, and then checks whether cond is zero or not.
I guess your original intent was to store in cond the result of strcmp, so you should move the closing parenthesis before ==. The correct line is if ((cond = strcmp(dictElem[pos], val) == 0).
There are some other problems with your code:
0 is used as special not-found value, but in the same time 0 can be
returned when element is found at index 0.
Using char *val, when
it is better to use const char *val, because contents of this
string aren't going to be modified. It is always better to write const-correct code.
Your problem is this line:
if ((cond=strcmp(dictElem[pos],val) == 0))
The parentheses are giving it the wrong order of evaluation and cond will always end up 0 or 1 (because you're assigning the results of the comparison strcmp() == 0 to it). Try this instead:
if ((cond=strcmp(dictElem[pos],val)) == 0)
Suppose, for example, that some k which is an arbitrary number=2 k=2, then there is code in C:
int wordcomp(char *p, char *q) {
int n = k;
for ( ; *p == *q ; p++, q++) {
if ( *p==0 && --n == 0 )
return 0;
}
return *p - *q;
}
Please explain to me what this code does? Also, what does *p-*q mean? Also, how is it implemented in Java?
please explain me what does this code do?
It compares two words
also what means *p-*q?
It means, Tell me the value of char the pointer p is pointing to, and rest it to the char the pointer q is pointing to.
and also how implement it in java?
The *p-*q part? Here is it.
// char c
// char k
c - k;
If you mean the whole function, this could help you to get started:
int wordcomp( String sp, String sq) {
int n = k; // I have no idea what is this for
int pi = 0, qi = 0;
for ( ; sp.charAt(pi) == sq.charAt(qi) ; pi++, qi++) {
if ( sp.length()==pi && --n == 0 )
return 0;
}
return sp.charAt(pi) - sq.charAt(qi);
You need to validate limits tough.
Looks to be close to strcmp. It takes two string pointers, loops over them until it finds a character that is different, and then returns a positive value if p is alphabetically after q, a negative value if p is alphabetically before q, or 0 if they are the same. As stated by others, k looks to define the number of consecutive null-terminated strings to compare before it just returns 0.
*p-*q means subtract the value pointed to by pointer q from the value pointed to by pointer p.
this being C, subtracting 2 char values means subtracting their ASCII codes.
This function loops through two character arrays, comparing them for equality.
If they are unequal, it returns *p - *q, which is the difference between the values in the first unequal position. If, after the kth zero in the first string, there is still no inequality, then it returns 0.
So it returns the difference between the values in the first unequal position, or 0 if the first string has k zeros and is equal until that point to the second string.
Returns the difference between the first two dissimilar chars in two character arrays (*p and *q) of maximum length k, i.e.
batter
batsman
Returns 't'-'s'
If both strings are same for length k and we reach the null character of p, we return 0. I think it should be || not && since these are termination conditions.
It compares to char arrays (words) to the element set in k.
Lets say if you have k=4 it means it will compare first 4 chars.
Also I believe instead of
if ( *p==0 && --n==0)
you need
if ( *p==0 || --n==0)
And also please consider using p - q .
And the function name must be wordcomp instead of wrodcomp.
So to summarize it is something like strncmp from string.h.