1

コードの長いセクションで申し訳ありませんが、私は困惑しており、手を必要としています!

私の具体的な問題は、「del」イベントを呼び出すために解析メソッドを使用すると、奇妙な文字の置換が行で行われ、私が知る限り、触れられていないことです。これは、関数「del」を直接呼び出した場合には発生しません。文字列をトークン化する別の方法を実装しようとして、このコードを調べても無駄でした。あなたはそれに名前を付けます。問題がどこにあるのかわからないため、すべてのコードを含めました。これは、関数「parse」内にないと考え始めているためです。

私はぶらぶらして、要求された限り多くの情報を提供します.今のところ、他に何を追加すればよいかわかりません.

PSコンパイラは、strsepの由来であるgnu Windowsライブラリとリンクしています。

Windows用LibGW32C

PPSコンパイラの警告のみが、char * bufを使用していないことについて泣き言を言っています

db.h

#define MAX_ITEMS 80

typedef struct item {
    long id;
    char* name;
    char* desc;
    float price;
} item_t;

extern char *strsep (char **restrict stringp, const char *restrict delim);

int isLong (char* str);

int isFloat (char* str);

void add (item_t* item, long id, char* name, char* desc, float price);

void del (item_t* item, long id);

void modify (item_t* item, long id, char* name, char* desc, float price);

void disp (item_t* item, long id);

void itemCopy (item_t* from, item_t* to);

void parse (item_t* item, char* buf);

int findLastElement (item_t* item);

db.c

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "db.h"

int isLong (char* str) {
    if (str == NULL) {
        return 0;
    }
    char* pEnd;
    strtol (str, &pEnd, 10);
    if (isalpha (*pEnd) || *pEnd == ' ') {
        return 0;
    } else {
        return 1;
    }
}

int isFloat (char* str) {
    if (str == NULL) {
        return 0;
    }
    char* pEnd;
    strtod (str, &pEnd);
    if (isalpha (*pEnd) || *pEnd == ' ') {
        return 0;
    } else {
        return 1;
    }
}


void add (item_t *item, long id, char* name, char* desc, float price) {
    int i = 0;
    while (1) {
        if (item[i].id == id) {
            printf ("Item \"%s\" with ID %lu already exists.\n", item[i].name, id);
            break;
        } else if (item[i].id == 0) {
            item[i].id = id;
            item[i].name = name;
            item[i].desc = desc;
            item[i].price = price;
            break;
        } else {
            i++;
        }
    }
}

void del (item_t* item, long id) {
    int i = 0;
    int end = findLastElement (item);
    while (1) {
        if (item[i].id == id) {
            item[i].id = 0;
            item[i].name = "";
            item[i].desc = "";
            item[i].price = 0;
            while (i < end) {
                itemCopy (&item [i + 1], &item [i]);
                i++;
            }
            break;
        } else {
            if (i == MAX_ITEMS) {
                printf ("Item with ID %lu does not exist.\n", id);
                break;
            }
            i++;
        }
    }
}

void modify (item_t *item, long id, char* name, char* desc, float price) {
    int i = 0;
    while (1) {
        if (item[i].id == id) {
            item[i].name = name;
            item[i].desc = desc;
            item[i].price = price;
            break;
        } else {
            if (i == MAX_ITEMS) {
                printf ("Item with ID %lu does not exist.\n", id);
                break;
            }
            i++;
        }
    }
}

void disp (item_t* item, long id) {
    int end = findLastElement (item);
    printf ("\nID\tNAME\tDESCRIPTION\tPRICE\n--\t----\t-----------\t-----\n");
    if (id == -1) {
        for (int i = 0; i < end; i++) {
            printf ("%lu\t%s\t%s\t$%2.2f\n", item[i].id, item[i].name, item[i].desc, item[i].price);
        }
    } else {
        for (int i = 0; i < end; i++) {
            if (item[i].id == id) {
                printf ("%lu\t%s\t%s\t$%2.2f\n", item[i].id, item[i].name, item[i].desc, item[i].price);
                break;
            }
        }
    }
}

void itemCopy (item_t* from, item_t* to) {
    to -> id = from -> id;
    to -> name = from -> name;
    to -> desc = from -> desc;
    to -> price = from -> price;
}

void parse (item_t* item, char* str) {
    char **ap, *argv[10], *inputstr = malloc (sizeof(str)), *ptr;
    strcpy (inputstr, str);
    memset (argv, 0, sizeof (argv));
    for (ap = argv; (*ap = strsep (&inputstr, ",\n")) != NULL;) {
        if (**ap != '\0') {
            if (++ap >= &argv[10]) {
                break;
            }
        }
    }

    if (strcmp (argv[0], "add\0") == 0) {
        if (!isLong (argv[1]) || argv[1] == NULL) {
            printf ("\nInvalid/Missing ID\n");
            return;
        } else if (argv[2] == NULL) {
            printf ("\nInvalid/Missing Product Name.\n");
            return;
        } else if (argv[3] == NULL) {
            printf ("\nInvalid/Missing Product Description.\n");
            return;
        } else if (!isFloat (argv[4]) || argv[4] == NULL) {
            printf ("\nInvalid/Missing Price\n");
            return;
        } else {
            add (item, strtol (argv[1], &ptr, 10), argv[2], argv[3], strtod (argv[4], &ptr));
        }
    } else if (strcmp (argv[0], "del\0") == 0) {
        if (!isLong (argv[1]) || argv[1] == NULL) {
            printf ("\nInvalid/Missing ID\n");
            return;
        } else {
            del (item, strtol (argv[1], &ptr, 10));
        }
    }
} 

