我必须阅读这样的文件:
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30
这是我的代码:
graphs = fopen(argv[2],"r");
if(graphs==NULL){
printf("File hostgraphs not found\n");
exit(EXIT_FAILURE);
}
while((err=fscanf(graphs,"%d ->",&num))==1){
row=num;
while((err1=fscanf(graphs," %d:%d ",&column,&visits))==2){
hostgraphs[row*n+column]=visits;
}
if(err1!=2)
break;
if(err==0){
printf("Hostgraph out of bounds\n");
exit(EXIT_FAILURE);
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%d ", hostgraphs[i*n+j]);
}
printf("\n");
}
它给了我以下结果:
0 50 30 10
0 0 0 0
0 0 0 0
0 0 0 0
预期输出必须是:
0 50 30 10
0 0 0 0
10 0 0 20
0 20 10 30
有人可以帮我吗?
答案 0 :(得分:0)
修复很简单:删除
中fscanf
格式字符串中的尾随空格
fscanf(graphs," %d:%d ",&column,&visits)
应该简化为
fscanf(graphs,"%d:%d", &column, &visits)
答案 1 :(得分:0)
您可以通过使用getline一次一行地读取文件,然后在每行上分别应用相同的逻辑来实现此目的。
在以下代码中,我首先使用getline
方法从buffer
中的文件中获取一行。然后我使用fmemopen
方法将该行处理为FILE
指针fbuffer
,该方法用于读取类似文件的字符串:
graphs = fopen(argv[2],"r");
if(graphs==NULL)
{
printf("File hostgraphs not found\n");
exit(EXIT_FAILURE);
}
char *buffer = NULL;
size_t len = 0;
while(getline(&buffer, &len, graphs) != -1)
{
FILE * fbuffer = fmemopen(buffer, len, "r");
while((err=fscanf(fbuffer,"%d -> ",&num))==1)
{
row=num;
while((err1=fscanf(fbuffer," %d:%d ",&column,&visits))==2)
{
hostgraphs[row*n+column]=visits;
}
if(err1!=2)
{
break;
}
if(err==0)
{
printf("Hostgraph out of bounds\n");
exit(EXIT_FAILURE);
}
}
free(buffer);
buffer = NULL;
len = 0;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ", hostgraphs[i*n+j]);
}
printf("\n");
}
注意:我刚刚添加了代码,可以让现有代码正常运行,而无需对代码进行任何更改。
答案 2 :(得分:0)
fscanf
在读取第一行后忽略换行符,然后移至下一行并在5
中读取1
并生成err1
。这是根本原因。您可以添加fseek
以向下移动并以下面的代码剪切开始新序列,或者只是将算法更改为另一个有效的算法。
graphs = fopen(argv[2],"r");
if (!graphs) {
printf("File hostgraphs not found<%s>\n", argv[1]);
exit(EXIT_FAILURE);
}
while((err = fscanf(graphs, "%d ->", &num)) == 1) {
pos = ftell(graphs); // save position
while((err1 = fscanf(graphs, " %d:%d", &column, &visits)) == 2 ) {
hostgraphs[num * n + column] = visits;
pos = ftell(graphs); // save position
}
// seek back to previous one and start new sequence
fseek ( graphs , pos, SEEK_SET );
}
for(i = 0; i< n; i++){
for(j = 0; j < n; j++){
printf("%d ", hostgraphs[i * n + j]);
}
printf("\n");
}
答案 3 :(得分:0)
你很接近,但是你需要一种方法来定位每个'\n'
,而无需从文件中读取下一行值。使用fscanf
非常困难,因为输入文件中的每一行都有不同数量的元素。
另一种方法是使用fgets
读取整行,然后将初始"row -> "
前缀与数据值分开。如果将值移动到单独的值缓冲区(例如vbuf
),则可以通过找到space
,前进到下一个digit
然后使用{{}来重复循环缓冲区。 1}}拆分sscanf
和column
。
(您实际上甚至不需要在visits
中拆分值,您只需使用指针超过使用整行的vbuf
文本。)
以下示例将这些部分放在一起,并将值解析为"row -> "
中的正确位置。仔细看看,如果您有疑问,请告诉我:
hostgraphs
输入文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { COLS = 4, MAXH = 16, MAXC = 64 };
int main (int argc, char **argv) {
char buf[MAXC] = "", vbuf[MAXC] = "";
char *p = NULL, *rfmt = "%d -> %[^\n]";
int row, column, visits, hostgraphs[MAXH] = {0};
size_t i, j, n = 0;
FILE *graphs = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!graphs) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, graphs))
{
*vbuf = 0; /* initialize vbuf, split %d:%d pars into vbuf */
if (sscanf (buf, rfmt, &row, vbuf) < 1)
break;
if (!*vbuf) { /* check vbuf contians values */
n++;
continue;
}
/* read 1st pair */
if (sscanf (vbuf, "%d:%d", &column, &visits) != 2) {
fprintf (stderr, "error: invalid line format\n");
exit (EXIT_FAILURE);
}
hostgraphs[row*COLS+column] = visits;
p = vbuf; /* assign p, parse remaining pairs */
while ((p = strchr (p, ' '))) /* find space */
{
while (*p < '0' || '9' < *p) /* find digit */
p++;
if (sscanf (p, "%d:%d", &column, &visits) == 2)
hostgraphs[row*COLS+column] = visits;
}
n++; /* advance row count */
}
for (i = 0; i < n; i++) { /* output values */
printf (" row[%2zu] : ", i);
for(j = 0; j < COLS; j++) {
printf (" %2d", hostgraphs[i * COLS + j]);
}
printf ("\n");
}
if (graphs != stdin)
fclose (graphs);
return 0;
}
<强>输出强>
$ cat ../dat/hostgraph.txt
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30