如何在C中正确从文本文件中使用scanf读取内容

huangapple go评论75阅读模式
英文:

How to properly scanf things from txt file in c

问题

这是我的代码,我试图从一个结构化如下的文件中进行 fscanf:

Tom Veri 1234567890 HJA
Peter Schmit 9874561230 ABA
Jhon Smart 0192837465 DPA
Harry Tompson 0912354876 PHA

但是在编译后,我的输出很奇怪,为什么会这样发生:

以下是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int nOfLines(FILE* file);

struct inputAbc
{
    char ime[20+1];
    char prezime[20+1];
    char jmbg[20+1];
    char sign[3+1];
};

int main()
{
    int nLines, i;
    FILE* input = NULL;
    FILE* output;
    struct inputAbc model_arr[10];

    input = fopen("input.txt", "r");
    output = fopen("output.txt", "w");
    nLines = nOfLines(input);

    for(i = 0; i < nLines+1; i++)
    {
        fscanf(input, "%s %s %s %s", 
        model_arr[i].ime, model_arr[i].prezime, 
        model_arr[i].jmbg, model_arr[i].sign);
    }
    for(i = 0; i < nLines+1; i++)
    {
        fprintf(output, 
            "ime: %s\nprezime: %s\njmbg: %s\nznakovlje: %s\n\n", 
            model_arr[i].ime, model_arr[i].prezime,
            model_arr[i].jmbg, model_arr[i].sign);
    }

    return 0;
}

int nOfLines(FILE *file)
{
    int lines = 0;
    int index;
    while(!feof(file))
    {
        index = fgetc(file);
        if(index == '\n')
            lines++;
    }
    return lines;
}

请注意,我已经删除了代码部分,只提供了代码的翻译。

英文:

This is my code and what am I trying to do is to fscanf from file that is structured like this:

Tom Veri 1234567890 HJA
Peter Schmit 9874561230 ABA
Jhon Smart 0192837465 DPA
Harry Tompson 0912354876 PHA

And after compiling my output is weird why that happens:
Code is below

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

int nOfLines(FILE* file);

struct inputAbc
{
    char ime[20+1];
    char prezime[20+1];
    char jmbg[20+1];
    char sign[3+1];
};

int main()
{
    int nLines, i;
    FILE* input = NULL;
    FILE* output;
    struct inputAbc model_arr[10];

    input = fopen(&quot;input.txt&quot;, &quot;r&quot;);
    output = fopen(&quot;output.txt&quot;, &quot;w&quot;);
    nLines = nOfLines(input);
    //printf(&quot;%d\n&quot;, nLines+1);

    for(i = 0; i &lt; nLines+1; i++)
    {
        fscanf(input ,&quot;%s %s %s %s&quot;, 
        model_arr[i].ime, model_arr[i].prezime, 
        model_arr[i].jmbg, model_arr[i].sign);
    }
    for(i = 0; i &lt; nLines+1; i++)
    {
        fprintf(output, 
            &quot;ime: %s\nprezime: %s\njmbg: %s\nznakovlje: %s\n\n&quot;, 
            model_arr[i].ime, model_arr[i].prezime,
            model_arr[i].jmbg, model_arr[i].sign);
    }

    return 0;
}