int findLastElement (item_t* item) {
    for (int i = 0; i < MAX_ITEMS; i++) {
        if (item[i].id == 0) return i;
    }
    return -1;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "db.h"


int main (int argc, char* argv[]) {
    item_t item [MAX_ITEMS];
    memset (item, 0, sizeof (item));
    char* buf = malloc (255);
    int exit = 0;

    while (!exit) {
        printf ("Adding 3 test items.\n");
        add (item, 1234, "Pizza", "Tasty Pizza", 9.99F);
        add (item, 5678, "Pasta", "Tasty Pasta", 19.99F);
        add (item, 9012, "Ribs", "Tasty Ribs", 29.99F);
        disp (item, -1);
        printf ("\nDeleting Item with ID 5678.\n");
        del (item, 5678);
        disp (item, -1);
        printf ("\nModifying item with ID 1234.\n");
        modify (item, 1234, "Soup", "Tasty Soup", 4.99F);
        disp (item, -1);
        printf ("\nAdding another item with id 5678.");
        add (item, 5678, "Pasta", "Tasty Pasta", 19.99F);
        printf ("\nAdding item \"Pizza\" with the same ID as \"Soup\".\n");
        add (item, 1234, "Pizza", "Tasty Pizza", 9.99F);
        disp (item, -1);
        printf ("\nDeleting item \"Soup\" and re-adding \"Pizza\".\n");
        del (item, 1234);
        add (item, 1234, "Pizza", "Tasty Pizza", 9.99F);
        disp (item, -1);
        printf ("\nDisplaying only the item with id 5678.\n");
        disp (item, 5678);
        printf ("\nAdding item \"Wings\" using the parsing function.\n");
        parse (item, "add,9898,Wings,Tasty Wings,14.99\n");
        disp (item, -1);
        printf ("\nAttempting to Delete non-existent item with ID 9999.\n");
        //del (item, 9999);
        parse (item, "del,9999\n"); <--- This is the problem line
        printf ("\nAttempting to Modify non-existent item with ID 9999.\n");
        modify (item, 9999, "Test", "Test", 0.0F);
        disp (item, -1);
        exit = 1;
    }
}

そして最後に、私の出力:

Adding 3 test items.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
1234    Pizza   Tasty Pizza     $9.99
5678    Pasta   Tasty Pasta     $19.99
9012    Ribs    Tasty Ribs      $29.99

Deleting Item with ID 5678.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
1234    Pizza   Tasty Pizza     $9.99
9012    Ribs    Tasty Ribs      $29.99

Modifying item with ID 1234.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
1234    Soup    Tasty Soup      $4.99
9012    Ribs    Tasty Ribs      $29.99

Adding another item with id 5678.
Adding item "Pizza" with the same ID as "Soup".
Item "Soup" with ID 1234 already exists.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
1234    Soup    Tasty Soup      $4.99
9012    Ribs    Tasty Ribs      $29.99
5678    Pasta   Tasty Pasta     $19.99

Deleting item "Soup" and re-adding "Pizza".

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
9012    Ribs    Tasty Ribs      $29.99
5678    Pasta   Tasty Pasta     $19.99
1234    Pizza   Tasty Pizza     $9.99

Displaying only the item with id 5678.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
5678    Pasta   Tasty Pasta     $19.99

Adding item "Wings" using the parsing function.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
9012    Ribs    Tasty Ribs      $29.99
5678    Pasta   Tasty Pasta     $19.99
1234    Pizza   Tasty Pizza     $9.99
9898    Wings   Tasty Wings     $14.99

Attempting to Delete non-existent item with ID 9999.
Item with ID 9999 does not exist.

Attempting to Modify non-existent item with ID 9999.
Item with ID 9999 does not exist.

ID      NAME    DESCRIPTION     PRICE
--      ----    -----------     -----
9012    Ribs    Tasty Ribs      $29.99
5678    Pasta   Tasty Pasta     $19.99
1234    Pizza   Tasty Pizza     $9.99
9898    Win♦    Çdel    $14.99 <--- THIS IS WHAT'S DOING MY HEAD IN

事前にご協力いただきありがとうございます。

これが些細な愚かな初心者のエラーに終わらないことを本当に願っています。

4

1 に答える 1

4

実際に a (つまり、文字列定数)char* を指定しているので、2 番目の引数としてparse を使用することについてコンパイラが文句を言うだろうと私は考えていました。const char*ただし、実際には文字列をコピーしようとするので、prototype を作成した可能性があります (作成する必要があります) const char*

「コピーしてみる」ことに注目しましょう。難読化された初期化は別として、次のことを行います。

 inputstr = malloc (sizeof(str));
 strcpy(inputstr, str);

先に進む前に、 をご覧になることをお勧めしますstrdup.

 inputstr = strdup(str);

大騒ぎもエラーもありません。とにかく、

strですchar*。つまり、文字へのポインタです。(それは であるべきconst char*でしたが、それでも文字へのポインターです。)sizeof(str)ポインターのサイズも同様です。プラットフォームでは 4 バイトになる可能性がありますが、8 バイトになることもあります。いずれにせよ、文字列を保持するのに十分な長さではない"add,9898,Wings,Tasty Wings,14.99\n"ため、それを にコピーするとinputstr、ランダムなメモリが上書きされます。(そしておそらく再びdel文字列で)。

sizeof(*str)1バイトである文字のサイズになります。あなたが意味していたstrlen(str)のは、バイト単位の文字列の長さでしたstrが、終端の NUL バイトが除外されているため、それも正しくありません。

要するに、あなたが望んでいたのstrdupは上記の呼び出しでした。これは次と同等です。

char* inputstr = malloc(strlen(str) + 1);
strcpy(inputstr, str);
于 2013-09-19T05:05:47.200 に答える