Compare character by character 2 strings - c

I am trying to code a program that tells me if 2 strings are identcal. If they have one different chracter they are not.
I have this code, but it does not work, why?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main() {
char str1[30], str2[30];
int i;
printf("\nEnter two strings :");
gets(str1);
gets(str2);
for (i=0;str1[i]==str2[i];i++)
if (str1[i]!=str2[i]){
printf("They are not identical");
}
else continue;
return (0);
}
It compiles with 0 errors and 0 warnings, but when I introduce 2 not identical strings it returns nothing. (The same happens when I introduce 2 identical strings, but that is how is supposed to be)
What should I do to fix it?

There is one important thing wrong here. First of all: The classic "c style string" is null terminated. Allthough there are other alternatives (like storing the length outside of the string), the null terminated string is part of the language (as string literals in code are null terminated by the compiler), and the runtime library (most string functions handle the \0 at the end of the string).
gets also appends a \0 at the end of the entered string:
http://www.cplusplus.com/reference/cstdio/gets/
You are comparing not only the entered strings, but also anything (random) after that string in memory.
It should look like this:
for(int i=0;str1[i]==str2[i];i++){
if(str1[i]==0) {
printf("equal");
}
}
printf("not equal");
There are other alternative, like using pointer. But on modern compilers they should produce roughly the same machine code.
Please note that there are C runtime library functions to compare strings:
strcmp is the most basic one, just two char *:
strncmp allows to specify the maximium chars to compare, do compare a part of a string:
There are other, just check out the links.
Please note that it's better to use the library functions, because even if in such a "simple" function. There are optimized ways to compare string. Like comparing in native word sizes. On 32 bit platforms you spend four time more time in comparation, not including the masking needed to perform byte wise operations.

