gpt4 book ai didi

c - 为什么我不能使用 C 中的 sscanf() 将值读入具有简单格式字符串的简单变量中?

转载 作者:行者123 更新时间:2023-11-30 18:28:22 25 4
gpt4 key购买 nike

我正在尝试解析一些简单格式的文本,并使用数字和短字符串值创建文本/数字记录的简单数据结构。我已经调试并定位到问题所在;这是由于 sscanf() 没有使用特定的格式字符串将值读入我的变量(程序中的其他格式字符串运行良好)。我创建了一个简单的文本文件来查看发生了什么。

代码如下:

char *idNumber = (char *)malloc(sizeof (char*));
char *partNumber = (char *)malloc(sizeof (char*));
int amountItems = 0;
double unitPrice = 0;

char *line1 = "Govan, Guthrie (N210) AX299 x 6 $149.94";
char *line2 = "Mustaine, Dave (N106) AX350N x 2 $63.98";
char *line3 = "Van Halen, Edward (N1402) AV2814 x 10 $34.90";


sscanf(line1, "%*s, %*s (%s) %s x %d $%lf", idNumber, partNumber,
&amountItems, &unitPrice);

printf("%s, %s, %d, %f\n", idNumber, partNumber, amountItems, unitPrice);


sscanf(line2, "%*s, %*s (%s) %s x %d $%lf", idNumber, partNumber,
&amountItems, &unitPrice);
printf("%s, %s, %d, %lf\n", idNumber, partNumber, amountItems, unitPrice);

sscanf(line3, "%*s, %*s (%s) %s x %d $%lf", idNumber, partNumber,
&amountItems, &unitPrice);
printf("%s, %s, %d, %lf\n", idNumber, partNumber, amountItems, unitPrice);

我对以下字段感兴趣,其余字段被忽略。例如,在记录中:

“格思里戈万 (N210) AX299 x 6 149.94 美元”

我希望变量中按顺序依次为 N210、AX299、6 和 149.94。

结果如下:

andrew@levin-Inspiron-3650:~/Desktop/schoolwork/project2$ ./a.out

, , 0, 0.000000
, , 0, 0.000000
, , 0, 0.000000

预期输出是:

N210, AX299, 6, 149.94
N106, AX350N, 2, 63.98
N1402, AV2814, 10, 34.90

请分享帮助!

这不是直接来 self 的程序的代码,而是我临时创建的一个“帮助程序”文件,只是为了非常简单地调试这个问题,而无需调用整个应用程序!

以下类似的代码适用于不同的格式:记录为:

N210 AX299 6 24.99

在下面的代码中:

struct record *current = malloc(sizeof(struct record *));
current->idNumber = (char *)malloc(sizeof (char *) * 8);
current->partNumber = (char *)malloc(sizeof (char *) * 10);
sscanf(line, "%s %s %d %lf", current->idNumber, current->partNumber,
&(current->amountItems), &(current->unitPrice));

我并不期望这段代码具有丰富的 C 之美,我是一名 Java 开发人员,这是社区大学的 C 项目。但是你能帮我调试这个 sscanf 问题吗?

谢谢!

最佳答案

这里的动态分配有问题。 char *idNumber = (char *)malloc(sizeof (char*)); 行为指向 char 的指针分配空间,而不是为 char 分配空间code> 或 char 数组。这应该是这样的:

char *idNumber = malloc(sizeof (char) * 256);

或者:

char *idNumber = malloc(sizeof *idNumber * 256);

请注意,无需在 C 中转换 malloc() 的结果。第二个版本是在 C 中执行此操作的一种非常惯用的方法。通过避免在将操作数设置为 sizeof,这在编码中更容易且不易出错,并且在代码生命周期中类型发生变化时更易于维护。但是,由于 sizeof (char) 在 C 中始终为 1,因此也可能是:

char *idNumber = malloc(256);

没有必要吝啬分配,256 为输入提供了足够的空间。请记住在尝试使用分配的内存之前始终检查分配是否成功;并且不要忘记在使用完毕后释放malloced 内存。

但是,这并没有造成麻烦。问题在于,格式字符串告诉 sscanf() 匹配第一个字符串后面的逗号,但在输入中,该逗号被 %*s 消耗。没有进一步的匹配,因此 sscanf() 返回。还有一个问题是 %s) 在输入字符串末尾消耗了 ),从而在格式字符串中没有留下匹配的右括号。 %s 转换说明符读取字符串直至空白字符,因此 "Van Halen,"%*s %*s 使用,留下 "Edward" 尝试与 (%s) 进行匹配。此类错误是可以检测到的;人们应该始终检查调用scanf()系列函数返回的值,以确保输入符合预期。

这里使用 scanset 指令可以达到很好的效果。该指令:%*[^(]()告诉scanf()匹配任何字符,直到遇到(,抑制赋值并匹配在继续之前将 ( 添加到末尾。然后 %255[^)]) 指令告诉 scanf() 最多匹配 255 个字符,直到遇到 ),将结果存储在数组中,并在最后匹配 ) 后再继续。请注意此处最大宽度的规范,以防止缓冲区溢出,并注意必须为 \0 终止符留出空间,该终止符始终由 scanf() 添加。

这是一个修改后的程序,它将按预期工作:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *idNumber = malloc(256);
if (idNumber == NULL) {
perror("Allocation failure");
exit(EXIT_FAILURE);
}
char *partNumber = malloc(256);
if (idNumber == NULL) {
perror("Allocation failure");
exit(EXIT_FAILURE);
}

int amountItems = 0;
double unitPrice = 0;

char *line1 = "Govan, Guthrie (N210) AX299 x 6 $149.94";
char *line2 = "Mustaine, Dave (N106) AX350N x 2 $63.98";
char *line3 = "Van Halen, Edward (N1402) AV2814 x 10 $34.90";

if (sscanf(line1, "%*[^(]( %255[^)]) %255s x %d $%lf",
idNumber, partNumber, &amountItems, &unitPrice) < 4) {
fprintf(stderr, "Input error in line1\n");
} else {
printf("%s, %s, %d, %f\n",
idNumber, partNumber, amountItems, unitPrice);
}

if (sscanf(line2, "%*[^(]( %255[^)]) %s x %d $%lf",
idNumber, partNumber, &amountItems, &unitPrice) < 4) {
fprintf(stderr, "Input error in line2\n");
} else {
printf("%s, %s, %d, %f\n",
idNumber, partNumber, amountItems, unitPrice);
}

if (sscanf(line3, "%*[^(]( %255[^)]) %s x %d $%lf",
idNumber, partNumber, &amountItems, &unitPrice) < 4) {
fprintf(stderr, "Input error in line3\n");
} else {
printf("%s, %s, %d, %f\n",
idNumber, partNumber, amountItems, unitPrice);
}

free(idNumber);
free(partNumber);

return 0;
}

程序输出:

N210, AX299, 6, 149.940000
N106, AX350N, 2, 63.980000
N1402, AV2814, 10, 34.900000

关于c - 为什么我不能使用 C 中的 sscanf() 将值读入具有简单格式字符串的简单变量中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47614647/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com