Compare the content of two char arrays in C - c

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.

Related

Why is my for loop increasing the size of my array in C?

I'm trying to make a binary number calculator in c and I'm running into issues of my for loops doubling the size of my second array and adding the first array onto the end. I'm really confused because I thought you couldn't increase the size after already declaring it. It is happening in my equation reading function as well but in this ones complement function it's a bit simpler to see. Any ideas of how to fix this?the codethe output
welcome to stack-overflow. From next time please use inline code editor to put your code instead of images. I have taken effort put your code in the answer itself to explain the problem. Please consider this as courtesy. Its very unusual to do it. But as you are a new member, I'm doing it.
// Cole carson's original code from image:
char * onescomp(char x[16], char y[16]){
int i;
for(i=0;i<=15;i++){
if(x[i] == '0'){
y[i] = '1';
continue;
}
else if(x[i] == '1'){
y[i] = '0';
continue;
}
}
return y;
}
int main()
{
char b3n[16]={'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
char cb3n[16];
puts(b3n);
onescomp(b3n,cb3n);
puts(cb3n);
return 0;
}
Answer:
You don't need continue; in if-else blocks.
You need to add '\0' in the last cell of cb3n array. so puts() knows when string ends & stop printing.
so to quickly fix this issue you can create array with extra cell and assign all values as '\0'. so after copying fifteen 1's there will be '\0' in the end. I think in your case those extra zeros being printed might be garbage values. It looks like array is doubling but it isn't, its just printing values beyond allocated memory because '\0' has not been provided.
//Quick fix
int main()
{
char b3n[16]={'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
char cb3n[17]={'\0'}; // <--- quick fix
puts(b3n);
onescomp(b3n,cb3n);
puts(cb3n);
return 0;
}

Looping through a char array in C

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).

Compare specific strings in array of strings

I have something like this in my code:
char *objects[] = {"_muldi3.o","_negdi2.o","_lshrdi3.o","_divdi3.o","_moddi3.o","_udivdi3.o"};
/* Around 127 strings stored above, listed only few here. */
char *divmod_objs[]={"_divdi3.o","_moddi3.o","_udivdi3.o"};
for (i=0;i<obj_count;i++)
{
if (objects[i]==divmod_objs[0])
break;
else
{
/* do something */
}
}
The if statement seems to give "Segmentation fault (core dumped)" so I might be doing something wrong. What is the right way to compare these strings?
Segmentation fault basically means a pointer accessed memory outside of it's bounds (it's allocated memory area).
There is a core mistake in your code, in which you expect the equality operator "==" to compare strings the way it works in Java or C#. But the comparison of strings does not work like that in C. Instead what happens is that you it is trying to compare the [0..(obj_count-1)] char elements of the first string pointed to by "objects" array pointer to the first character of the first string pointed to by the "divmod_objs" pointer. Since the strings in object could end up being > obj_count, in that case a seg. fault is thrown up.
If you want to implement string comparison in C, you need to implement a comparison on character-by-character basis.
Basically You would need a double loop, the outer one would iterate through the string objects, the inner one would iterate within the characters of the individual strings. Plus some bells and whistles to check for array bounds etc.
Write simple function to compare strings:
bool equal(char a[], char b[])
{
for (int i = 0; a[i] != '0' && b[i] != '0'; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
and use it in your code:
char *objects[] = {"_muldi3.o","_negdi2.o","_lshrdi3.o","_divdi3.o","_moddi3.o","_udivdi3.o"};
/* Around 127 strings stored above, listed only few here. */
char *divmod_objs[]={"_divdi3.o","_moddi3.o","_udivdi3.o"};
for (i=0;i<obj_count;i++)
{
if (equal(objects[i], divmod_objs[0]))
break;
else
{
/* do something */
}
}

Segmentation fault when indexing into char array via pointer

My code is causing a segmentation fault when accessing an array element even though that element was already accessed without a problem.
int charToInt(char a)
{
int b;
if(isdigit(a))
{
b = a - '0' - 1;
}
if(isalpha(a))
{
b = a - 65;
}
return b;
}
int validPosition(char **array, int r, int c, char* position, int slots)
{
int i,k;
if(strlen(position) == 5)
{
if(!isalpha(position[0]) || !isdigit(position[1]) || position[2]!=' ' || (position[3]!='N' && position[3]!='E' && position[3]!='W' && position[3]!='S')) //lathos gramma
{
printf("\n%s", "Invalid answear.This is an example of a valid answear: A5 N");
return 2;
}
if( charToInt(position[0]) > r - 1 || charToInt(position[1]) > c - 1 )//ama vgainei eksw apo ta oria
{
printf("\n%s", "The position you choosed is out of the bountries...");
return 2;
}
printf("\n%s%c%s","position[3] is: ",position[3], " but it doesn't work >_<"); // position[3] is N
if(position[3] == 'N') //the problem is here <~~~~~~~~~~~~~~~~~~~<
{
printf("\n%s", "come on");
if(charToInt(position[0]) + slots < r)
{
for(i=charToInt(position[0])-1; i<charToInt(position[0])+slots; i++)
{
if(array[i-1][charToInt(position[1])-1] != '.')
{
printf("\n%s", "The position you choosed is not valid because there is oneother ship there");
return 2;
}
}
}
else
{
printf("\n%s", "The ship is going out of the bountries...");
return 2;
}
}
}
}
When position holds the string "A9 N", the printf correctly outputs 'N' for position[3]. For some reason when it tries to do if(position[3] == 'N'), however, a segmentation fault occurs.
Example program run:
Example of positioning: G3 E
Aircraft carrier (5 places), Give location and direction: A9 N
1
position[3] is: N but it doesn't work >_<
Well, based on your updates, it seems you have a variety of problems. For future reference, actually adding in the (possibly simplified) code showing how you were calling the function in question is better than trying to describe it using prose in a comment. There will be less guesswork for the people trying to help you.
If I'm reading your comment correctly, the code that calls validPosition looks something like this:
// "r and c are 9 and 9 in the specific example(rows columns)."
int rows = 9;
int columns = 9;
// "slots=5."
int slots = 5;
// "array is a 2d array and it contains characters(created with malloc)."
char **array = malloc(rows * columns * sizeof(char));
// "i created char position[10] in the function that called this function"
char position[10];
// "and with fgets(position, 10, stdin); i putted A9 N inside it."
fgets(position, 10, stdin);
validPosition(array, rows, columns, position, slots);
The first problem is your description of the allocation of array (I apologize if I misunderstood your comment and this isn't actually what you are doing). It should look similar to the code below for a dynamically sized two-dimensional array used with two subscripting operations (array[index1][index2], as it is in validPosition). Pointers-to-pointers (char **array) act differently than fixed sized multi-dimensional arrays (array[SIZE1][SIZE2]) when you access them that way.
// each entry in array should be a pointer to an array of char
char **array = malloc(rows * sizeof(char*));
for(i = 0; i < rows; i++)
array[i] = malloc(columns * sizeof(char));
You also need to be careful about using position after the fgets call. You should check the return value to make sure it isn't NULL (indicating an EOF or error condition). The string may not be \0-terminated in this case. In fact, all the elements may still be uninitialized (assuming you didn't initialized them before the call). This can lead to undefined behavior.
The next issue is that validPosition does not return a value on every code path. One example is if strlen(position) != 5. The other is if you enter the for loop and array[i-1][charToInt(position[1])-1] != '.' is never true (that is, the ship placement is deemed valid).
As strange as it is for an English speaker to say this to a Greek author, lets ignore internationalization and focus only on the default C local. The checks on position[0] should therefore be sufficient, though you might consider allowing your users to use lowercase letters as well. When converting position[1] from 1-based to 0-based, however, you do not account for the case when it is '0', which will result in charToInt returning -1. Furthermore, you're erroneously doing the subtraction again in the second array subscript of array[i-1][charToInt(position[1])-1].
Similarly, as pointed out by Jite and BLUEPIXY, you are doing two extra subtractions on the result of charToInt(position[0]): one in the for loop initializer (i=charToInt(position[0])-1) and one in the first array subscript of array[i-1][charToInt(position[1])-1].
Once you fix that, you might find that you are sometimes incorrectly telling the user that their selection is invalid. This is because you are checking charToInt(position[0]) + slots < r instead of <= r.
As I mentioned in my comment, one of the accesses to array is very probably the culprit behind your segmentation violation, not position[3] == 'N'. The reason you don't see the output of printf("\n%s", "come on"); is that your stdout appears to be line-buffered and there's no end of line to flush it. It is generally automatically flushed on normal program termination, however you're seg-faulting so that doesn't happen.
Finally, these are only the semantic errors I noticed. Stylistically, the code could also stand to be improved. For instance, it seems you're going to be implementing else if(position[3] == 'E', else if(position[3] == 'W', and else if(position[3] == 'S' clauses with similar logic to your if(position[3] == 'N' clause. This increases the likelihood you'll introduce an error by incorrectly copying-and-pasting and also increases your work later when you need to make a change in four places instead of one.
Since the terminology 'Segmentation Fault' I believe you are on Linux machine.
Use gdb to find the cause of error. Here are the steps.
Compile with additional -g flag (ex. gcc -g my_prog.c)
Run debugger: gdb a.out
Use 'list' command to find the line for break point (eg. first line of your function)
Set breakpoint on that line with: b 25 (if 25 is that line)
Run program with 'run' command
Use command 'next' to execute next line of code
Now the execution will pause on that line, you can examine memory, print variable contents
and stuff. But generally you want to determine on which line the execution fails and what was in which variable.
With a little playing with memory, you will easily find where the problem is. Personally, my code wont work with gdb support.
Perhaps segmentation fault at array[i-1][charToInt(position[1])-1]
i:charToInt(position[0])-1 : charToInt('A') - 1 : -1 <- Array out-of-bounds

Binary search, strcmp two dynamic arrays of strings in C

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)

Resources