1
#include <stdio.h>
#include <string.h>

int in_mot(char *str) //check whether input from text file in mot table
{
    FILE *fp_mot;
    int i = 0, j = 0, r;
    char check[300], first_field[7];

    fp_mot = fopen("mot.txt", "r");

    while (1)
    {
        if (fgets(check, sizeof(check), fp_mot) == NULL)
        {
            printf("EOF");
            return 0;
        }
        else
        {
            i = 0;
            for (i = 0; i < 7; i++)
                first_field[i] = 0;

            i = 0;
            while (check[i] != ' ')
            {
                first_field[i] = check[i];
                i++;
            }
            first_field[i] = '\0';

            if (strcmp((char*)str, (char*)first_field) == 0)
            {
                puts(first_field);
                return 1;
            }
        }
    }
    if (j == 18)
        return 0;
}

int main()
{
    char temp[30], wc[10], str[4][10];
    int i = 0, j = 0, k = 0, z;
    FILE *fp;

    int LC = 0, RC = 0, STP = 1;

    fp = fopen("ip.txt", "r");

    while (1)
    {   //1-break a line and store in array of strings(str)
        if (fgets(temp, 30, fp) == NULL)
            break;
        else
        {
            j = 0; i = 0;
            while (j < 3)
            {
                k = 0;
                for (z = 0; z < 10; z++)
                    wc[z] = 0;
                while (temp[i] != ' ' && temp[i] != ',')
                {
                        wc[k] = temp[i];
                        i++;
                        k++;
                }
                i++;
                wc[k] = '\0';
                strcpy(str[j], wc);
                j++;
            }
        }

        //str[0][3] = '\0';
        if (in_mot(str[0]))
        {
            //printf("\n yesssssssss");
        }
    }

    return 0;    
}

str and first_field are my two strings. By puts(), when both the strings are equal they print same output but strcmp() returns non zero value? Aren't str and first_field being considered as strings? When I tried to print their lengths by strlen, it didn't show any output.

12
  • 5
    Then they only look identical. Commented Feb 21, 2017 at 6:24
  • 3
    Try printing their strlen, it will likely be different due to non-printable characters Commented Feb 21, 2017 at 6:24
  • 3
    @ash Please, provide a complete test program with/and your test data. Otherwise, your observation is not reproducable. Commented Feb 21, 2017 at 6:25
  • 1
    @ash Just a guess: strcmp() was intended to be used with ASCII. If applied to UTF-8, it will work for identical encoded strings. However, in Unicode/UTF-8 are in certain cases multiple way to express the same glyph e.g. 'ü' can be code point 252 or a 'u' and a diaresis (the upper double points). In this case, it looks equal but strcmp()will consider this as different. Commented Feb 21, 2017 at 6:33
  • 1
    @ash end yet you cast to char*, which is pointless since arrays decay to pointers without any cast. It's just not idiomatic to stick a cast there. Commented Feb 21, 2017 at 6:39

3 Answers 3

2

Try to print each character code, not the characters only visible(printable). Then you would find out what is different between two strings.

Like,

char* p = str;
while (*p)
{
    printf("%02x ", p++);
}
Sign up to request clarification or add additional context in comments.

Comments

1

Perhaps, strings are different in some non-printable characters, e.g. \n or \r or (space) that you cannot see at the screen.

E.g.:

char first_field[] = "Test\r";
char str[] = "Test\n";
puts(first_field);
puts(str);
if ( !strcmp(str, first_field) )
{
    puts(first_field);
    return 1;
}

will give the same output but strings are really different.

UPDATE:

Possible ways to check:

// check pointers
if (str != NULL && first_field != NULL)
{
    // check length
    if (strlen(str) == strlen(first_field))
    {
        // check content
        if (!strcmp(str, first_field))
        {
            //do something for equal strings
            return 1;
        }
    }
}

As an option, you can write your own comparison, that skips some characters when compare strings, or delete all non-printable characters at the end of strings before using strcmp, e.g.:

void removeEmptyEnd(char * str)
// removes insignificant endings (including space with code 32)
{
    if (!str)
    {
        return;
    }
    // Start from the end
    int i = strlen(str);
    // and skip space and other non-printable chars
    while (i >= 0 && str[i] <= 32)
    {
        i--; // move to next char
    }
    // put new null-termitator to the end of string
    str[i+1] = '\0';
}

UPDATE 2:

Also check file-pointers after opening:

fp=fopen("ip.txt","r");
if( fp )
{
     // use file - read data
}

4 Comments

any way to check this?
@ash As StoryTeller wrote: you could check the length additionally. strlen() will count \r and \nas well as any character != 0.
yes they are showing different length due to escape characters maybe,but they contain same characters(as in alphabets) .How do i find out the extra escape sequence character?
@ash I have added my solution - you can call removeEmptyEnd(first_field) to ensure that here is no ' ', '\n' and other in the end of string
0

Your parser does not verify the lengths of the destination arrays. If ip.txt contains words (separated by a single space or comma) longer than 9 characters or if the first word on any line in file mot.txt is longer than 6 characters, you would have a buffer overflow, causing undefined behavior.

You also have undefined behavior if the lines in ip.txt do not contain at least 3 separators and if the lines in mot.txt do not all contain a space.

Here is a version that checks and reports buffer overflows:

#include <stdio.h>
#include <string.h>

int copy_word(char *dest, int size, const char *src, int len,
              const char *filename, int lineno) {
    *dest = '\0';
    if (len >= size) {
        fprintf(stderr, "%s:%d: word longer than %d characters: %.*s\n",
                filename, lineno, size - 1, len, src);
        return -1;
    }
    strncat(dest, src, len);
    return len;
}

int in_mot(const char *str) { //check whether input from text file in mot table
    FILE *fp_mot;
    char check[300], first_field[7];
    int i, lineno = 0;

    fp_mot = fopen("mot.txt", "r");
    if (fp_mot == NULL) {
        perror("cannot open file mot.txt");
        return 0;
    }

    while (fgets(check, sizeof(check), fp_mot)) {
        lineno++;
        i = strcspn(check, " \n");
        copy_word(first_field, sizeof first_field, check, i, "mot.txt", lineno);
        if (strcmp(str, first_field) == 0) {
            puts(first_field);
            return 1;
        }
    }
    return 0;
}

int main(void) {
    char temp[30], wc[10], str[4][10];
    int i, j, k;
    int lineno = 0;
    FILE *fp;

    //int LC = 0, RC = 0, STP = 1;

    fp = fopen("ip.txt", "r");
    if (fp == NULL) {
        perror("cannot open file ip.txt");
        return 1;
    }

    while (fgets(temp, sizeof(temp), fp)) {
        lineno++;
        for (j = i = 0; j < 3; j++) {
            k = strcspn(temp + i, " ,\n");
            copy_word(wc, sizeof(wc), temp + i, k, "ip.txt", lineno);
            strcpy(str[j], wc);
            i += k;
            if (temp[i] != '\0')
                i++;
        }
        if (in_mot(str[0])) {
            printf("yes!\n");
        }
    }
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.