很抱歉代码很长,但我很难过,需要一只手!
我的具体问题是,当我使用我的parse方法来调用“del”事件时,我会在一条线上进行奇怪的字符替换,据我所知,这条线没有被触及。当我直接调用函数“del”时,这不会发生。我花了很长时间仔细研究这段代码无济于事,试图实现一种不同的字符串标记方式;你说出来的。我包含了所有代码,因为我不知道问题出在哪里,因为我开始认为它不属于“解析”功能。
我会随意提供所需的信息,现在我不知道还有什么要补充。
P.S。编译器链接到gnu windows库,这就是strsep的来源。
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
提前感谢您的帮助!
我真的希望这不会成为一些愚蠢的新手错误。
答案 0 :(得分:4)
我原以为编译器会抱怨解析时将char*
作为其第二个参数,因为你实际上提供了一个const char*
(即一个字符串常量)。但是,您实际上是尝试复制字符串,因此您可以(并且应该)创建原型const char*
。
让我们专注于“尝试复制”。抛开模糊的初始化,你要做的是:
inputstr = malloc (sizeof(str));
strcpy(inputstr, str);
在我继续前进之前,我建议你看看strdup
,它正是你想要的,只是正确的:
inputstr = strdup(str);
没有大惊小怪,没有错误。但无论如何,
str
是char*
;也就是说,指向一个字符的指针。 (它应该是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);