TEX Quotes 以及fgetc()和fgets()解析

TEX Quotes

         Time Limit:3000MS    Memory Limit:0KB    64bit IO Format:%lld & %llu
 

Description

TeX is a typesetting language developed by Donald Knuth. It takes source text together with a few typesetting instructions and produces, one hopes, a beautiful document. Beautiful documents use `` and " to delimit quotations, rather than the mundane " which is what is provided by most keyboards. Keyboards typically do not have an oriented double-quote, but they do have a left-single-quote ` and a right-single-quote '. Check your keyboard now to locate the left-single-quote key ` (sometimes called the ``backquote key") and the right-single-quote key ' (sometimes called the ``apostrophe" or just ``quote"). Be careful not to confuse the left-single-quote ` with the ``backslash" key \. TeX lets the user type two left-single-quotes `` to create a left-double-quote `` and two right-single-quotes '' to create a right-double-quote ''. Most typists, however, are accustomed to delimiting their quotations with the un-oriented double-quote ".

If the source contained

"To be or not to be," quoth the bard, "that is the question."

then the typeset document produced by TeX would not contain the desired form:

``To be or not to be," quoth the bard, ``that is the question."

In order to produce the desired form, the source file must contain the sequence:

``To be or not to be,'' quoth the bard, ``that is the question.''

You are to write a program which converts text containing double-quote (") characters into text that is identical except that double-quotes have been replaced by the two-character sequences required by TeX for delimiting quotations with oriented double-quotes. The double-quote (") characters should be replaced appropriately by either `` if the " opens a quotation and by '' if the " closes a quotation. Notice that the question of nested quotations does not arise: The first " must be replaced by ``, the next by '', the next by ``, the next by '', the next by ``, the next by '', and so on.

Input

Input will consist of several lines of text containing an even number of double-quote (") characters. Input is ended with an end-of-file character.

Output

The text must be output exactly as it was input except that:

the first " in each pair is replaced by two ` characters: `` and

the second " in each pair is replaced by two ' characters: ''.

Sample Input

"To be or not to be," quoth the Bard, "that
is the question".
The programming contestant replied: "I must disagree.
To `C' or not to `C', that is The Question!"

Sample Output

``To be or not to be,'' quoth the Bard, ``that
is the question''.
The programming contestant replied: ``I must disagree.
To `C' or not to `C', that is The Question!''

解析

简单的引号转换

#include<stdio.h>
int main() { 
  int c, q = 1;
  while((c = getchar()) != EOF) {
    if(c == '"') { printf("%s", q ? "``" : "''"); q = !q; }
    else printf("%c", c);
  }
  return 0;
}

使用“scanf("%s")”输入字符串,但却不能在本题中使用它,因为它碰到空格 或者TAB就会停下来。虽然下次调用时会输入下一个字符串,可是不知道两次输入的字符串 中间有多少个空格、TAB甚至换行符。可以用下述两种方法解决这个问题:

第一种方法是使用“fgetc(fin)”,它读取一个打开的文件fin,读取一个字符,然后返回一 个int值。为什么返回的是int而不是char呢?因为如果文件结束,fgetc将返回一个特殊标记 EOF,它并不是一个char。如果把fgetc(fin)的返回值强制转换为char,将无法把特殊的EOF和 普通字符区分开。如果要从标准输入读取一个字符,可以用getchar,它等价于fgetc(stdin)。

使用fgetc(fin)可以从打开的文件fin中读取一个字符。一般情况下应当在检 查它不是EOF后再将其转换成char值。从标准输入读取一个字符可以用getchar,它等价于 fgetc(stdin)。

fgetc和getchar将读取“下一个字符”,因此需要知道在各种情况下,“下一个字符”是哪 个。如果用“scanf("%d", &n)”读取整数n,则要是在输入123后多加了一个空格,用getchar读 取的将是这个空格;如果在“123”之后紧跟着换行,则读取到的将是回车符“\n”。

这里有个潜在的陷阱:不同操作系统的回车换行符是不一致的。Windows是“\r”和“\n”两 个字符,Linux是“\n”,而MacOS是“\r”。如果在Windows下读取Windows文件,fgetc和getchar 会把“\r""吃掉”,只剩下“\n”;但如果要在Linux下读取同样一个文件,它们会忠实地先读 取“\r”,然后才是“\n”。如果编程时不注意,所写程序可能会在某个操作系统上是完美的,但 在另一个操作系统上就错得一塌糊涂。当然,比赛的组织方应该避免在Linux下使用Windows 格式的文件,但正如前面所强调过的:选手也应该把自己的程序写得更鲁棒,即容错性更 好。

第二种方法是使用“fgets(buf, maxn, fin)”读取完整的一行,其中buf的声明为char buf[maxn]。这个函数读取不超过maxn-1个字符,然后在末尾添上结束符“\0”,因此不会出现 越界的情况。之所以说可以用这个函数读取完整的一行,是因为一旦读到回车符“\n”,读取 工作将会停止,而这个“\n”也会是buf字符串中最后一个有效字符(再往后就是字符串结束 符“\0”了)。只有在一种情况下,buf不会以“\n”结尾:读到文件结束符,并且文件的最后一 个不是以“\n”结尾。尽管比赛的组织方应避免这样的情况(和输出文件一样,保证输入文件 的每行均以回车符结尾),但正如刚才所说,选手应该把自己的程序写得更鲁棒。 "fgets(buf, maxn, fin)"将读取完整的一行放在字符数组buf中。应当保证 buf足够存放下文件的一行内容。除了在文件结束前没有遇到“\n”这种特殊情况外,buf总是 以“\n”结尾。当一个字符都没有读到时,fgets返回NULL。

和fgetc一样,fgets也有一个"标准输入版"gets。遗憾的是,gets和它的"兄弟"fgets差别比 较大:其用法是gets(s),没有指明读取的最大字符数。这里就出现了一个潜在的问题:gets 将不停地往s中存储内容,而不管是否存储得下!难道gets函数不去管s的可用空间有多少 吗?确实如此。

C语言并不禁止程序读写"非法内存"。例如,声明的是char s[100],完全可 以赋值s[10000] = 'a'(甚至-Wall也不会警告),但后果自负。

正是因为如此,gets已经被废除了,但为了向后兼容,仍然可以使用它。从长远考虑, 最好不要使用此函数。事实上,在C11标准里,gets函数已被正式删除。

C语言中的gets(s)存在缓冲区溢出漏洞,不推荐使用。在C11标准里,该函 数已被正式删除。

猜你喜欢

转载自blog.csdn.net/lxq1071717521/article/details/81084606
TEX