读取文本文件并用分隔符分隔
Reading text file and breaking it by delimiters
我正在尝试读取具有以下结构的文本文件:
Item 1 - 50, Item 2 - 400, Item 3 - 120, Item 4 - 15;
在遍历文件时,我想将价格和商品名称存储在两个字符串中。
为了更清楚,我有 int credit
,我想将其与价格进行比较,如果信用更大,我将打印价格。
我用这个功能打印了所有的产品:
int credit = 1000; //For the example purpose
int displayProducts(){
int row=0;
char line[MAX_LINE_SIZE + 1]; // ptr to the current input line
FILE *fp;
fp = fopen("machinedata.txt", "r");
if (fp == NULL)
{
printf("Error while opening the file.\n");
// exit(EXIT_FAILURE);
}
while (fgets(line, MAX_LINE_SIZE, fp)) {
char *next_item; // ptr to the next item extracted from the current line
char* name = NULL;
int price;
next_item = strtok(line, " ,");
while (next_item != NULL){
printf("%s\n", next_item);
next_item = strtok(NULL, " ,");
/*WHAT CAN I DO HERE TO EXTRACT EACH PRICE AND COMPARE WITH CREDIT??*/
}
}
fclose(fp);
return 1;
}
我正在迈出 C 语言的第一步,但我不知道该怎么做。
有什么帮助吗?
在阅读一行之后,您需要将其拆分为项目条目。由于您使用的是 strtok()
,我假设您不需要识别分隔符。此外,不喜欢 strtok()
and preferring Microsoft's strtok_s()
on Windows and POSIX strtok_r()
的原因之一是您不能对 strtok()
进行嵌套调用,但您需要它们。或者您需要使用 scanf()
或其他一些技术。
警告:none此代码已接近编译器!
char *next_ptr = NULL;
char *next_item = strtok_r(line, ",;", &next_ptr);
while (next_item != NULL){
char *item_ptr = NULL;
char *name = strtok_r(next_item, "-", &item_ptr);
if (name == NULL)
{
fprintf(stderr, "Failed to scan name out of [%s]\n", next_item);
break;
}
int price;
next_item = strtok_r(NULL, " ,", &item_ptr);
assert(next_item != NULL);
if (sscanf(next_item, "%d", &price) != 1)
fprintf(stderr, "Failed to convert [%s] to integer\n", next_item);
else
printf("Item: [%s] price %d\n", name, price);
next_item = strtok_r(NULL, ",;", &next_ptr);
}
错误的break
是因为我懒惰。理想情况下,您应该继续该行中的下一项,但这涉及将循环重写为 for
循环:
for (next_item = strtok_r(line, ",;", &next_ptr);
next_item != NULL;
next_item = strtok_r(NULL, ",;", &next_ptr))
{
...body of loop except for final call to strtok_r()...
}
现在可以使用continue
,next_item = strtok_r(NULL, ",;", &next_ptr)
语句就会被执行,这很关键。您可能需要担心分号后的空项;将 && *next_item != '[=23=]'
添加到循环条件。
如果你因为某些原因(什么?)不能使用strtok_r()
或strtok_s()
,那么你可以考虑使用:
char name[30];
int price;
if (sscanf(next_item, "%29[^-] - %d", name, &price) != 2)
{
fprintf(stderr, "Failed to extract item name and price from [%s]\n", next_item);
continue; // Or break!
}
还有其他选择——事实上有很多。
请注意 strtok()
及其亲戚都 (a) 破坏输入字符串 (b) 不告诉您哪个字符标记结束,并且 (c) 将多个分隔符视为一个,因此您可以不要在两个分隔符之间发现空项(在本例中这不是问题)。破坏是通过在找到分隔符的地方插入空字节,将原始字符串切成更短的子字符串。
请注意,如果项目名称包含破折号,则表示您已使用此系统。您会将 'Vacuum-24' 解释为名为 'Vacuum' 且价格为 24 的商品。你也可以解决这个问题,但它更难(例如 strstr()
找到 " - "
(空白、破折号、空白)作为项目名称和价格之间的分隔符)。
我正在尝试读取具有以下结构的文本文件:
Item 1 - 50, Item 2 - 400, Item 3 - 120, Item 4 - 15;
在遍历文件时,我想将价格和商品名称存储在两个字符串中。
为了更清楚,我有 int credit
,我想将其与价格进行比较,如果信用更大,我将打印价格。
我用这个功能打印了所有的产品:
int credit = 1000; //For the example purpose
int displayProducts(){
int row=0;
char line[MAX_LINE_SIZE + 1]; // ptr to the current input line
FILE *fp;
fp = fopen("machinedata.txt", "r");
if (fp == NULL)
{
printf("Error while opening the file.\n");
// exit(EXIT_FAILURE);
}
while (fgets(line, MAX_LINE_SIZE, fp)) {
char *next_item; // ptr to the next item extracted from the current line
char* name = NULL;
int price;
next_item = strtok(line, " ,");
while (next_item != NULL){
printf("%s\n", next_item);
next_item = strtok(NULL, " ,");
/*WHAT CAN I DO HERE TO EXTRACT EACH PRICE AND COMPARE WITH CREDIT??*/
}
}
fclose(fp);
return 1;
}
我正在迈出 C 语言的第一步,但我不知道该怎么做。 有什么帮助吗?
在阅读一行之后,您需要将其拆分为项目条目。由于您使用的是 strtok()
,我假设您不需要识别分隔符。此外,不喜欢 strtok()
and preferring Microsoft's strtok_s()
on Windows and POSIX strtok_r()
的原因之一是您不能对 strtok()
进行嵌套调用,但您需要它们。或者您需要使用 scanf()
或其他一些技术。
警告:none此代码已接近编译器!
char *next_ptr = NULL;
char *next_item = strtok_r(line, ",;", &next_ptr);
while (next_item != NULL){
char *item_ptr = NULL;
char *name = strtok_r(next_item, "-", &item_ptr);
if (name == NULL)
{
fprintf(stderr, "Failed to scan name out of [%s]\n", next_item);
break;
}
int price;
next_item = strtok_r(NULL, " ,", &item_ptr);
assert(next_item != NULL);
if (sscanf(next_item, "%d", &price) != 1)
fprintf(stderr, "Failed to convert [%s] to integer\n", next_item);
else
printf("Item: [%s] price %d\n", name, price);
next_item = strtok_r(NULL, ",;", &next_ptr);
}
错误的break
是因为我懒惰。理想情况下,您应该继续该行中的下一项,但这涉及将循环重写为 for
循环:
for (next_item = strtok_r(line, ",;", &next_ptr);
next_item != NULL;
next_item = strtok_r(NULL, ",;", &next_ptr))
{
...body of loop except for final call to strtok_r()...
}
现在可以使用continue
,next_item = strtok_r(NULL, ",;", &next_ptr)
语句就会被执行,这很关键。您可能需要担心分号后的空项;将 && *next_item != '[=23=]'
添加到循环条件。
如果你因为某些原因(什么?)不能使用strtok_r()
或strtok_s()
,那么你可以考虑使用:
char name[30];
int price;
if (sscanf(next_item, "%29[^-] - %d", name, &price) != 2)
{
fprintf(stderr, "Failed to extract item name and price from [%s]\n", next_item);
continue; // Or break!
}
还有其他选择——事实上有很多。
请注意 strtok()
及其亲戚都 (a) 破坏输入字符串 (b) 不告诉您哪个字符标记结束,并且 (c) 将多个分隔符视为一个,因此您可以不要在两个分隔符之间发现空项(在本例中这不是问题)。破坏是通过在找到分隔符的地方插入空字节,将原始字符串切成更短的子字符串。
请注意,如果项目名称包含破折号,则表示您已使用此系统。您会将 'Vacuum-24' 解释为名为 'Vacuum' 且价格为 24 的商品。你也可以解决这个问题,但它更难(例如 strstr()
找到 " - "
(空白、破折号、空白)作为项目名称和价格之间的分隔符)。