int nOfLines(FILE *file)
{
    int lines = 0;
    int index;
    while(!feof(file))
    {
        index = fgetc(file);
        if(index == &#39;\n&#39;)
            lines++;
    }
    return lines;
}

答案1

得分: 2

以下是您提供的代码的翻译:

以下是建议的代码:

1. 清晰地编译
2. 执行所需的功能
3. 生成所需的输出
4. 消除了一些“魔术”数字
5. 消除不必要的变量
6. 用注释来帮助 OP 理解代码
7.  `fscanf()` 中使用了 'max character' 修饰符,以避免缓冲区溢出和由此导致的未定义行为
8. 消除了 `#include <string.h>`,因为在发布的代码中未使用相关功能
9. 在退出之前正确地清理(关闭打开的文件)。
10. 适当检查 `fopen()`  `fscanf()`  I/O 错误
11. 对变量 `i`  `j` 使用了 `size_t`,因为它们永远不会小于0

现在,以下是建议的代码:

#include <stdio.h>
#include <stdlib.h>;

struct inputAbc
{
    char ime[20 + 1];
    char prezime[20 + 1];
    char jmbg[20 + 1];
    char sign[3 + 1];
};

#define MAX_LINES 10

int main(void)
{
    FILE *input = NULL;
    FILE *output = NULL;
    struct inputAbc model_arr[MAX_LINES];

    if ((input = fopen("input.txt", "r")) == NULL)
    {
        perror("fopen to read 'input.txt' failed");
        exit(EXIT_FAILURE);
    }

    // implied else, fopen for input successful
    if ((output = fopen("output.txt", "w")) == NULL)
    {
        perror("fopen to write 'output.txt' failed");
        fclose(input);
        exit(EXIT_FAILURE);
    }

    // implied else, fopen for output successful
    size_t i; // file global scope since needed in next code block
    for (i = 0; i < MAX_LINES; i++)
    {
        if (fscanf(input, "%20s %20s %20s %3s",
                   model_arr[i].ime,
                   model_arr[i].prezime,
                   model_arr[i].jmbg,
                   model_arr[i].sign) != 4)
        {
            break;
        }
    }

    for (size_t j = 0; j < i; j++)
    {
        fprintf(output,
                "ime: %s\nprezime: %s\njmbg: %s\nznakovlje: %s\n\n",
                model_arr[j].ime,
                model_arr[j].prezime,
                model_arr[j].jmbg,
                model_arr[j].sign);
    }

    fclose(input);
    fclose(output);

    return 0;
}
英文:

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. produces the desired output
  4. eliminates some of the 'magic' numbers
  5. eliminates unneeded variables
  6. is commented to assist OP in understanding the code
  7. uses 'max character' modifiers in the fscanf() to avoid any possibility of a buffer overflow and the resulting undefined behavior
  8. eliminates: #include &lt;string.h&gt; because none of the associated functionality is used in the posted code
  9. properly cleans up (by closing open files) before exiting.
  10. properly checks for I/O errors for fopen() and fscanf()
  11. used size_t for variables i and j as they can never be less than 0

and now, the proposed code:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
struct inputAbc
{
char ime[20+1];
char prezime[20+1];
char jmbg[20+1];
char sign[3+1];
};
#define MAX_LINES    10
int main( void )
{
FILE* input  = NULL;
FILE* output = NULL;
struct inputAbc model_arr[ MAX_LINES ];
if( (input = fopen(&quot;input.txt&quot;, &quot;r&quot;)) == NULL )
{
perror( &quot;fopen to read &#39;input.txt&#39; failed&quot; );
exit( EXIT_FAILURE );
}
// implied else, fopen for input successful
if( (output = fopen(&quot;output.txt&quot;, &quot;w&quot;) ) == NULL )
{
perror( &quot;fopen to write &#39;output.txt&#39; failed&quot; );
fclose( input );
exit( EXIT_FAILURE );
}
// implied else, fopen for output successful
size_t i;  // file global scope since needed in next code block
for( i = 0; i &lt; MAX_LINES; i++ )
{ 
if( fscanf(input ,&quot;%20s %20s %20s %3s&quot;, 
model_arr[i].ime, 
model_arr[i].prezime, 
model_arr[i].jmbg, 
model_arr[i].sign) != 4 )
{
break;
}
}
for( size_t j = 0; j &lt; i; j++ )
{
fprintf(output, 
&quot;ime: %s\nprezime: %s\njmbg: %s\nznakovlje: %s\n\n&quot;, 
model_arr[j].ime, 
model_arr[j].prezime,
model_arr[j].jmbg, 
model_arr[j].sign);
}
fclose( input );
fclose( output );
return 0;
}

huangapple
  • 本文由 发表于 2020年1月3日 22:14:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/59580073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定