本题的目的是学习如何逐个字符地读取一行字符,进行修改并保存到另一个文件中。
为了简单起见,我们以一个简单的应用程序为例,它使用众所周知的简单算法“移位密码”加密外部文本文件。我只能给你一个框架,如下所示,其余的我都不知道。
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{plain.txt}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
\end{filecontents*}
% shift parameter,
% positive value moves forward (for example, 1 makes A get shifted to B),
% negative value moves backward (for example, -1 makes B get shifted to A).
\def\offset{13}
\newread\reader
\newwrite\writer
\begin{document}
\openin\reader=plain.txt
\immediate\openout\writer=encrypted.txt
\loop
\read\reader to \data
\unless\ifeof\reader
\immediate\write\writer{Do something here}
\repeat
\immediate\closeout\writer
\closein\reader
\end{document}
我想了解的有趣的部分:
- 如何从外部文件中获取的单行逐个读取一个字符。
- 如何修改单个字符。
- 如何知道从外部文件中提取的单行字符数。
请使用最简单的方法,以便新手(像我)可以轻松消化代码。
答案1
最简单的方法是设置大写表来进行翻译。
该文件进行两次编码以确认您回到开始的地方(除了空格规范化)
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{plain.txt}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
\end{filecontents*}
% shift parameter,
% positive value moves forward (for example, 1 makes A get shifted to B),
% negative value moves backward (for example, -1 makes B get shifted to A).
\def\offset{13}
\newread\reader
\newwrite\writer
\def\wrot#1{%
\uppercase{\immediate\write\writer{#1}}}
\begin{document}
\makeatletter
{
\count@`a
\loop
\uccode\count@=\numexpr\count@+\offset\relax
\uccode\numexpr\count@+\offset\relax=\count@
\advance\count@\@ne
\ifnum\count@<`n
\repeat
\count@`A
\loop
\uccode\count@=\numexpr\count@+\offset\relax
\uccode\numexpr\count@+\offset\relax=\count@
\advance\count@\@ne
\ifnum\count@<`N
\repeat
\openin\reader=plain.txt
\immediate\openout\writer=encrypted.txt
\loop
\read\reader to \data
\unless\ifeof\reader
\expandafter\wrot\expandafter{\data}
\repeat
\immediate\closeout\writer
\closein\reader
\openin\reader=encrypted.txt
\immediate\openout\writer=reencrypted.txt
\loop
\read\reader to \data
\unless\ifeof\reader
\expandafter\wrot\expandafter{\data}
\repeat
\immediate\closeout\writer
\closein\reader
}
\section{plain.txt}
\input{plain.txt}
\section{encrypted.txt}
\input{encrypted.txt}
\section{reencrypted.txt}
\input{reencrypted.txt}
\end{document}
答案2
这应该允许所有 ASCII 可打印字符。
\begin{filecontents*}{plain.txt}
u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
\end{filecontents*}
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\int_gzero_new:N \g_karl_offset_int
\ior_new:N \l_karl_input_stream
\iow_new:N \l_karl_output_stream
\seq_new:N \l__karl_input_seq
\tl_new:N \l__karl_input_tl
\tl_new:N \l__karl_temp_tl
\tl_const:Nn \c_karl_space_tl { ~ }
\NewDocumentCommand{\cypher}{omm}
{% #1 = shift #2 = input file, #3 = output file
\IfValueT{#1}{ \int_gset:Nn \g_karl_offset_int { #1 } }
\ior_open:Nn \l_karl_input_stream { #2 }
\iow_open:Nn \l_karl_output_stream { #3 }
\ior_str_map_inline:Nn \l_karl_input_stream
{
\tl_set:Nn \l__karl_input_tl { ##1 }
\tl_replace_all:Nnn \l__karl_input_tl { ~ } { \c_karl_space_tl }
\karl_write:V \l__karl_input_tl
}
\ior_close:N \l_karl_input_stream
\iow_close:N \l_karl_output_stream
}
\cs_new_protected:Npn \karl_write:n #1
{
\tl_clear:N \l__karl_temp_tl
\tl_map_inline:nn { #1 } { \karl_shift:n { ##1 } }
\iow_now:NV \l_karl_output_stream \l__karl_temp_tl
}
\cs_generate_variant:Nn \karl_write:n { V }
\cs_generate_variant:Nn \iow_now:Nn { NV }
\cs_new_protected:Npn \karl_shift:n #1
{
\group_begin:
\token_if_eq_meaning:NNTF #1 \c_karl_space_tl
{
\char_set_lccode:nn { `~ } { \g_karl_offset_int + 32 }
\tl_to_lowercase:n { \group_end: \tl_put_right:Nn \l__karl_temp_tl { ~ } }
}
{
\int_compare:nTF { `#1 + \g_karl_offset_int > 126 }
{ \char_set_lccode:nn { `#1 } { `#1 + \g_karl_offset_int - 126 + 32 } }
{
\int_compare:nTF { `#1 + \g_karl_offset_int < 32 }
{ \char_set_lccode:nn { `#1 } { `#1 + \g_karl_offset_int + 126 - 32 } }
{ \char_set_lccode:nn { `#1 } { `#1 + \g_karl_offset_int } }
}
\tl_to_lowercase:n { \group_end: \tl_put_right:Nn \l__karl_temp_tl { #1 } }
}
}
\ExplSyntaxOff
\cypher[13]{plain.txt}{thirteen.txt}
\cypher[-13]{thirteen.txt}{plain13.txt}
\cypher[15]{plain.txt}{fifteen.txt}
\cypher[-15]{fifteen.txt}{plain15.txt}
\stop
plain.txt
u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
thirteen.txt
$3FMMk*J.**,
Xn!y4"-"#$qr{#"-q|-{|#-pn!r-no|$#-qn"uv{t-}n##r!{";
Xn!y4"-"#$qr{#"-q|-{|#-pn!r-no|$#-n!!|&-#v}";
Xn!y4"-"#$qr{#"9-o(-#ur-&n(9-q|-{|#-x{|&-&un#-n-#!n{"s|!zn#v|{-zn#!v'-v";
plain13.txt
u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
fifteen.txt
&5HOOm,L0,,.
Zp#{6$/$%&st}%$/s~/}~%/rp#t/pq~&%/sp$wx}v/!p%%t#}$=
Zp#{6$/$%&st}%$/s~/}~%/rp#t/pq~&%/p##~(/%x!$=
Zp#{6$/$%&st}%$;/q*/%wt/(p*;/s~/}~%/z}~(/(wp%/p/%#p}$u~#|p%x~}/|p%#x)/x$=
plain15.txt
u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
答案3
虽然我完全赞成使用 LaTeX 作为制作精美书籍和文档的工具,但这个问题只是要求使用一种更适合该问题的编程语言来回答。
这是用 Python 实现的。它非常冗长,但我认为几乎所有有编程知识的人,即使从未见过一行 Python 代码,也能理解并在一定程度上修改以下代码:
import string
filecontents = """Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
"""
f = open('plain.txt', 'w')
f.write(filecontents)
f.close()
def shift(char, offset):
if char in string.lowercase:
shifted_index = string.lowercase.index(char) + offset
shifted_char = string.lowercase[shifted_index % len(string.lowercase)]
elif char in string.uppercase:
shifted_index = string.uppercase.index(char) + offset
shifted_char = string.uppercase[shifted_index % len(string.uppercase)]
else:
# do nothing for special characters, otherwise we end up with non-printable
shifted_char = char
return shifted_char
def read_process_save(filename, offset):
input = open('plain.txt', 'r')
output = open('plain_shift.txt','w')
while True:
char = input.read(1)
if char:
shifted = shift(char, offset)
output.write(shifted)
else:
break
input.close()
output.close()
offset = 13
read_process_save('plain.txt', offset)
plain_shifted.txt
生成包含以下内容的文件:
Xney'f fghqragf qb abg pner nobhg qnfuvat cnggreaf.
Xney'f fghqragf qb abg pner nobhg neebj gvcf.
Xney'f fghqragf, ol gur jnl, qb abg xabj jung n genafsbezngvba zngevk vf.
如果我们更加 Pythonic 并使用“包含电池”座右铭,标准库甚至提供 rot13 编码:
from codecs import getencoder
encoder = getencoder('rot-13')
rot13string = encoder(mystring)[0]