我正在尝试编写一个程序,它接收一个明文文件作为它的参数并解析它,将所有数字加在一起然后打印出总和。以下是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
static int sumNumbers(char filename[])
{
int sum = 0;
FILE *file = fopen(filename, "r");
char *str;
while (fgets(str, sizeof BUFSIZ, file))
{
while (*str != '\0')
{
if (isdigit(*str))
{
sum += atoi(str);
str++;
while (isdigit(*str))
str++;
continue;
}
str++;
}
}
fclose(file);
return sum;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Please enter the filename as the argument.\n");
exit(EXIT_FAILURE);
}
else
{
printf("The sum of all the numbers in the file is : %d\n", sumNumbers(argv[1]));
exit(EXIT_SUCCESS);
}
return 0;
}
我正在使用的文本文件是:
这是一个相当无聊的文本文件 一些随机数分散 贯穿始终。
这是一个:87,这是另一个:3
最后两个数字:12 1938年。完成。呼。
当我编译并尝试运行它时,我遇到了分段错误。
答案 0 :(得分:14)
你没有为缓冲区分配空间。
指针str
只是一个悬空指针。因此,您的程序有效地将从文件读取的数据转储到您不拥有的内存位置,从而导致分段错误。
你需要:
char *str;
str = malloc(BUFSIZ); // this is missing..also free() the mem once done using it.
或只是:
char str[BUFSIZ]; // but then you can't do str++, you'll have to use another
// pointer say char *ptr = str; and use it in place of str.
编辑:
还有另一个错误:
while (fgets(str, sizeof BUFSIZ, file))
第二个参数应该是BUFSIZ
而不是sizeof BUFSIZ
。
<强>为什么吗
因为第二个参数是要读入缓冲区的最大字符数,包括空字符。由于sizeof BUFSIZ
为4
,因此您可以将最多3
个字符读入缓冲区。这就是为什么19381
被视为193
然后81<space>
的原因。
答案 1 :(得分:3)
您尚未分配任何内存来填充str
。 fgets
将第一个参数作为缓冲区,而不是未指定的指针。
您需要定义合理大小的缓冲区,而不是char *str;
,而不是char str[BUFSIZ];
答案 2 :(得分:2)
因为您没有为缓冲区分配空间。
答案 3 :(得分:2)
很多人已经解决了你问过的问题,但我有一个问题作为回报。你认为这完成了什么:
if (isdigit(*str))
{
if (isdigit(*str))
{
sum += atoi(str);
str++;
while (isdigit(*str))
str++;
continue;
}
}
具有完全相同条件的两个连续if
语句应该是什么意思? (注意记录:两者都没有else
条款。)
答案 4 :(得分:1)
你已经声明了char * str,但是你还没有为它预留内存。你将需要malloc内存。
使用valgrind可以轻松找到许多与内存相关的错误,例如此错误。我强烈建议将它用作调试工具。
答案 5 :(得分:1)
char *str;
str没有分配内存。使用malloc()为其分配一些内存,或者使用预定义的大小声明它。
char str[MAX_SIZE];
答案 6 :(得分:1)
你的程序有几个错误:
The |numb|er 1|2345| is |larg|e.
,其中垂直线表示缓冲区的内容。然后,您将分别计算1和2345。isdigit
。只要您阅读任何“大”字符(大于char
),行为就会未定义。您的程序可能会崩溃或产生不正确的结果或做任何想做的事情。要解决此问题,您必须先将值转换为SCHAR_MAX
,例如unsigned char
。或者,与我的代码一样,您可以从isdigit((unsigned char) *str)
函数中提取值,该函数可以保证是fgetc
的有效参数。isdigit
)的函数,但无法分配缓冲区。正如其他人所指出的,获取缓冲区的最简单方法是声明局部变量fgets
。char buffer[BUFSIZ]
变量用于两个目的:保存缓冲区的地址(在整个执行时间内应保持不变)和用于分析文本的指针(在执行期间会发生变化)。制作这两个变量。我会称他们为str
和buffer
(指针的缩写)。这是我的代码:
p
答案 7 :(得分:0)
这是一个完成工作的功能:
static int sumNumbers(char* filename) {
int sum = 0;
FILE *file = fopen(filename, "r");
char buf[BUFSIZ], *str;
while (fgets(buf, BUFSIZ, file))
{
str=buf;
while (*str)
{
if (isdigit(*str))
{
sum += strtol(str, &str, 10);
}
str++;
}
}
fclose(file);
return sum;
}
这不包括错误处理,但效果很好。对于您的文件,输出将是
文件中所有数字的总和为:19483