As mentioned by PaulMcKenzie, it seems that you apply concepts of other languages directly to the c programming language, mostly by guessing. If you do not have a book to start with, use at least google to find some tutorials. For example, I entered "c strings introduction" and got - among others - this link, which explains a lot of the issues you are currently having.
The following does not answer your question or even solve your homework, but maybe it gives you enough hints to start.
A "string" in c is an array of characters, terminated by a 0 (often written as '\0'.
String literals are enclosed in double quotes, i.e. "hello" (not 'hello').
Single characters of a string can be accessed by an index, e.g. char c = ch[0] of char c = ch[5] or int i=3; char c = ch[i].
A loop that iterates through the characters of a string and looks for an A could look as follows:
int i=0;
int found = 0;
while (!found && i < 80 && ch[i] != '\0') {
if (ch[i] == 'A')
found = 1;
i++;
}
This is not meant as an answer; It is just that I am a beginner, too (though in other fields than C); and beginners should help beginners :-) Have fun learning C, use google and good books, and be aware that it will take some time.
Answer from Stephan Lechner on Stack OverflowHow do I properly compare strings in C? - Stack Overflow
Compraring Char array without using strcmp in C - Stack Overflow
c - proper way of comparing two strings other than strcmp - Stack Overflow
Compare two strings character by character in C - Stack Overflow
You can't (usefully) compare strings using != or ==, you need to use strcmp:
while (strcmp(check,input) != 0)
The reason for this is because != and == will only compare the base addresses of those strings. Not the contents of the strings themselves.
Ok a few things: gets is unsafe and should be replaced with fgets(input, sizeof(input), stdin) so that you don't get a buffer overflow.
Next, to compare strings, you must use strcmp, where a return value of 0 indicates that the two strings match. Using the equality operators (ie. !=) compares the address of the two strings, as opposed to the individual chars inside them.
And also note that, while in this example it won't cause a problem, fgets stores the newline character, '\n' in the buffers also; gets() does not. If you compared the user input from fgets() to a string literal such as "abc" it would never match (unless the buffer was too small so that the '\n' wouldn't fit in it).
Here you have a solution, is prety like your code, but I have made some changes. I took out the returns in the middle of the loop, because they break the structure, in this way it is easier to analyze. Finishing, I added a new condition to the while, so when the end of string is found, the loop ends
int compare_info(char *array1, char *array2)
{
int i;
int response = 0;
i = 0;
while(array1[i] == array2[i] && response == 0 )
{
if(array1[i] == '\0' || array2[i] == '\0'){
response = 1;
}
i++;
}
return response;
}
Here you have a solution
int compare_info(char *array1, char *array2)
{
if ((array1 == NULL) || (array2 == NULL))
return 0;
while ((*array1 != '\0') && (*array2 != '\0') && (*array1 == *array2))
{
array1++;
array2++;
}
return (*array1 == *array2);
}
or perhaps you like this more
int compare_info(char *array1, char *array2)
{
int i;
i = 0;
if ((array1 == NULL) || (array2 == NULL))
return 0;
while ((array1[i] != '\0') && (array2[i] != '\0') && (array1[i] == array2[i]))
{
i++;
}
return (array1[i] == array2[i]);
}
you can make the arguments const it would be better style since if you only want to compare the strings, you guarantee that the function wont modify them i mean compare_info(const char *array1, const char *array2)
Literal strings in C are really arrays of characters, whose life-time last the entire run-time of the program.
When you get a pointer to a literal string, you get a pointer to its first character (it's normal array-to-pointer decay).
Also, the C specification allows compilers to reuse literals. So for example all instances of "oliver bier" can (and most likely will) be the exact same array, and the pointers to its first character will then of course also be the same.
That's the reason that the comparison x == "oliver bier" will work.
But if you change it to:
char x[] = "oliver bier";
Then the comparison will no longer work, as the pointer to the array x and the pointer to the array "oliver bier" will be different.
Most of the time, calling a function like strcmp is the proper and the only way of reliably comparing two strings. Most of the time, checking pointer equality is not a reliable way.
The problem is that two different pointers can point to two different memory regions that contain separate copies of the same string. You can have this:
+---+ +---+---+---+---+---+---+---+---+---+---+---+---+
p1: | *--------> | o | l | i | v | e | r | | b | i | e | r |\0 |
+---+ +---+---+---+---+---+---+---+---+---+---+---+---+
+---+ +---+---+---+---+---+---+---+---+---+---+---+---+
p2: | *--------> | o | l | i | v | e | r | | b | i | e | r |\0 |
+---+ +---+---+---+---+---+---+---+---+---+---+---+---+
Or you can have this:
+---+ +---+---+---+---+---+---+---+---+---+---+---+---+
p3: | *--------> | o | l | i | v | e | r | | b | i | e | r |\0 |
+---+ +---+---+---+---+---+---+---+---+---+---+---+---+
^
+---+ |
p4: | *------------'
+---+
p1 and p2 point to different strings, so the pointers will compare unequal. p3 and p4 point to the same string, so the pointers will compare equal.
If the pointers compare equal, obviously strcmp will say the strings are equal, too. But if the pointers are different, the strings might be the same (as in p1 and p2), or they might be different.
Sometimes people write things like
if(str1 == str2 || strcmp(str1, str2) == 0)
This checks to see whether the two strings str1 and str2 are the same. If the pointers are equal, then the strings are the same, and only if the pointers are not equal does the code perform the (more expensive) call to strcmp to check the actual, pointed-to characters.
When you have two string literals in your program that happen to be the same, like
char *w = "oliver bier";
char *w2 = "oliver bier";
or
char *w = "oliver bier";
...
if(w == "oliver bier") { ... }
you can't predict, in general, whether their pointers will be the same or different, whether the compiler was clever enough to have one in-memory copy of the string do double duty for its use in multiple places. Once upon a time this "cleverness" was quite rare, although I gather that today it's pretty common.
Why are you using a nested for loop for this? If both strings are of size n do this:
Copyfor(int i=0;i<n;i++){
if(string1[i]==string2[i]){
//do something
else if(// lesser than condition)
//do something else
else if(//greater than condition)
//do something else other than the previous something
}
Here you when i=0, you are comparing string1[0] with string2[0], when i=1, you compare string1[1] with string2[1] and so on.....
Your approach with nested loops isn't very well thought-out.
Clearly it will compare all letters of the second string against the first letter of the first string, then do the same for the second letter of the first string, and so on. Not at all the desired behavior.
Re-implementing strcmp() isn't very hard, here's a shot:
Copyint my_strcmp(const char *a, const char *b)
{
for(; *a && *b && *a == *b; ++a, ++b)
;
if(*a < *b)
return -1;
return *a > *b;
}
Note that it returns zero when the strings are equal. A good way to write a test is:
Copyif(my_strmcp(a, b) == 0)
{
printf("two equal strings: '%s' and '%s'\n", a, b);
}
Some people write it as if(!my_strcmp()) but I don't recommend that, since it's mashing up so many concepts.
Hi, I'm working just for fun on a fast comparison for strings written in C, with the intent of being faster than the normal strncmp function, which is currently the code bellow
```
int fast_strncmp(const char *str1, const char *str2, int len) {
const char *final_pos = (str1 + len) - 4;
while (str1 < final_pos) {
// if characters differ, or end of the second string is reached
if (*((uint32_t *)str1) != *((uint32_t *)str2)) {
break;
}
// move to the block of characters
str1 += 4;
str2 += 4;
}
final_pos += 4;
while (str1 < final_pos) {
if (*str1 != *str2 || *str1 == 0 || *str2 == 0) {
return *str1 - *str2;
}
// move to the next pair of characters
str1++;
str2++;
}
return 0;
}
```Is there any clear problem with the code that could make it a bad option for fast string comparisons. When I wrote it a couple of weeks ago, I didn't think there could be any problem with it, but this week I was watching a couple of videos about C programming and it was mentioned that casting an array of 4 uint8_t to a uint32_t could be a problem. I'm even using this function at work and haven't had a single problem or warning, but since I'm planning to make a youtube video about it, I want to guarantee that my code won't be a problem for other people.
On top of that I've made a couple of benchmarks on the performance to be sure it really is fast, so I've compared it to strncmp and an implementation by https://github.com/mgronhol, that I found here: https://mgronhol.github.io/fast-strcmp/, which got me the following results:
EDIT: reddit was not cooperating with me posting the results text in a well formatted way, so here's the link to the file:
https://github.com/BenjamimKrug/fast_string_comparison/blob/main/results.txt
As you can see, running on the STM32 and the ESP32, my algorithm runs faster by a little compared to the fast_compare function by mgronhol, but running on my PC, it's performing terribly. Does anyone know why that is?
You can find more info about the code in my github repository where I put everything related to this test: https://github.com/BenjamimKrug/fast_string_comparison
P.S.: Sorry if this is the wrong subreddit for this kind of thing, I was going to post it on r/programming, but after reading the rules, I saw that maybe it was best to post it here.
EDIT: fixed code formatting
A char variable is actually an 8-bit integral value. It will have values from 0 to 255. These are almost always ASCII codes, but other encodings are allowed. 0 stands for the C-null character, and 255 stands for an empty symbol.
So, when you write the following assignment:
char a = 'a';
It is the same thing as this on an ASCII system.
char a = 97;
So, you can compare two char variables using the >, <, ==, <=, >= operators:
char a = 'a';
char b = 'b';
if( a < b ) printf("%c is smaller than %c", a, b);
if( a > b ) printf("%c is smaller than %c", a, b);
if( a == b ) printf("%c is equal to %c", a, b);
Note that even if ASCII is not required, this function will work because C requires that the digits are in consecutive order:
int isdigit(char c) {
if(c >= '0' && c <= '9')
return 1;
return 0;
}
In C the char type has a numeric value so the > operator will work just fine for example
#include <stdio.h>
main() {
char a='z';
char b='h';
if ( a > b ) {
printf("%c greater than %c\n",a,b);
}
}
The following code is completely ok in C
No, Not at all.
In your code
if(ch=="a")
is essentially trying to compare the value of ch with the base address of the string literal "a",. This is meaning-and-use-less.
What you want here, is to use single quotes (') to denote a char literal, like
if(ch == 'a')
NOTE 1:
To elaborate on the difference between single quotes for char literals and double quotes for string literal s,
For char literal, C11, chapter ยง6.4.4.4
An integer character constant is a sequence of one or more multibyte characters enclosed in single-quotes, as in
'x'
and, for string literal, chapter ยง6.4.5
Acharacter string literal is a sequence of zero or more multibyte characters enclosed in double-quotes, as in
"xyz".
NOTE 2:
That said, as a note, the recommend signature of main() is int main(void).
I wouldn't say the code is okay in either language.
'a' is a single character. It is actually a small integer, having as its value the value of the given character in the machine's character set (almost invariably ASCII). So 'a' has the value 97, as you can see by running
char c = 'a';
printf("%d\n", c);
"a", on the other hand, is a string. It is an array of characters, terminated by a null character. In C, arrays are almost always referred to by pointers to their first element, so in this case the string constant "a" acts like a pointer to an array of two characters, 'a' and the terminating '\0'. You could see that by running
char *str = "a";
printf("%d %d\n", str[0], str[1]);
This will print
97 0
Now, we don't know where in memory the compiler will choose to put our string, so we don't know what the value of the pointer will be, but it's safe to say that it will never be equal to 97. So the comparison if(ch=="a") will always be false.
When you need to compare a character and a string, you have two choices. You can compare the character to the first character of the string:
if(c == str[0])
printf("they are equal\n");
else printf("confusion\n");
Or you can construct a string from the character, and compare that. In C, that might look like this:
char tmpstr[2];
tmpstr[0] = c;
tmpstr[1] = '\0';
if(strcmp(tmpstr, str) == 0)
printf("they are equal\n");
else printf("confusion\n");
That's the answer for C. There's a different, more powerful string type in C++, so things would be different in that language.
I am trying to write a program and I've run into a compilation error.
--------------------------------------------
CODE:
-------------------------------------------
#include <stdio.h>
#include <cs50.h>
int main(void)
{
string country = get_string("Country: ");
if (country == "england")
{
printf("TEST\n");
}
}
-----------------------------------------------
ERROR MESSAGE:
--------------------------------------------
countries.c:9:17: error: result of comparison against a string literal is unspecified (use an explicit string comparison function instead) [-Werror,-Wstring-compare]
if (country == "england")
^ ~~~~~~~~~
1 error generated.
make: *** [<builtin>: countries] Error 1
------------------------------------------------------------------
This seems to happen whenever i put a string in an if statement. Any help?
Thank you.
Hi, I'm working just for fun on a fast comparison for strings written in C, with the intent of being faster than the normal strncmp function, which is currently the code bellow
```
int fast_strncmp(const char *str1, const char *str2, int len) {
const char *final_pos = (str1 + len) - 4;
while (str1 < final_pos) {
// if characters differ, or end of the second string is reached
if (*((uint32_t *)str1) != *((uint32_t *)str2)) {
break;
}
// move to the block of characters
str1 += 4;
str2 += 4;
}
final_pos += 4;
while (str1 < final_pos) {
if (*str1 != *str2 || *str1 == 0 || *str2 == 0) {
return *str1 - *str2;
}
// move to the next pair of characters
str1++;
str2++;
}
return 0;
}
```Is there any clear problem with the code that could make it a bad option for fast string comparisons. When I wrote it a couple of weeks ago, I didn't think there could be any problem with it, but this week I was watching a couple of videos about C programming and it was mentioned that casting an array of 4 uint8_t to a uint32_t could be a problem. I'm even using this function at work and haven't had a single problem or warning, but since I'm planning to make a youtube video about it, I want to guarantee that my code won't be a problem for other people.
On top of that I've made a couple of benchmarks on the performance to be sure it really is fast, so I've compared it to strncmp and an implementation by https://github.com/mgronhol, that I found here: https://mgronhol.github.io/fast-strcmp/, which got me the following results:
EDIT: reddit was not cooperating with me posting the results text in a well formatted way, so here's the link to the file:
https://github.com/BenjamimKrug/fast_string_comparison/blob/main/results.txt
As you can see, running on the STM32 and the ESP32, my algorithm runs faster by a little compared to the fast_compare function by mgronhol, but running on my PC, it's performing terribly. Does anyone know why that is?
You can find more info about the code in my github repository where I put everything related to this test: https://github.com/BenjamimKrug/fast_string_comparison
P.S.: Sorry if this is the wrong subreddit for this kind of thing, I was going to post it on r/programming, but after reading the rules, I saw that maybe it was best to post it here.
EDIT: fixed code formatting
I have written a complete version of what I think you are trying to do:
#include <string.h>
void main()
{
char command[20];
scanf("%s",command);
// command and "hello" can be less than, equal or greater than!
// thus, strcmp return 3 possible values
if (strcmp(command, "hello") == 0)
{
printf("\nThe user said hello!");
}
}
Several people have commented about using scanf and they are correct, except that a new programmer has to start somewhere in learning this stuff, so don't feel too bad we are all learning...
Hope this helps.
strcmp returns 0 when the strings are the same. I have code that uses strcmp comparing character arrays to string literals, and I was quite confused when it wasn't working. Turns out it was wrong for me to assume it would return 1 when the string are the same!
Maybe you've made the same mistake?