Your for loop is:
for (i=0;str1[i]==str2[i];i++)
if (str1[i]!=str2[i]){
printf("They are not identical");
}
else continue;
Let's say str1 is "abc" and str2 is "xyz".
The conditional in the for loop will evaluate to false for i = 0. Hence, you will never get to the statement:
if (str1[i]!=str2[i]){
Consequently, you will never execute:
printf("They are not identical");
You can fix the logic error by using:
for (i=0; str1[i] != '\0' && str2[i] != '\0'; i++)
{
if (str1[i]!=str2[i]) {
break;
}
}
// If at end of the loop, we have reached the ends
// of both strings, then they are identical. If we
// haven't reached the end of at least one string,
// then they are not identical.
if ( str1[i] != '\0' || str2[i] != '\0' )
{
printf("They are not identical");
}

I have this code, but it does not work, why?
Because your looping condition str1[i]==str2[i] will make the inner if condition be always false.
What should I do to fix it?
Simple code:
for ( i=0; str1[i]==str2[i] && str1[i]!='\0'; i++) {
}
if ( str1[i]!=str2[i] ) {
printf("They are not identical");
}
or
i=0;
while ( str1[i]==str2[i] && str1[i]!='\0' ) {
i++;
}
if ( str1[i]!=str2[i] ) {
printf("They are not identical");
}

Let's say you have two string in which the first character is different. then you will not enter the loop as the condition of the loop (str1[i]==str2[i]) fails, therefore the condition should be ( str1[i]!='\0' && str2[i]!='\0' ). The '\0' is the last character of the c-style string.
You can also use string built in functions like " strcmp(str1,str2) ".

Related

Checking for string null terminators in C

I know what the null-terminator in C is represented by \0 and has the numerical value of 0. However, when I execute the following code below, the program treats the null terminator as %. I searched this up online but I couldn't find anyone with this issue.
int main(){
char* forward = "hello";
int forward_length = 0;
while (*(forward++) != '\0') {
printf("%d\n", forward_length++);
}
if(*forward == '%'){
printf("Terminator Found");
}
}
The output is:
0
1
2
3
4
Terminator Found
Clearly, forward[5] does not equal the char %. Can someone please let me know what is wrong with the program?
The construction leaves forward advanced too far. This is because the post-increment will run even if the loop condition is false (as it is inside the loop condition). The obvious fixed loop is as follows:
for (;*forward != '\0'; ++forward)
printf("%d\n", forward_length++);
If you prefer to keep the while loop, --forward after the while loop will fix it.

while loop is not breaking

I am not able to find out the reason for the misbehavior of the below code. This is a simple code to accept characters until either * is entered or until array size is reached and then print the characters read from the keyboard. It looks like the reading part is fine. Also if I enter * before array size is reached everything is OK. But if I do not enter * and wait until array size is reached in reading portion, I have the trouble. While printing it prints the characters read, but after that some garbage is printed. Ran through debugger, but while loop is not breaking when index is 3 or more.
int main()
{
char myStr [3];
unsigned int index=0;
printf("Enter Single characters. Enter * to stop\n");
do
{
scanf(" %c",&myStr[index]);
index++;
} while ((myStr[index-1]!='*')&&((index)<(sizeof(myStr)/sizeof(myStr[0]))));
index=0;
while ((myStr[index]!='*')&&(index<(sizeof(myStr)/sizeof(myStr[0]))))
{
printf("%c",myStr[index]);
index++;
}
printf("\n");
return(0);
}
The code runs into undefined behaviour on the printf loop's last iteration here
while ((myStr[index]!='*')&&(index<(sizeof(myStr)/sizeof(myStr[0]))))
{
...
as it in fact is doing
while ((myStr[3] ....
with myStr[3] accessing myStr out-of-bounds.
To fix this do:
while ((index < (sizeof(myStr)/sizeof(myStr[0]))) && (myStr[index] != '*'))
Boolean short-circuiting will take care of myStr[3] not being executed.
You are manipulating strings, witch need to be null-terminated.
You should use fgets(3) to get your string and then strlen(3) to get the length.
Then you can move in your string by
while (str[i] != '*' && i < strlen(str))
good luck

what is wrong with my understanding of strings ie character arrays ending with '\0' element in C programming

I am a total beginner and recently started studying strings in C programming.
I understand that we need to supply the '\0' (null) character at the end of the string (to act as a end of string marker).
So if my character array is
char string[]={'H','E','L','L','O','\0'};
This makes it a 6 element array.
So I was going through this simple example of copying one string to another string. Here is the code.
#include<stdio.h>
int main()
{
char string1[80],string2[80];
int i;
printf("Enter a string \n");
gets(string2);
for(i=0; string2[i]!= '\0';i++)
{
string1[i]=string2[i];
}
string1[i]='\0'; /*here is my problem*/
printf("The copied string is \n");
printf("%s",string1);
printf("\n");
printf("The number of character are \t");
printf("%d \n",i);
}
why isn't it string1[i+1]='\0'??
I mean, isn't by putting string1[i]='\0' overwrite the last element that was just stored in the above for loop?
The code is correct, because of the way the for loop works:
for(A; B; C)
CODE;
Is equivalent to:
A;
while (B)
{
CODE;
C;
}
(Except for the use of continue, that will jump to the increment expression, not the condition, as it would happen with a while).
And since the loop ends when string2[i] != '\0', it is obvious that upon exiting, i is the index for the proper NUL byte. So after that:
string1[i] = '\0';
will write the \0 at the same place as it is in string2.
Usually for this kind of analysis it is helpful to think about preconditions and postconditions. That is, assuming there are no break and no goto, you are guaranteed that at the beginning of a for or while loop the condition is always true. And just after the end of a for or while loop the condition is always false.
Your particular code, illustrated with assert calls:
for(i=0; string2[i] != '\0'; i++)
{
asssert(string2[i] != '\0');
string1[i] = string2[i];
}
asssert(string2[i] == '\0');
string1[i] = '\0';
Looking at the code, it seems as if i is incremented as long as the character is not '\0'. So, the last time it's incremented, it increments to a new position that hasn't had a character written to it yet.
So, at the end of the loop, there's a space to write the null character to.

Strcmp() function isn't returning 0

i was trying to compare two strings using strcmp() , and in the case they're equal the function returns -1 (meaning they are not equal) , i dont know whats wrong .
int main()
{
char password[]={'6','6','6','6','6','6'};
char passmatch[6];
int i =0;
for(i ; i<6 ; i++)
{
passmatch[i]='6';
}
printf("\n");
if(strcmp(password,passmatch)==0)
{
printf("Strings are equal");
}
else
{
printf("String are'nt equal");
}
return 0;
}
In C, strings need to be null terminated in order to be used with the standard library. Try putting a '\0' at the end, or make a string literal in the "normal" way, e.g. char password[] = "666666";, then the language will automatically put \0 at the end.
The problem is that in C '6' (with quotes) is not the same as 6 (without quotes). That's why this loop
for(i ; i<6 ; i++) {
passmatch[i]=6; // <<== Should be '6', not 6
}
is not assigning what you want it to assign. If you put quotes around this 6 as well, you would get the right content, but your program would remain broken, because strcmp requires null termination.
You can fix it in two ways:
Add null termination to both C strings, either manually or by initializing with a string literal,
Switch to using memcmp, which takes length, and therefore does not require null termination.

Cannot Break Out of a "While" loop

I am converting a 2-d char array into a 2-d int array, and I need to break out of the while loop if \0 or \n comes in the string. This code gives segmentation fault.
Definition of Array is and the indices are less than 1000 and the 2-d char array tempCharArray is already stored. What is the problem with my code?
//Array[tempCount][1000];
for(int i=0;i<tempCount;i++)
{
strtok(tempCharArray[i]," ");
while(tempCharArray[i]!="\0" || tempCharArray[i]!="\n")
{
Array[i][arrayindex]=atoi(strtok(NULL," ");
arrayindex++;
}
arrayindex=0;
}
You are a little mixed up (a) between char literals and string literals and (b) with your while loop logic.
Change this line:
while(tempCharArray[i]!="\0" || tempCharArray[i]!="\n")
to:
while(tempCharArray[i]!='\0' && tempCharArray[i]!='\n')
Note that your compiler should have warned you about mistake (a) - you do have warnings enabled, I hope ?
Edit: it seems from subsequent comments that tempCharArray may actually be an array of strings ? In that case you would need to do this to fix problem (a):
while(strcmp(tempCharArray[i],"")!=0 && strcmp(tempCharArray[i],"\n")!=0)
Note that you can not compare strings with == or != - you need to use strcmp.
The logic bug and its fix still apply of course.
If tempCharArray is the char array, you are trying to compare a single character with a complete string. That will not do what you want it to. Instead compare it to a character literal:
while(tempCharArray[i]!='\0' || tempCharArray[i]!='\n')
Note the use of single quotes instead of double.
You need to use && instead of || because the loop continues as long as the condition is true (and this is—in your case—as long as tempCharArray[i] is '\0' and '\n'
You need to use single quotes, because you compare character literals
This leads to
while (tempCharArray[i] != '\0' && tempCharArray[i] != '\n')

Resources