How to use the character array to identify a string - c

For my class we use char arrays for strings. If I was to use an if else statement, would something like this work if I had it modified to do so?
I know an array like this would make every character broken down to simple letters. And to use an if else statement I have to go like array[1] == 'H' and so on.
Is there a way to modify the code below to spit out the information I want if I type up "Alas". Right now, it only goes to the else part.
int main()
{
char s[10];
printf("Yo, this is a string: ");
gets_s(s);
if (s == "Alas")
{
printf("B ");
}
else
{
printf("A");
}
system("pause");
}

Use the strncmp standard library function to compare two strings. Include the <string.h> header.
strncmp(const char *s1, const char *s2, size_t n)
RETURN VALUE:
Upon successful completion, strncmp() shall return an integer greater than, equal to, or less than 0, if the possibly null-terminated array pointed to by s1 is greater than, equal to, or less than the possibly null-terminated array pointed to by s2 respectively.

Now in your code s is pointer and "Alas" is treated as pointer. Pointer to another memory area. This is a reason why they are always different. Use
if (!strcmp(s, "Alas"))

Something like:
int main()
{
char s[10];
printf("Yo, this is a string: ");
gets_s(s);
if (strcmp(s, "Alas") == 0)
{
printf("B ");
}
else
{
printf("A");
}
system("pause");
}

If the only thing you want to know is whether two strings are identical or not, you can define a function yourself to check each character of two strings, returning a 0 as soon as you encounter a difference, returning a 1 only if it encounters the terminating zero on both at the same time:
SameStrings( char * s1, char * s2 ) {
for ( int i = 0; s1[i] && s2[i]; i++ )
if ( s1[i] != s2[i] )
return 0;
// if the programme advanced this far
// either one of both should be 0
return s1[i] == s2[i];
// if they are equal, then both must be 0, in which case it will return 1
// else it will return a 0
}
You can add one more argument to that function, an integer that will limit the maximum number of characters to be checked, in case, for example, you want SameStrings( "lalaqwe", "lalaasd", 4 ) to return true.
This is good if you don't want to include a library for a function that does much more than you need...

Related

Baffled by strcmp

