为什么可以';我在C中使用sscanf()将值读入具有简单格式字符串的简单变量吗?
我试图解析一些简单格式化的文本,并使用数字和短字符串值创建文本/数字记录的简单数据结构。我已经调试并定位了问题;这取决于sscanf()没有使用特定的格式字符串(程序中的其他格式字符串工作正常)将值读入我的变量。我创建了一个简单的文本文件来查看发生了什么 代码如下:为什么可以';我在C中使用sscanf()将值读入具有简单格式字符串的简单变量吗?,c,scanf,C,Scanf,我试图解析一些简单格式化的文本,并使用数字和短字符串值创建文本/数字记录的简单数据结构。我已经调试并定位了问题;这取决于sscanf()没有使用特定的格式字符串(程序中的其他格式字符串工作正常)将值读入我的变量。我创建了一个简单的文本文件来查看发生了什么 代码如下: char *idNumber = (char *)malloc(sizeof (char*)); char *partNumber = (char *)malloc(sizeof (char*)); int amountIt
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);
andrew@levin-Inspiron-3650:~/Desktop/schoolwork/project2$ ./a.out
, , 0, 0.000000
, , 0, 0.000000
, , 0, 0.000000
我对以下领域感兴趣,其余的被忽略。例如,在记录中:
“Govan,Guthrie(N210)AX299 x 6$149.94”
我希望变量中有N210、AX299、6和149.94,按顺序排列
结果如下:
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);
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
请分享帮助
这不是直接从我的程序中得到的代码,而是我创建的一个“助手”文件,只是为了简单地调试这个问题,而不必调用整个应用程序
以下类似代码适用于不同的格式:
记录如下:
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问题吗
谢谢大家! 格式字符串与参数类型不匹配。与其一个接一个地指出这里的每个错误,防止这种情况的方法是启用编译器警告。例如,如果您使用的是GCC或Clang,请将
-Wall-Wextra-Werror
添加到编译器命令中。然后,编译器将告诉您有关格式字符串不匹配的所有信息。这里的动态分配有问题。行char*idNumber=(char*)malloc(sizeof(char*))
为指向char
的指针分配空间,而不是为char
或char
数组分配空间。这应该是这样的:
char *idNumber = malloc(sizeof (char) * 256);
或:
请注意,无需在C中强制转换malloc()
的结果。第二个版本是在C中执行此操作的一种非常惯用的方法。通过避免在操作数中使用显式类型来执行sizeof
,这在编码中更容易、更不容易出错,并且在代码生命周期内类型更改时更容易维护。但是,由于C中的sizeof(char)
始终为1,这也可能是:
char *idNumber = malloc(256);
在分配方面吝啬是没有意义的,256为输入提供了大量空间。在尝试使用分配的内存之前,请记住始终检查分配是否成功;完成后,不要忘记释放malloc
ed内存
但是,这并不是问题的根源。问题是格式字符串告诉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;
}
我以为你说的是“简单”,但后来我看到了输入记录和想要的和不想要的位,结果是“不简单”如果你
malloc
某个东西,你必须释放它。他们发明了函数,你用它来避免把同样棘手的代码写三次。常用的材料放在函数体中,变量放在参数中id bowling,david hoelzer。你能帮助解决sscanf问题吗?D.bowling:我已经修复了它,在gdb中,值仍然显示为没有被sscanf()填充,甚至在printf问题之外,我想我已经修复了它(在OP中被新代码替换)谢谢!我已经更改了代码以符合警告,并且代码现在已在原始帖子中编辑和替换…除了不使用args to main()之外,现在没有任何警告。我仍然收到意外的输出!您能帮助我吗?@AndrewLevin:修复所有错误!sscanf(第1行,%*s,%*s(%s)%s x%d$%lf“,idNumber,partNumber,&amountItems,&unitPrice);
如果使用我告诉过你的选项,将不会编译。我编辑了上面的代码,它确实编译了&没有给出错误。我使用了一个简单的printf来打印argc的值和argv的一个元素。编译时没有警告或错误,仍然是“空的” output@AndrewLevin:好的,现在您的错误是scanf()的工作方式与您想象的不一样。有关如何使其停止在分隔符处,请参阅:-您需要类似于%*[^,],
sscanf(line1,“%*[^(]([^)])%s%*[^x]x%d%*[^$]$%f”、idNumber、partNumber、&amountItems和unitPrice的内容;
您是否完成了tr