1

このデータベースがあり、製品名が既にデータベースにあるかどうかを確認する必要があります。それ以外の場合は、ユーザーに別の名前を入力するように依頼します。

問題はこれです:

構造体内にある文字列 (製品名) とユーザーが入力した文字列を比較しようとしています。

構造体のコーディング、ユーザー入力部分、および検索方法は次のとおりです。

製品構造

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

checkProduct メソッド:

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;
}

およびユーザー入力部分 [コードの一部]:

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;

現在、次のエラーが発生しています(ECLIPSEを使用しています):

(checkProduct == 1) [ユーザー入力で見つかりました] が私に与えている行で、「ポインターと整数の比較 - デフォルトで有効になっています」という黄色の警告三角形でマークされています

p.pName = nameCheck; 赤い十字としてマークされ、コンパイルを停止して、「タイプ 'char *' からタイプ 'char [100] に割り当てるときに互換性のないタイプです ^---- ユーザー入力と文字列を比較しているときの両方で問題が発生しています.

どうすれば修正できるか、またはどうすればそれを延期できるかについての提案はありますか? 構造体では char pName が「*」としてマークされているのに、char[100] ではマークされていない理由がわかりません。

簡単な説明をお願いします。

前もって感謝します

編集: 以下のいくつかでコードを修正した後: これは INPUT NAME OF PRODUCT セクションです。

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);

これは新しい checkName メソッドです

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;
}
4

2 に答える 2

3
p.pName = nameCheck; 

ある配列のアドレスを別の配列に割り当てようとすると、が間違っています。おそらくあなたが望むのはそれをコピーすることです。

strcpy()代わりに使用してください。

strcpy(p.pName, nameCheck);

while (checkProduct == 1)

checkProductは関数であるため、関数のアドレスは1に等しくないため、上記の条件は常にfalseになります。戻り値は次のように別の整数に格納できます。

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

またはむしろ単純に:

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

注-コード全体をチェックしていません。これ以外にもバグがある可能性があります。ところで、プログラミングに不慣れな場合は、教科書の小さな例から始めて、少し複雑なものに取り組むことができます。

于 2012-12-21T19:04:56.143 に答える
0
int checkProduct (char nameCheck[100])

型シグネチャは嘘であることに注意してください。署名は

int checkProduct(char *nameCheck)

関数が期待して受け取る引数は へのポインターであるため、または、引数が 0 で終わる配列charの最初の要素へのポインターであるべきであることをユーザーに文書化するchar

int checkProduct(char nameCheck[])

配列は、関数の引数として関数に引数として渡されることはなく、ほとんどの場合 [例外は、配列が のオペランドまたはアドレス演算子sizeofである場合]、最初の要素へのポインターに変換されます。_Alignof&

    {
        product temp;
        p.pName = nameCheck;

配列は代入できません。a の左側に配列名を指定できるのは=、配列が宣言された時点での初期化のみです。

あなたはおそらくしたいです

strcpy(p.pName, nameCheck);

そこの。

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

strcmp最初の引数が 2 番目の引数よりも辞書的に小さい場合は負の値を返し、両方の引数が等しい場合は 0 を返し、最初の引数が 2 番目の引数より辞書的に大きい場合は正の値を返します。

あなたはおそらくしたいです

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

そこの。

    gets (nameCheck);

絶対に使用しないでくださいgets。これは非常に安全ではありません (そして、最後の標準で言語から削除されました)。使用する

fgets(nameCheck, sizeof nameCheck, stdin);

ただし、十分なスペースがある場合は改行をバッファーに格納するため、存在する場合はそれを上書きする必要があります0

POSIX システムを使用していて、移植性を気にする必要がない場合は、 を使用getline()して末尾の改行を保存せずに行を読み込むことができます。

    checkProduct (nameCheck);

製品が既知であるかどうかを確認しますが、結果は破棄します。変数に格納します。

    while (checkProduct == 1)

checkProduct関数です。ほとんどの場合、関数指定子はポインターに変換されるため、ポインターと整数の比較に関する警告が表示されます。上記で保存する必要がある呼び出しの値と比較するつもりでした。

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

文字を保存せずに読み取ります。したがって、 の内容を変更することはなくnameCheck、無限ループに陥ることはありません。

        {
            continue;
        }

ループ本体の唯一のステートメントが である場合はcontinue;、本体を空のままにしておく必要があります。

    }
    p.pName = nameCheck;

繰り返しますが、配列に代入することはできません。


編集に関しては、

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

nameCheck配列からポインターに変更されました。つまり、 は配列に格納できる ssizeof nameCheckの数ではなく、 へのポインターのサイズを示します。これは、それが指すものとは無関係です (通常、32 ビット システムでは 4 で、64 ビット システムでは 8 です)。 )。charchar

そして、そのポインターが文字列リテラルを指すようにします""。これがクラッシュの原因です。現在、文字列リテラルは通常、メモリの読み取り専用セグメントに格納されているため、文字列リテラルを変更しようとすると未定義の動作となり、多くの場合クラッシュにつながります。

あなたはそれを残すべきだった

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

を使用して、読み取ることができる文字数sizeof nameCheckを伝えるfgetsことができます。または、ポインターとmallocメモリを使用することもできます。

#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);

いずれにせよ、入力を取得した後、改行がある場合は削除します。

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;
}
于 2012-12-21T19:24:00.937 に答える