我需要像这样对文件中每一行的数字求和:
1 2 3
10 -1 -3
结果,我应该将每一行写入另一个文件,如下所示:
6
6
在读取文件中最后一个数字之后的每一行中有更多空格时,例如,也许我使用'_'来显示此问题:
当我的功能正常工作时:
10_11_12 '\n'
1_2_3 '\n'
当我的功能不起作用时:
10_11_12_ _ _ '\n'
1_2_3 '\n'
我想我知道问题出在哪里,但我不知道如何解决。 这是我的功能:
int num=0;
char s;
while(fscanf(file, "%d", &num)==1){
fscanf(file, "%c", &s);
sum+=num;
if(s=='\n'){
fprintf(res_file, "%d\n", sum);
sum=0;
}
}
答案 0 :(得分:0)
问题是fscanf需要一个指向char的指针。在函数中,您使用的是常规字符s。
char s;
您可以通过使用s指针来解决问题。首先,分配内存。
char *s = malloc(sizeof(char) + 1);
现在,我们可以正确扫描到变量s,然后检查换行符。唯一的区别是现在我们通过取消引用s检查换行符。
if (*s == '\n')
别忘了用free()清理内存泄漏!
free(s);
我可以使用下面的代码获得所需的输出。
#include <stdio.h>
#include <stdlib.h>
int processInputFile(char *filename)
{
FILE *ifp;
int buffer = 0;
char *newline = malloc(sizeof(char) + 1);
int sum = 0;
if ((ifp = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Failed to open \"%s \" in processInputFile.\n", filename);
return -1;
}
while(fscanf(ifp, "%d", &buffer) == 1)
{
fscanf(ifp, "%c", newline);
sum += buffer;
if (*newline == '\n')
{
printf("%d\n", sum);
sum = 0;
}
}
free (newline);
fclose(ifp);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("Proper syntax: ./a.out <n>\n");
return -1;
}
processInputFile(argv[1]);
return 0;
}
答案 1 :(得分:0)
通过先读取行然后进行处理,可以更轻松地完成C中的任何逐行处理。 fgets(3)为您处理行尾;那么您只需要扫描其阅读内容即可。另外,在现实世界中,某些行将不会扫描:它们将出现错误,或者您的扫描不够全面。发生这种情况时,将输入写入标准错误非常方便,因此您可以看到正在查看的内容。
这是一个完整的程序,可以满足您的需求。它假定行的长度小于80个字节,但是不能防止无效输入。
#include <stdio.h>
#include <err.h>
int main( int argc, char *argv[] ) {
char line[80];
static const char *filename = "sum.dat";
FILE *input;
if( (input = fopen(filename, "r")) == NULL ) {
err(1, "could not open %s", filename);
}
for( int nlines = 0;
fgets(line, sizeof(line), input) != NULL;
nlines++ )
{
double value, sum = 0;
int n;
for( char *p = line; sscanf(p, "%lf%n", &value, &n) > 0; p += n ) {
sum += value;
}
printf( "line %d: sum = %lf\n", nlines, sum );
}
return 0;
}
答案 2 :(得分:0)
使用面向{em> line 的输入函数(如fgets()
或POSIX getline()
)进行读取,可确保每次调用都消耗完整的输入行。 (不要跳过缓冲区大小)。创建strtol
的目的是将每行未知数量的值转换为long
。成功转换后,您可以利用endptr
填充的strtol
参数来向下移动缓冲区,以指向转换后的最后一位数字之后的下一个字符。
这允许使用一种简单的方法来使用一对指针,p
是您的起始指针,ep
是您的末尾指针,可以在整行中随即转换值。基本方法是调用strtol
,成功完成 validation ,然后设置p = ep;
进行下一次转换。 strtol
忽略前导空格。
完全将其放入,您可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
/* (don't skimp on buffer-size) */
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line read */
size_t n = 0; /* line-counter */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line */
char *p = buf, *ep = p; /* pointer and end-pointer */
int sum = 0; /* variable to hold sum */
if (*buf == '\n') /* ignore empty lines */
continue;
while (*p && *p != '\n') {
errno = 0;
long tmp = strtol (p, &ep, 0); /* convert to temp long */
if (p == ep) { /* validate digits were converted */
fputs ("error: no digits extracted.\n", stderr);
break;
}
else if (errno) { /* validate no under/overflow occurred */
fputs ("error: underflow/overflow occurred.\n", stderr);
break;
}
else if (tmp < INT_MIN || INT_MAX < tmp) { /* validate in range */
fputs ("error: tmp exceeds range of int.\n", stderr);
break;
}
sum += tmp; /* add tmp to sum */
p = ep; /* set p to end-ptr (one past last digit used) */
}
n++; /* advance line counter */
printf ("sum line [%2zu] : %d\n", n, sum); /* output sum */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
(注意: if (*buf == '\n')
用于测试该行中的第一个字符是否为 newline 字符,并且可以简单地跳到下一行,而无需担心在空行中转换值)
使用/输出示例
使用dat/sumlines.txt
中的数据会产生预期的结果。
$ ./bin/sumline dat/sumlines.txt
sum line [ 1] : 6
sum line [ 2] : 6
如果您还有其他问题,请告诉我。