I have a very simple function to convert a 3 char string representing a bit string to a decimal number:
int bin3_to_dec(char *bin) {
int result;
result=0;
printf("string: %s\n", bin);
printf("c0: %c\n", bin[0]);
printf("c1: %c\n", bin[1]);
printf("c2: %c\n", bin[2]);
if ((strcmp(&bin[0], "1") == 0))
result += 4;
if ((strcmp(&bin[1], "1") == 0))
result += 2;
if ((strcmp(&bin[2], "1") == 0))
result += 1;
printf("result: %d\n", result);
return result;
}
When I run the program and feed this function the string 111 it should calculate 7. Instead it outputs this:
string: 111
c0: 1
c1: 1
c2: 1
result: 1
Why is it not calculating the correct value? Why is only the third condition successfully passing?
Your string bin equal "111" really consists of four chars - that is '1', '1', '1', '\0' where the 4th char has the value zero which terminates (i.e. ends) the string.
So &bin[0] is the string "111"
and &bin[1] is the string "11"
and &bin[2] is the string "1"
So what your code is actually doing is the same as:
if ((strcmp("111", "1") == 0))
result += 4;
if ((strcmp("11", "1") == 0))
result += 2;
if ((strcmp("1", "1") == 0))
result += 1;
Only the last compare results in true so resultbecomes 1
&bin[0] is actually a pointer to a character array starting from 0th index which is 111. So, your first comparison fails. Similarly for second. But in your third comparison, &bin[2] is a pointer to character array starting from 2nd index which is 1 and hence it add 1 to result. So to make your code work:
you can check if(bin[0] == '1') // Here you compare the character at bin[0] and it is equal to 1 and so here the condition gets fulfilled.
C does not detect the end of a string until it encounters a null (i.e. \0). When you pass "111" into your function, you are actually passing a pointer to a block of memory that looks like this: "111\0". Thus, when you pass the address of bin[0] into strcmp(), strcmp operates on the full string "111". When you pass the address of bin[1] into strcmp(), strcmp operates on the string "11". Only when you pass the address of bin[2] into strcmp() do you get the behavior you were expecting, because in that case the next character in memory is a null.
if (bin[0] == '1') result += 4;
if (bin[1] == '1') result += 2;
if (bin[2] == '1') result += 1;
please note that &bin[0] is the same as bin
bin[0] is the first element
&bin[0] is a pointer to the first element just like bin
Have you tried printing &bin[1] (for example) as a string, instead of the individual characters? Because that's how strcmp() is going to see them.
In you do that, strcmp(&bin[0], "1") is clearly always non-zero, because &bin[0] is the full input string and (in our example) "111" is not at all like "1". Strings run until the null-terminator character.
You can use direct character comparisons (bin[0] == '1'), copy the character to a null-terminated string of its own, or (destructively) work from right to left and insert the null character ('\0') after the character that interests you. But you can't compare the middle of a string as a single character.
As mentioned by others, you are confusing those strings. The three of them are strings, however, string in java is an array of chars. So when you mean the string "1" using &bin[0], you are actually comparing "111". Why? Pointer to an array of chars make a string with the chars in this array starting where your pointer shows and continues to the end.
So when you point at the first letter you get "111", when you point at the second letter you get "11" and when you point at the last character you get "1", thats why your sum is 1. You can try to pass as argument the string "1111", you can see that your result is 0 intead of 1.
Your code seems somehow baffled around a function call of strcmp(), which isn't needed and would consistently return non-zero for any comparison between the string literal "1" and any "sub-string" pointed to in your code (&bin[0], &bin[1]), except for the one-printable-member-string &bin[2], if also "1". Let's have a walk-through.
As you have properly written in your function prototype, the pointer to the first element of the character array is being passed by value to your called function and copied as its argument. This is the "mechanism" for the part of memory populated by the array pointed to, to become visible by the called function, if its "upper bound" is known.
There are two means of having its upper bound known:
Passing the char array size as additional argument to the function, or
Null-terminating the char array in the calling function, so the called function can interpret it as string, which is your choice. The called function can either use strlen() to determine string length (size), or step through it, incrementing the counter, until a null-character is reached, and read size from the counter.
If the calling function already receives the array as a null-terminated string of '0' and '1' characters, the second looks more practical.
Allowing for up to as many characters as allowed by the storage capacity of the return data type of the called function (in this case int) clarifies the problem and simplifies the code. The caller function should guard against overflow.
The called function should only compare every array member's ASCII value with '1' and convert if equal.
For this strcmp isn't needed.
Please see the comments in this demonstration code, based on your post:
#include <stdio.h>
#include <string.h>
#define BPB 8 //bits per byte
int bin_to_dec(char *bin) //called function
{
int result=0;
int l = (int)strlen(bin);
for (int i = 0; i < l; i++){
printf("c%d: %c\n", i, bin[i]);
if(bin[i] == '1') //compare value of the i-th element
result += 1<<(l - i - 1); //convert to power-of-two and add to the result
}
return result;
}
int main(int argc, char *argv[]) //calling function
{
size_t siz = BPB*sizeof (int); //size for each char to represent one bit
char s[siz + 1]; //characters, each representing one bit + terminating '\0'
if((argc < 2)||(argc > 2)) //fail-safe check for correct count of arguments
return 1;
size_t len = strlen(argv[1]) ; //get length of the input string
if ( len > siz ) //check against too long input which would cause overflow
return 2;
strncpy(s, argv[1], len);
s[len] = '\0'; //appending the terminating null-character
for(int i = 0; i < (int)len; i++)
if((s[i] < '0')||(s[i] > '1')) //fool-proof check against 'off-limit' input
return 3;
printf("decimal: %d\n", bin_to_dec(s));
return 0;
}

Check if a string is the substring of another string

I was having some problem when trying to check if a string is the substring of another string. Here is the expected output:
Enter a source string: abc
Enter the target string: abcde
findSubstring(): 1
Enter a source string: abcde
Enter the target string: cdef
findSubstring(): -1
And here is my code which used the strstr standard string library:
int main()
{
char sourceStr[40], targetStr[40];
printf("Enter a source string: ");
gets(sourceStr);
printf("Enter the target string: ");
gets(targetStr);
printf("findSubstring(): %d\n", findSubstring(sourceStr, targetStr));
return 0;
}
int findSubstring(char *s, char *t) {
if (strstr(s, t) != NULL) {
return 1;
}
return 0;
}
With these code, it works perfectly. However, I was told that I am not supposed to use any standard string library, so I was thinking how should I modify it?
Sorry for posting the question with no error but I seriously need a head start, as I googled for quite a while and I still have no idea how to do it.
Thanks in advance.
The key here is that when working in C, strings do not exist as an actual data structure as they do in, say, C++'s STL (std::string) or Java's String objects.
Instead, you should be treating them as a sequence of individual characters, whose end is denoted by an agreed-upon convention, which in this case is the 'NULL' character, which is the value 0 and can be represented in a string literal using the escaping symbol.
This is why strings are passed around as pointers to char in C, which actually point to the first character in the sequence.
Therefore, you can use pointer arithmetic to check the subsequent characters, until you find a value of 0, which means the string has ended.
By using a snippet like this, you can check any given string character by character.
char * pointer_to_string; //Pointer to start of string
char * pointer_to_character = pointer_to_string; //Start at the first character
while (*pointer_to_character != '\0'){ // Repeat while we haven't found the end
char c = *pointer_to_character; // The character the pointer is pointing to.
//do what you need to with the character
pointer_to_character++; //Now it points to the next character
}
// We exit the loop once the end of the string is found
HOWEVER:
This means you must be careful since this kind of string manipulation has its risks, since you are depending on finding an actual NULL character that ends the string, and if it's not present, the loop would run indefinitely, and in more complex examples, would easily lead to a segmentation fault and a crash.
In short, when using raw pointers in C, gotta be extra careful with what you do with the underlying memory, and certainly using known libraries and not reinventing the wheel tends to be the best option, but since I'm inclined to believe the purpose of the assignment is learning about string representation and pointer arithmetic, we'll do with that.
With this, you should be able to figure out what you need to do to solve the problem.
Well, if you don't want to use standard library, here is one way to do it.
This is simple code that satisfies the purpose:
int FindString(char *Str,const char *SubStr)
{
size_t count = 0 , x , y ;
size_t Str_len = strlen( Str ) ;
size_t SubStr_len = strlen( SubStr );
size_t diff = Str_len - SubStr_len;
if( SubStr_len > Str_len )
return 0;
for( x = 0 ; x <= diff ; x++ )
{
for( y = 0 ; y < SubStr_len ; y++ )
{
if( Str[ x + y ] == SubStr[ y ] )
count++;
else
{
count = 0;
break;
}
}
if( count == SubStr_len )
return 1;
}
return 0;
}
Also, if you want the version that compares insensitively, notify me in a comment.

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.

