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.
Related
This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 8 months ago.
sort.hpp -> we sort station names
struct _element {
char icao_code[5];
char station_name[100];
};
typedef struct _element element;
void bubbleSort(element* stations, int size);
bubblesort (doesn't work)
void bubbleSort(element *pElement, int size) {
int i, j;
for (i = 0; i < size - 1; i++)
// Last i elements are already in place
for (j = 0; j < size - i - 1; j++)
if (pElement[j].station_name > pElement[j + 1].station_name)
{
element tmp = pElement[j];
pElement[j] = pElement[i];
pElement[i] = tmp;
}
}
Does someone know how to make this code work?
This is not the correct way to compare C strings
if (pElement[j].station_name > pElement[j + 1].station_name)
The problem is that you are comparing the pointers, not the characters that are pointed at.
Use strcmp instead
if (strcmp(pElement[j].station_name, pElement[j + 1].station_name) > 0)
The reason is because when you use relational operators (==,<,etc) to compare strings, C actually compares their addresses, not their contents.
To compare the contents of two strings you have you have to use strcmp().
strcmp(string1, string2);
strcmp() works by comparing each character's ASCII value. So, a value of 0 means that both strings are equal and you would test for that like this:
if(strcmp(string1, string2) ==0){
printf("Both strings are equal!");
}
As a side note, it can also tell you if the first string is considered to be "bigger" or "smaller" in value (not length) when compared the second string.
For example:
strcmp("hello", "HELLO");
Will return a value bigger than 0 which means the ASCII values of "hello" add up to be higher than those of "HELLO". Meanwhile, a value less than 0 would mean that the first string is smaller than the second string.
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).
I am doing a c program but the sample input is not giving the sample output if I use the. I think my program is not calling the function. I guess I have declared it incorrectly. Or my logic is wrong. What I am getting is a zero as output. The question is given below.
Write a C function to find the kth occurrence of an integer n in a sequence of non-negative integers, and then call your function from
main.
Your function should be according to the following declaration:
int find(int n, int k);
Input
You are given the input in two lines:
The first line contains a non-negative integer, say n, and a positive
integer k, in that order. You have to find the kth occurrence of n in
the sequence below.
The second line consists of a sequence of non-negative integers,
terminated with a -1. The -1 is not part of the sequence.
Output
If n occurs k times in the sequence, then output the index of the kth
occurrence of n in the sequence.
If n does not occur k times in the sequence, then output -1.
(For example, the second occurrence of the integer 3 in the sequence
1 1 3 2 3 -1 is at position 4 in the sequence. The first index in the
sequence is 0.)
Input:
3 2
1 1 2 3 3 -1
Output:
4
Code:
#include<stdio.h>
int check(int a,int n ,int k ){
int f;
int value;
int counter=0;
counter++;
if (a==n)
{
f++;
}
if(f==k)
{
value= counter;
}
return value;
}
int main(void)
{
int n , k,a;
int tempo;
scanf("%d",&n);
scanf("%d",&k);
while(a!=-1)
{
scanf("%d",&a);
tempo=check(a,n,k);
}
printf("%d",tempo);
return 0;
}
Your check function has numerous problems:
int check(int a,int n ,int k ){
Your prototype does not match the one in the assignment - you're only supposed to take 2 arguments, neither of which is the sequence of values you're checking against. Somehow, someway, you are supposed to access that sequence from within the body of the function, either by referencing a global array (bad), or by reading the input sequence from within the body of the function (slightly less bad, and probably the intent of the exercise1).
int f;
int value;
auto variables are not implicitly initialized in a declaration - their initial value is indeterminate (it may be 0, it may be a trap representation, it may be a valid non-zero integer value). This will cause problems later.
int counter=0;
counter++;
I think I know what you're trying to go for here, and it won't work as written2 - counter only exists for the lifetime of the function. Each time you call check, a new instance of counter is created and initialized to 0. It won't remember the value stored in it from a previous call.
if (a==n)
{
f++;
f isn't guaranteed to be 0 at this point (or any other specific value). It could be 0, or it could be any non-zero value, or even a trap representation (a bit pattern that does not correspond to a valid integer value).
}
if(f==k)
{
value= counter;
}
return value;
}
At this point, counter is only ever going to be 1 - you initialize it to 0 at function entry and immediately increment it, then you never touch it again. So value is only ever going to be indeterminate or 1.
So, how should you proceed from here and satisfy the requirements of the assignment?
The less bad option is to read the sequence from within the check (or find) function, although that's still pretty bad (again, I/O should be a separate operation, and we're assuming all input comes through stdin).
int find( int n, int k )
{
int next; // next value in the sequence
... // additional items for index, number of matches, etc.
while ( scanf( "%d", &next ) == 1 && next != -1 )
{
// update index, does next match n, is it the k'th match, etc.
}
...
}
scanf is a poor tool for interactive input, but at this point is the simpler approach.
Which, honestly, isn't any better than keeping a global array. I/O should be factored out from computation whenever possible, and if a function *is* required to read from an input stream, that stream should be specified as a parameter to the function - you shouldn't force your code to assume all input comes through stdin.
counter would need to be declared static for it to retain its value from call to call.
My solution is totally extension of what John Bode said above and as John Bode said, you are using more parameters than the preferred. You should stick to only 2 parameters. And as you have two parameters n(for search element) and K(k th occurrence) you cant pass an sequential array to that function, So you should start reading(scanning) the sequence inside the find().
As the program clearly says it terminates with -1. You can use this to end the loop in terminating the find function.
Scan function returns true as long as it reads. even for -1 it returns true so you should use the value!=-1. And inside the loop you can use your logic of matching and finding the index number.
int find(int n, int k){
int next;
int match=0;
int index=0; //for parsing the sequence
while( scanf("%d", &next) ==1 && next!=-1){
if(next == n){
match++;
if(match==k)
return index;
}
index++; //move the index
}
return -1;
}
Note I'm using C not C++. I'm working on a program that will take a 2d-array and count the numbers of non-spaces in a subarray. Such as lines[0][i] <-- iterating over line[0][0] - line[0][n]. However, I'm having difficulty getting the function to accept the 2d-array.
Here is my code:
pScore[0]=letters(pLines, 0);
This is the actual function. pScore[] is another array, but a 1d one. pLines is a 4 by 200 2d-array.
int letters(char line[][], int row)
{
int i = 0;
int n = n;
int results = 0;
for( i = 0; i < (sizeof(line)/sizeof(line[0])); i++ )
{
if( !isspace(line[row][i]) )
results++;
}
return results;
}
When I do this it gives me "formal parameter number 1 is not complete". If I remove the second [] from it, the code runs but gives the worng number of non-space characters.
Taking from the comments above, and your function parameter list:
int letters(char line[][], int row)
You violate one primary tenant of passing a 2D array to a function. Specifically, you must always provide the number of columns contained in the array. e.g.
int letters(char line[][5], int row)
char line[][5] is an appropriate parameter. However, whenever you pass an array as a function parameter, the first level of indirection is converted to a pointer. (you will often here this referred to as "pointer-decay", though that is a bit of a misnomer). Therefore a proper declaration that makes this clear is:
int letters(char (*line)[5], int row)
line, after conversion, is a pointer-to-an-array of 5-int. While you can pass the array as line[][5], that is not nearly as informative as (*line)[5]. Let me know if you have any questions.
Numbers Instead of Characters
It is hard to tell what is going on without seeing the remainder of your code. However, I suspect that you are confusing the numerical value and the ASCII character value for the contents of your array. (e.g. character '0' = decimal 48 (0x30 (hex), '1' = 49, 'a' = 97, etc..). See ASCIItable.com
You you pass an array to a function it decays to a pointer. That means char line[][] should really by char (*line)[SIZE_OF_SECOND_ARRAY].
It also means the sizeof trick will not work, as doing sizeof on the pointer line will just return the size of the pointer and not what it points to, you need to explicitly pass the size as an argument to the function.
You need tell function the number of columns of 2d array. Here may help you.
I am not sure if the following statement works with you
for( i = 0; i < (sizeof(line)/sizeof(line[0])); i++ )
where sizeof(line) will be 4 or something like that depends on your platform because "line" is a pointer and you get the size of pointer itself.
Correct me if I am wrong.
In this case, you should pass column number as row's.
I really don't know how to implement this function:
The function should take a pointer to an integer, a pointer to an array of strings, and a string for processing. The function should write to array all variations of exchange 'ch' combination to '#' symbol and change the integer to the size of this array. Here is an example of processing:
choker => {"choker","#oker"}
chocho => {"chocho","#ocho","cho#o","#o#o"}
chachacha => {"chachacha","#achacha","cha#acha","chacha#a","#a#acha","cha#a#a","#acha#a","#a#a#a"}
I am writing this in C standard 99. So this is sketch:
int n;
char **arr;
char *string = "chacha";
func(&n,&arr,string);
And function sketch:
int func(int *n,char ***arr, char *string) {
}
So I think I need to create another function, which counts the number of 'ch' combinations and allocates memory for this one. I'll be glad to hear any ideas about this algorithm.
You can count the number of combinations pretty easily:
char * tmp = string;
int i;
for(i = 0; *tmp != '\0'; i++){
if(!(tmp = strstr(tmp, "ch")))
break;
tmp += 2; // Skip past the 2 characters "ch"
}
// i contains the number of times ch appears in the string.
int num_combinations = 1 << i;
// num_combinations contains the number of combinations. Since this is 2 to the power of the number of occurrences of "ch"
First, I'd create a helper function, e.g. countChs that would just iterate over the string and return the number of 'ch'-s. That should be easy, as no string overlapping is involved.
When you have the number of occurences, you need to allocate space for 2^count strings, with each string (apart from the original one) of length strlen(original) - 1. You also alter your n variable to be equal to that 2^count.
After you have your space allocated, just iterate over all indices in your new table and fill them with copies of the original string (strcpy() or strncpy() to copy), then replace 'ch' with '#' in them (there are loads of ready snippets online, just look for "C string replace").
Finally make your arr pointer point to the new table. Be careful though - if it pointed to some other data before, you should think about freeing it or you'll end up having memory leaks.
If you would like to have all variations of replaced string, array size will have 2^n elements. Where n - number of "ch" substrings. So, calculating this will be:
int i = 0;
int n = 0;
while(string[i] != '\0')
{
if(string[i] == 'c' && string[i + 1] == 'h')
n++;
i++;
}
Then we can use binary representation of number. Let's note that incrementing integer from 0 to 2^n, the binary representation of i-th number will tell us, which "ch" occurrence to change. So:
for(long long unsigned int i = 0; i < (1 << n); i++)
{
long long unsigned int number = i;
int k = 0;
while(number > 0)
{
if(number % 2 == 1)
// Replace k-th occurence of "ch"
number /= 2;
k++;
}
// Add replaced string to array
}
This code check every bit in binary representation of number and changes k-th occurrence if k-th bit is 1. Changing k-th "ch" is pretty easy, and I leave it for you.
This code is useful only for 64 or less occurrences, because unsigned long long int can hold only 2^64 values.
There are two sub-problems that you need to solve for your original problem:
allocating space for the array of variations
calculating the variations
For the first problem, you need to find the mathematical function f that takes the number of "ch" occurrences in the input string and returns the number of total variations.
Based on your examples: f(1) = 1, f(2) = 4 and f(3) = 8. This should give you a good idea of where to start, but it is important to prove that your function is correct. Induction is a good way to make that proof.
Since your replace process ensures that the results have either the same of a lower length than the original you can allocate space for each individual result equal to the length of original.
As for the second problem, the simplest way is to use recursion, like in the example provided by nightlytrails.
You'll need another function which take the array you allocated for the results, a count of results, the current state of the string and an index in the current string.
When called, if there are no further occurrences of "ch" beyond the index then you save the result in the array at position count and increment count (so the next time you don't overwrite the previous result).
If there are any "ch" beyond index then call this function twice (the recurrence part). One of the calls uses a copy of the current string and only increments the index to just beyond the "ch". The other call uses a copy of the current string with the "ch" replaced by "#" and increments the index to beyond the "#".
Make sure there are no memory leaks. No malloc without a matching free.
After you make this solution work you might notice that it plays loose with memory. It is using more than it should. Improving the algorithm is an exercise for the reader.