#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void convert(int type, double amount, double rate);
int get_type(char* string);
void convert(int type, double amount, double rate) {
printf("%.2f %s is %.2f %s\n", amount, type == 1 ? "dollars" : "euros",amount * rate, type == 1 ? "euros" : "dollars");
}
int get_type(char* string) {
int i, c;
for (i = 0, c = string[0]; c != '\0'; c = string[i]) {
if (c >= 'A' && c <= 'Z') {
string[i] -= 'A' - 'a';
}
}
return !strcmp(string, "dollar") ? 1 : !strcmp(string, "euro") ? 2 : 0;
}
int main(int argc, char** argv) {
assert(argc != 2 || argc ==4);
if (argc == 4) {
int type = get_type(argv[1]);
if (type == 0) {
printf("%s is an invalid currency type. Use dollar or euro.\n", argv[1]);
return 1;
}
convert(type, atof(argv[2]), atof(argv[3]));
}
if (argc == 2) {
FILE* fd;
fd = fopen(argv[1], "r");
if (fd == NULL) {
printf("Could not open %s\n", argv[1]);
return 1;
}
char* typestring = (char*)malloc(16 * sizeof(char));
double amount, rate;
int matches, type;
while (!feof(fd)) {
matches = fscanf(fd, "%s %lf %lf\n", &typestring, &amount, &rate);
if (matches != 3) {
printf("Line was not formed correctly.\n");
continue;
}
type = get_type(typestring);
if (type == 0) {
printf("%s is an invalid currency type. Use dollar or euro.\n", typestring);
continue;
}
convert(type, amount, rate);
}
free(typestring);
}
if (argc == 2 && argc != 4) {
printf("Usage:\n\tmoney-exchange [dollar|euro type] [double amount] [double rate]\n");
printf("\tmoney-exchange [FILE]\n");
printf("Examples:\n\tmoney-exchange dollar 10.50 0.92\n");
printf("\tmoney-exchange euro 5.99 1.09\n");
printf("\tmoney-exchange prices.txt\n");
return 1;
}
return 0;
}
在功能&#39;主要&#39;: 47:4:警告:格式&#39;%s&#39;期望类型&#39; char *&#39;的参数,但参数3的类型为&#39; char **&#39; [-Wformat =] matches = fscanf(fd,&#34;%s%lf%lf \ n&#34;,&amp; typestring,&amp; amount,&amp; rate);
为什么会这样?
答案 0 :(得分:0)
%s格式说明符要求相应的参数是指向字符数组的指针,而不是字符串,并且您有责任分配足够大的字符数组。因此,相应的参数必须为typestring
,而不是typestring
。
您已将typestring
分配为最多15个字符的足够大的数组,但代码中没有任何内容可以验证该文件不包含更大的字符串,在这种情况下您将最终内存损坏和未定义的行为。
因此,scanf
函数族通常不是解析不受信任输入的最强大或推荐的方法。当你正在学习C和C ++时,重要的是要理解这个主题,以避免在你未来的职业生涯中犯下更为严重的错误。
答案 1 :(得分:0)
typestring是一个char *,它是%s说明符的用途,但是你提供&amp; typestring,并且包括&amp;;这使它成为一个char **。传递类型字符串没有&amp;并且你的编译器错误应该会消失,但是关于确保足够大小的答案在这里是相关的,所以请检查一下!