'Scanf' for a String - Program crashing?

Why is this crashing when I input the string? I don't think I'm reading in the string right but the program gives me an error on the first 'scanf.' The program should be correct but this is C not C++. Most help that I could find was for C++.
//Andrei Shulgach
//April 27th, 2015
/*A string is a palindrome if it can be read forward and backward with the same
meaning. Capitalizations and spacing are ignored.*/
#include <stdio.h>
#include <stdlib.h>
int newStrCmp (const char *string1, const char *string2);
int main()
{
//Local Declarations
int dummy, value;
char string1[100],string2[100];
printf("Please enter the 1st string: ");
scanf_s("%99s", string1[100]);
printf("\nPlease enter the 2nd string: ");
scanf_s("%99s", string2[100]);
//Call Function and get value
value = newStrCmp(string1, string2);
if (value == 0)
printf("The strings are equal.\n");
else
printf("The strings are not equal.\n");
scanf_s("%d",&dummy);//Keep Window Open
return 0;
}
int newStrCmp (const char *string1, const char *string2)
{
//Local Declarations
int value = 0;
while (string1[value] == string2[value])
{
if (string1[value] == '\0' || string2[value] == '\0')
break;
value++;
}
if (string1[value] == '\0' && string2[value] == '\0')
return 0;
else
return -1;
}
You must enable all compiler warnings that you can get from your compiler; the above code shouldn't have compiled.
This:
scanf_s("%99s", string1[100]);
invokes undefined behavior since it indexes outside the 100-character string1 array. Remember that C arrays are indexed from 0. It also fails to comply with scanf_s()'s requirement that the size be specified for all string conversions.
It then probably1 causes more undefined behavior, when scanf_f() interprets a single character as a buffer address where input is to be stored (assuming the call happens, of course).
This is not valid code.
It should simply pass the address of the first character in the array:
scanf_s("%99s", string1, sizeof string1);
Here, string1 is the same as &string1[0]; the name of an array evaluates to the address of its first element in many contexts. We then use sizeof string1 as the third argument to specify the size of the string1 buffer, which is required.
1 You cannot reason about what happens after undefined behavior has happened with any certainty.
The issue is you are 'scanf'ing into index 100 of your length 100 buffer, i.e. out-of-bounds.
scanf_s("%99s", string1);
Also your comparison would be safer as a for loop that ensures value is less than 100, rather than a while loop.
In the future, please include the error message.

Comparing string through pointers

I am new to the C language. Please, could someone tell me why I am always getting zero as output when comparing differing strings using my own implementation of strcmp?
I wrote the function xstrcmp to compare two strings: if they are equal, then it returns 0; otherwise, it returns the numeric difference between the ASCII values of the first non-matching pair of characters.
#include<stdio.h>
int xstrcmp(char*,char*);
int main()
{
int i;
char string1[]="jerry";
char string2[]="ferry";
i=xstrcmp(string1,string2);
printf("difference=%d\n",i);
return 0;
}
int xstrcmp(char*p,char*q)
{
int m;
while(*p!=*q)
{
if((*p=='\0')&&(*q=='\0'))
break;
p++;
q++;
}
m=(*p)-(*q);
return m;
}
You loop until you find equal chars, then you subtract them -- so of course the result is always 0.
Also, the condition inside the loop will always fail ... if the chars aren't equal, they can't both be NUL.
That should be enough for you to fix your code.
The reason why you get zero always is that your while loop while(*p!=*q) means that the loop will execute as long as the characters are NOT same.
The exit from loop will happen when *p and *q have the same value.
Hence the return value, which is m=(*p)-(*q); will always be zero.
while (*p == *q) /* as long as they have same value, loop; otherwise exit */
{
p++; /* increment the pointers */
q++;
}
return (*p)-(*q);
would be the way to go.

Resources