奇怪的角色替换在哪里没有意义(对我而言)

时间:2013-09-19 04:52:52

标签: c string parsing strsep

很抱歉代码很长,但我很难过,需要一只手!

我的具体问题是,当我使用我的parse方法来调用“del”事件时,我会在一条线上进行奇怪的字符替换,据我所知,这条线没有被触及。当我直接调用函数“del”时,这不会发生。我花了很长时间仔细研究这段代码无济于事,试图实现一种不同的字符串标记方式;你说出来的。我包含了所有代码,因为我不知道问题出在哪里,因为我开始认为它不属于“解析”功能。

我会随意提供所需的信息,现在我不知道还有什么要补充。

P.S。编译器链接到gnu windows库,这就是strsep的来源。

LibGW32C for Windows

P.P.S。只有编译器警告是抱怨我没有使用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

提前感谢您的帮助!

我真的希望这不会成为一些愚蠢的新手错误。

1 个答案:

答案 0 :(得分:4)

我原以为编译器会抱怨解析时将char*作为其第二个参数,因为你实际上提供了一个const char*(即一个字符串常量)。但是,您实际上是尝试复制字符串,因此您可以(并且应该)创建原型const char*

让我们专注于“尝试复制”。抛开模糊的初始化,你要做的是:

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

在我继续前进之前,我建议你看看strdup,它正是你想要的,只是正确的:

 inputstr = strdup(str);

没有大惊小怪,没有错误。但无论如何,

strchar*;也就是说,指向一个字符的指针。 (它应该是const char*,但它仍然是指向一个字符的指针。)所以sizeof(str)是指针的大小,在你的平台上可能是四个字节,尽管它可能是八点无论哪种方式,它都不足以保持字符串"add,9898,Wings,Tasty Wings,14.99\n",所以当你将其复制到inputstr时,你最终会覆盖随机内存。 (可能再次使用del字符串)。

sizeof(*str)将是一个字符的大小,即一个字节。我认为你可能意味着strlen(str),这是字符串str的长度,以字节为单位,但这也不正确,因为它省略了终止的NUL字节。

简而言之,您想要的是上面的strdup调用,相当于:

char* inputstr = malloc(strlen(str) + 1);
strcpy(inputstr, str);