1

I have this database and I Need to check whether a Product Name is already in the database otherwise I ask the user to input another one.

The problem is this:

I'm trying to compare a string (the Product Name) found inside the struct with the string the user inputs.

The coding of the struct, the user input part and the search method are here below:

product Structure

typedef struct
{
    char    pName[100];
    char    pDescription [100];
    float   pPrice;
    int     pStock;
    int     pOrder;
}product;

the checkProduct method:

int checkProduct (char nameCheck[100])
{
    product temp;
    p.pName = nameCheck;

    rewind (pfp);
    while (fread(&temp,STRUCTSIZE,1,pfp)==1)
    {
        if (strcmp (temp.pName,p.pName))
        {
            return 1;
        }
    }
    return 0;
}

and the user input part [part of the code]:

char nameCheck[100];
gets (nameCheck);
checkProduct (nameCheck);
while (checkProduct == 1)
{
    printf ("Product Already Exists!\n Enter another!\n");
    while (getchar() !='\n')
    {
        continue;
    }
}
p.pName = nameCheck;

Now I am having the following errors (I Use ECLIPSE):

on the line while (checkProduct == 1) [found in the user input] is giving me: "comparison between pointer and integer - enabled by default" marked by a yellow warning triangle

p.pName = nameCheck; is marked as a red cross and stopping my compiling saying: "incompatible types when assigning to type 'char [100] from type 'char*' ^---- Is giving me trouble BOTH in the userinput AND when I'm comparing strings.

Any suggestions how I can fix it or maybe how I can deference it? I can't understand why in the struct the char pName is being marked as '*' whereas in the char[100] it's not.

Any brief explanation please?

Thank you in advance

EDIT: After emending the code with some of below: THIS Is the INPUT NAME OF PRODUCT section;

char *nameCheck;
        nameCheck = "";
        fgets(nameCheck,sizeof nameCheck, stdin);

        checkProduct (nameCheck);

        int value = checkProduct (nameCheck);
        while (value == 1)
        {
            printf ("Product Already Exists!\n Enter another!\n");
            while (getchar() !='\n')
            {

            }
        }
        strcpy (p.pName, nameCheck);

this is the new checkName method

int checkProduct (char *nameCheck)
{
    product temp;
    strcpy (p.pName, nameCheck);

    rewind (pfp);
    while (fread(&temp,STRUCTSIZE,1,pfp)==1)
    {
        if (strcmp (temp.pName,p.pName) == 0)
        {
            return 1;
        }
    }
    return 0;
}
5
  • p.pName = nameCheck; you can't assign to an array. Commented Dec 21, 2012 at 19:00
  • And once you've fixed that, read up on what strcmp() actually returns for a match. Commented Dec 21, 2012 at 19:04
  • Maybe you should read a C book. :) Commented Dec 21, 2012 at 19:09
  • I know that strcmp() returns 0 for a match, but the problem is that I do not know how I'm going to assign that p.pName. what I want to know is how I can pass the characters into the method and then compare them Commented Dec 21, 2012 at 19:10
  • This is an assignment for university I'm afraid, and although I've read the C Book, it's not sufficient to help me in everything Commented Dec 21, 2012 at 19:18

2 Answers 2

3
p.pName = nameCheck; 

is wrong as you try to assign address of one array to another. What you probably want is to copy it.

Use strcpy() instead.

strcpy(p.pName, nameCheck);

while (checkProduct == 1)

Since checkProduct is a function, the above condition will always be false as the address of function won't be equal to 1. You can store the return value in another integer like this:

int value = checkProduct(nameCheck);
while (value == 1)
/* rest of the code */

Or rather simply:

