I have a delete
function on array of structures books
. I'm passing it an array of records, author of book
and name of book
and size of the list
.
Now here given that list[0].author
and list[5].author
and author
all are equal to "Dan Brown" (same string)
void delete(struct books *list,char author[],char name[],int n)
{
int i,a;
a=strcmp(list[0].author,list[5].author);
printf("%d\n",a); // prints 0
a=strcmp(list[0].author,author);
printf("%d\n",a); // prints other than 0
}
Why is it happening? What's wrong here?
From the documentation of fgets
:
Reading stops when a newline character is found, at end-of-file or error. The newline, if any, is retained.
This means that fgets
will not remove the final '\n'
from the end of the read string. Thus, your strings are:
- "Dan Brown"
- "Dan Brown"
- "Dan Brown\n"
They're not equal.
This is a very common issue when using fgets
. That's why I usually prefer scanf
, like this:
char buffer[BUF_LEN];
char format[16];
int scanf_result;
sprintf(format, "%%%u[^\n]", BUF_LEN);
//....
do
{
//TODO: Ask for input
scanf_result = scanf(format, buffer);
switch (scanf_result)
{
case -1: //TODO: Print error message and exit
case 0: //TODO: Print error mesage and break
}
//Discard remainings of buffered input line
while (getchar() != '\n') {;}
} while (1); //Ugly, but plain
Otherwise, you can use fgets
with something like this:
int buf_len;
//TODO: Ask for input
while (fgets(buffer, BUF_LEN, stdin) == NULL)
{
//TODO: Check and handle error
}
buf_len = strlen(buffer);
//Remove trailing '\n', if present
if (buffer[buf_len - 1] == '\n')
{
buffer[--buf_len] = '\0';
}
Even though it's easier, I don't like this second method, because strlen
scans the string another time to determine its length. In most cases, this is not a performance issue, I avoid it because I have my own mental issues.
You should verify your inputs. Sometimes by more than one method is necessary. Here, I am using strlen()
, and strstr()
, because if the length is ==
, and a substring exists, then the strings ARE equal. So, try something like this to verify the input strings are what you thing they are before making a conclusion:
Note: the enum is of course not necessary, but included here to add clarity to example of output.
enum {
SAME, //0
NOT_SAME //1
}
void delete(struct books *list,char author[],char name[],int n)
{
int i,a, len1, len2;
A = NOT_SAME;
len1 = strlen(list[0].author);
len2 = (list[5].author);
if(strstr(list[0].author,list[5].author) && (len1==len2)) a = SAME;
printf("%d\n",a);
a = NOT_SAME;
len1 = strlen(list[0].author);
len2 = (author);
if(strstr(list[0].author,author) && (len1==len2)) a = SAME;
printf("%d\n",a);
}
check second strings by printing character by character.
Especially author
string.
for(i=0; i < strlen(list[0].author);i++)
{
if(list[0].author[i]!=author[i])
{
printf("this is position is not matching\n",i+1);
//try to print characters and also print ascii characters.
break;
}
}
//or simply try to use strncpy()