【问题标题】:FILE I/O: two file pointes [closed]文件 I/O:两个文件点
【发布时间】:2016-01-20 14:22:28
【问题描述】:

我是 FILE I/O Stream 的新手,我想编写一个程序,将“ä,Ä,ü,Ü,ö,Ö”等字符(从“texti.txt”读取)转换为“ae” ,Ae,ue,Ue,oe,Oe”并将它们写入一个名为“texto.txt”的新文件中。

第一个问题: 可以像我一样同时拥有两个文件指针(指向每个文件)吗?

第二个问题: 我在 switch 语句中的字符比较做错了什么? VS2015警告案例2和3已经存在(参考案例1)

第三个问题 fpo(指向输出文件的文件指针)是否会通过写入字符自动递增?

问题四: VS2015 警告:

C4996 'fopen':此函数或变量可能不安全。考虑改用 fopen_s。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS。有关详细信息,请参阅在线帮助。

我应该使用其他功能吗?

int main()
{
    char c;
    FILE *fpi;
    FILE *fpo;
    fpi = fopen("texti.txt","r");
    fpo = fopen("texto.txt", "w");
    if (fpi == NULL)
        fprintf(stderr, "Fehler beim Lesen");
    while (!feof(fpi))
    {
        c = fgetc(fpi);
    switch (c)

{
    case 'ä'||'Ä':      
        fputc('a', fpo);
        fputc('e', fpo);
        break;

    case 'ö'||'Ö':
        fputc('o', fpo);
        fputc('e', fpo);
        break;

    case 'ü' || 'Ü':
        fputc('u', fpo);
        fputc('e', fpo);
        break;

    default:
        fputc((c), fpo);
    }
    fpi++;
}
fclose(fpi);
fclose(fpo);

}

【问题讨论】:

  • 你怎么看,fpi++; 会怎么做?此外,c 应该是 int,并且您不会检查第二个 fopen 的结果。
  • 一次一个问题。
  • foef 执行 not work 显然是您所期望的。还要小心非 ASCII 字符编码。这很可能不会按预期工作。至少你需要char16_tchar32_t 堡垒。
  • @classMate 是的。它将继续这样做,直到您看到一个 EOF(在您阅读完最后一个字符后您会开始阅读,我认为您使用 feof 是不正确的 - feof 只有在您阅读了一个EOF,这对于您的循环来说太晚了)。在内部,打开文件的控制信息(由 FILE 指针指向)会自动更新并跟踪您的位置。您可能想在 Google 中搜索“C 中的文件 I/O”以获取一些示例。

标签: c file io


【解决方案1】:

那里确实有很多不同的问题,您应该一次专注于一个问题,如果它们与您的问题不同,请发布不同的问题。

我将回答关于 switch 语句的第二个问题。答案是,如果您想在一个案例中使用多个值,则不能。但是,如果没有 break 语句,您可以依靠案例通过失败的事实,然后您可以这样做,例如

switch (c)
{
case 'ä':
case 'Ä':
    // Code for the ä or Ä case
    break;

...
}

你可以使用tolowertoupper

switch (tolower(c))
{
case 'ä':
    // Code for the ä or Ä case
    break;

...
}

关于case 'ä'||'Ä'有什么问题的一点解释。

发生的情况是编译器将'ä' || 'Ä' 视为一个布尔 表达式,而在C 中所有非零都被认为是true。同样在 C 中布尔 true 被认为等于1,这意味着您的情况下的表达式等于1 || 1,这是真的,因此1,所以你所有的情况都是case 1.

【讨论】:

  • 从技术上讲,'ä' || 'Ä' 将字符评估为它们在文件编码中的任何代码点(而不是 1)...尽管最终结果 is 1 因为它正在执行两个非零值的布尔 OR。
  • 这是我正在寻找的答案!
  • @aaaaaa123456789 啊,是的,你是对的,我可能应该编辑我的答案以使其正确。 :)
【解决方案2】:

您可以拥有任意数量的打开文件指针(受限于进程可以拥有的最大打开文件数量,但在大多数现代操作系统中,这个数字会达到数千个)。不过,您应该记住将它们全部关闭。

至于“递增”文件指针,请记住,尽管类型被称为FILE *,但这实际上并不指向文件的内容,它指向的是一个内部管理结构<stdio.h> 用于处理文件。因此,fpi ++ 之类的东西不会更新内部文件位置指针(这是您想要做的);它只是让fpi 指向其他FILE 结构。虽然这样做是有正当理由的(例如,指向 FILE * 数组的指针),但在文件内移动并不是这样。

如果您确实需要在文件中移动,有一个名为fseek() 的函数可以执行此操作。但是,读取或写入(即调用fread()fwrite()fgets()fprintf()getc()(及其等效的fgetc())、putc()(及其等效的fputc()),以及您可以想象的任何其他对由FILE * 值表示的文件执行 I/O 的函数)已经更新了内部文件指针以指向操作处理的数据之后。换句话说,当您读取或写入一个字符时,内部文件指针已经指向该字符之后。您不需要也不应该尝试自己更新它,因为它已经为您完成了。

字符比较可能会因编码而失败——虽然有一种非常标准的方式来表示通常的 ASCII 字符(代码点 32 到 126;基本字母、数字等),但国际字符没有这种奢侈.您需要找出文件使用的编码,并手动处理该编码;可能通过使用原始字符编号而不是字符表示法。如果您想对此进行研究,这里还有广泛的字符功能可以帮助您。 编辑:我刚刚注意到case 标签中的'C' || 'c' 符号。这只是计算为 1,因为 case 标签中的任何常量表达式都在编译时解决(并且根本不允许非常量表达式)。您需要多个case 标签来匹配多个值;你不能在那里使用表达式。

最后,VS 警告是虚假的,因为fopen() 是标准库调用。不过请记住#include 相应的文件(在本例中为<stdio.h>)。

【讨论】:

  • 那么我可以比较 Chars 和它的 ASCII 码吗?喜欢:if(c==66) {}
  • 您可以这样做(事实上,在几乎所有相关平台中,它都与if (c == 'B') { /* something */ } 相同),但请记住,您需要知道确切的代码点。 ASCII 上升到 127;在那之后它是无人区(因为每个供应商都以不同的方式填充 128-255 空间),除非您知道您正在处理的文本的确切编码。 (无论如何,请记住char 是一个数字类型,因此任何对数字有效的操作都对char 有效。)
猜你喜欢
  • 2012-05-01
  • 2010-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 2013-09-22
  • 2015-11-13
  • 2016-02-09
相关资源
最近更新 更多