while ( checkProduct(nameCheck) == 1 ) {
...

Note - I've not checked entire code, there might be other bugs apart from this one. Btw, if you are new to programming, you can start with small examples from textbooks and then work towards slightly complex stuff.

Sign up to request clarification or add additional context in comments.

4 Comments

the problem is how to pass the characters from the userinput (nameCheck) into that method. Then from then I'm creating a temporary struct and I want to assign the name from the Userinput INTO that temporary but how I don't know
@user1919739 You can use strcpy() or similar functions. See the edit now.
Yes i saw it, but still says the problem about how to declare the 'char' because the struct is considered as char (although in the struct it is declared as an array of characters) and when I'm creating the new char[100], it's not letting me strcpy the char with the char[]
user1919739 - I think's high time to you go back and start reading the basics of C programming.
0
int checkProduct (char nameCheck[100])

Note that the type signature is a lie. The signature should be

int checkProduct(char *nameCheck)

since the argument the function expects and receives is a pointer to a char, or, to document it for the user that the argument should be a pointer to the first element of a 0-terminated char array

int checkProduct(char nameCheck[])

Arrays are never passed as arguments to functions, as function arguments, and in most circumstances [the exceptions are when the array is the operand of sizeof, _Alignof or the address operator &] are converted to pointers to the first element.

    {
        product temp;
        p.pName = nameCheck;

Arrays are not assignable. The only time you can have an array name on the left of a = is initialisation at the point where the array is declared.

You probably want

strcpy(p.pName, nameCheck);

there.

        rewind (pfp);
        while (fread(&temp,STRUCTSIZE,1,pfp)==1)
        {
            if (strcmp (temp.pName,p.pName))

strcmp returns a negative value if the first argument is lexicographically smaller than the second, 0 if both arguments are equal, and a positive value if the first is lexicographically larger than the second.

You probably want

if (strcmp(temp.pName, p.pName) == 0)

there.

    gets (nameCheck);

Never use gets. It is extremely unsafe (and has been remoed from the language in the last standard, yay). Use

fgets(nameCheck, sizeof nameCheck, stdin);

but that stores the newline in the buffer if there is enough space, so you have to overwrite that with 0 if present.

If you are on a POSIX system and don't need to care about portability, you can use getline() to read in a line without storing the trailing newline.

    checkProduct (nameCheck);

You check whether the product is known, but throw away the result. Store it in a variable.

    while (checkProduct == 1)

checkProduct is a function. In almost all circumstances, a function designator is converted into a pointer, hence the warning about the comparison between a pointer and an integer. You meant to compare to the value of the call you should have stored above.

    {
        printf ("Product Already Exists!\n Enter another!\n");
        while (getchar() !='\n')

You read in characters without storing them. So you will never change the contents of nameCheck, and then be trapped in an infinite loop.

        {
            continue;
        }

If the only statement in a loop body is continue;, you should leave the body empty.

    }
    p.pName = nameCheck;

Once again, you can't assign to an array.


Concerning the edit,

char *nameCheck;
nameCheck = "";
fgets(nameCheck,sizeof nameCheck, stdin);

you have changed nameCheck from an array to a pointer. That means that sizeof nameCheck now doesn't give the number of chars you can store in the array, but the size of a pointer to char, which is independent of what it points to (usually 4 on 32-bit systems and 8 on 64-bit systems).

And you let that pointer point to a string literal "", which is the reason for the crash. Attempting to modify string literals is undefined behaviour, and more often than not leads to a crash, since string literals are usually stored in a read-only segment of the memory nowadays.

You should have left it at

char nameCheck[100];
fgets(nameCheck, sizeof nameCheck, stdin);

and then you can use sizeof nameCheck to tell fgets how many characters it may read, or, alternatively, you could have a pointer and malloc some memory,

#define NAME_LENGTH 100
char *nameCheck = malloc(NAME_LENGTH);
if (nameCheck == NULL) {
    // malloc failed, handle it if possible, or
    exit(EXIT_FAILURE);
}
fgets(nameCheck, NAME_LENGTH, stdin);

Either way, after getting input, remove the newline if there is one:

size_t len = strlen(nameCheck);
if (len > 0 && nameCheck[len-1] == '\n') {
    nameCheck[len-1] = 0;
}
// Does windows also add a '\r' when reading from stdin?
if (len > 1 && nameCheck[len-2] == '\r') {
    nameCheck[len-2] = 0;
}

8 Comments

Thank you very much! I have understood it. since you said about the POSIX system and so, Our lecturer wants us to use ONLY MinGW (C89/C90) so I pretty guess all these work? so gets is mostly discarded?
I don't know if MinGW implements the POSIX standard(s), actually. I half expect it, because it's sort of a Unix compatibility layer for Windows, but I'm not sure. So the portable and safe way is fgets. Concerning gets, let me quote the man page: "Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead."
oh ok thanks, I don't know but now when I'm trying to run the program and enter the input it's literally crashing my cmd...
With what code? And what does "crashing" mean here? Segmentation fault?
"CustomerOrders.exe has stopped worrking" I'm tyring to see which code but I think it's something with the inputs
|

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.