大家好我有一个奇怪的问题,当我使用scanf
输入数据时,它重复字符串并将它们保存为一个我不知道为什么。
请帮助
/ * Assment Label loop - 循环遍历assment标签并输入百分比和名称。 * /
i = 0;
j = 0;
while (i < totalGradedItems)
{
scanf("%s%d", assLabel[i], &assPercent[i]);
i++;
}
/ * Print Statement * /
i = 0;
while (i < totalGradedItems)
{
printf("%s", assLabel[i]);
i++;
}
输入数据
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
通过控制台输出
Prog1QuizQuizProg2MdtmMdtmFinal
答案 0 :(得分:3)
您没有显示声明......但您必须为字符串分配5个字符:
当我将枚举MAX_ASSESSMENTLEN从10调整到5时(参见下面的代码),我得到输出:
Prog1Quiz 20
Quiz 20
Prog2Mdtm 20
Mdtm 15
Final 25
您不允许终端为null。你没有告诉我们是什么导致了这个错误!而且你从打印输出中省略了换行符这一事实掩盖了这个问题。
发生的事情是'Prog1'占用了你读入的字符串的所有5个字节,并在第6个字节写入空值;然后从第六个字节开始读入测验。
当printf()
去读取'Prog1'的字符串时,它会在第一个空值处停止,这是'测验'的'z'之后的那个,产生显示的输出。重复'Prog2'和'Mtdm'。如果在“最终”之后有一个条目,它也会受到影响。你很幸运,周围有足够的零字节可以防止任何可怕的超支。
这是一个基本的缓冲区溢出(事实上,由于数组在堆栈上,它是一个基本的Stack Overflow);你试图将6个字符(Prog1加'\0'
)压缩成5个字节的空间,但它根本不能很好地工作。
首先,在数据之后打印换行符。
其次,检查scanf()是否没有返回错误 - 它可能不是,但是你和我们都无法确定。
第三,您确定数据文件包含您所说的内容吗?可能,它包含一对'测验'和一对'Mtdm'线。
顺便提及您的变量j
。
在接收阵列中的空间不足或读取失败之前,最好让输入循环运行。但是,当我稍微打扮时,代码对我有用:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char assLabel[10][10];
int assPercent[10];
int i = 0;
int totalGradedItems = 5;
while (i < totalGradedItems)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
{
fprintf(stderr, "Error reading\n");
exit(1);
}
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
i++;
}
return 0;
}
对于引用的输入数据,输出结果为:
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
我更喜欢这个版本:
#include <stdio.h>
enum { MAX_GRADES = 10 };
enum { MAX_ASSESSMENTLEN = 10 };
int main(void)
{
char assLabel[MAX_GRADES][MAX_ASSESSMENTLEN];
int assPercent[MAX_GRADES];
int i = 0;
int totalGradedItems;
for (i = 0; i < MAX_GRADES; i++)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
break;
}
totalGradedItems = i;
for (i = 0; i < totalGradedItems; i++)
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
return 0;
}
当然,如果我正确地设置scanf()
格式字符串'(意味着安全),以便限制评估名称的长度以适应分配的空间,那么循环将停止阅读在第二次尝试:
...
char format[10];
...
snprintf(format, sizeof(format), "%%%ds%%d", MAX_ASSESSMENTLEN-1);
...
if (scanf(format, assLabel[i], &assPercent[i]) != 2)
当MAX_ASSESSMENTLEN为5时,snprintf()
生成格式字符串"%4s%d"
。编译的代码为:
Prog 1
然后停下来。 '1'来自'Prog1'的第5个字符;下一个评估名称为'20',然后将'测验'转换为数字失败,导致输入循环停止(因为只转换了两个预期项中的一个)。
尽管有令人讨厌的价值,如果你想让你的scanf()
字符串调整到它所读取的数据变量的大小,你必须做一些类似于我在这里做的事情 - 使用正确的尺寸值。
答案 1 :(得分:0)
我想,你需要放一个
scanf("%s%d", assLabel[i], &assPercent[i]);
%s和%d之间的空格。
并不是一个人保存。您需要在打印%s后放置换行符或释放空格以查看差异。
添加:
当我尝试
时#include <stdio.h>
int main (int argc, const char * argv[])
{
char a[1][2];
for(int i =0;i<3;i++)
scanf("%s",a[i]);
for(int i =0;i<3;i++)
printf("%s",a[i]);
return 0;
}
带输入
123456
qwerty
sdfgh
输出是:
12qwsdfghqwsdfghsdfgh
证明,字符串数组的大小需要更大然后在那里消失。