使用 C++ 将文本文件转换为 .tex 文件

使用 C++ 将文本文件转换为 .tex 文件

我有一个包含如下数据的文本文件:

word: 'Swine';      conf: 92.03;pointsize:'48':,font_name:'Verdana_Bold',X1:'152', X2:'283', Y1: '166', Y2: '202
word: 'flu';    conf: 93.43;pointsize:'48':,font_name:'Verdana_Bold',X1:'299', X2:'354', Y1: '164', Y2: '202
word: 'tightens';   conf: 90.12;pointsize:'48':,font_name:'Verdana_Bold',X1:'370', X2:'551', Y1: '164', Y2: '211
word: 'its';    conf: 96.04;pointsize:'48':,font_name:'Verdana_Bold',X1:'568', X2:'617', Y1: '166', Y2: '202
word: 'grip';   conf: 90.41;pointsize:'48':,font_name:'Verdana_Bold',X1:'632', X2:'716', Y1: '166', Y2: '211
word: 'over';   conf: 94.29;pointsize:'48':,font_name:'Verdana_Bold',X1:'732', X2:'831', Y1: '175', Y2: '202
word: 'India';      conf: 94.00;pointsize:'48':,font_name:'Verdana_Bold',X1:'848', X2:'953', Y1: '164', Y2: '202

其含义如下:

Word: Actual word to be printed
Pointsize : Font size
Font name: Name of font used
X1,X2,Y1,Y2: Coordinates of location of word in the document

我想获取所有这些数据,并将其原封不动地放在 latex 文档中。现在,我知道我必须为此编写一个 C++ 代码,首先打开一个 .tex 文件,然后通过从文本文件中读取数据来开始记录数据。我面临的问题是,如何设置文件中提到的文本的确切字体和大小?谢谢!

编辑:最后,我想使用终端命令从生成的 .tex 文件中创建一个 pdf 文件。另外,我引用了链接:https://priyankacool10.wordpress.com/2012/05/10/creating-tex-file-using-c-program/我只想知道,为了创建 .tex 文件,我需要在 C++ 代码中编写哪些内容。我不需要完整的 C++ 代码,只需要确切的语法和包详细信息。

示例输出:

在此处输入图片描述

编辑2:我需要一个 C++ 代码来从文本文件中读取输入的单词并将其写入 tex 文件。还有其他方法吗?

编辑3:(错误)

* Redefining document command \oldstylenums with arg. spec. 'm' on line 128.
*************************************************
) (/usr/share/texlive/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty

! Package fontenc Error: Encoding file `eu2enc.def' not found.
(fontenc)                You might have misspelt the name of the encoding.

See the fontenc package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.99 \ProcessOptions*

答案1

看来 TeX 可以直接读取文件,我认为你不需要 C++

在此处输入图片描述

如果你输入的文本是,text1.txt那么上面的内容就是由下面的tex,经过xelatex处理而成的。

\documentclass{article}
\usepackage{fontspec}


\newread\dfile
\openin\dfile=text1.txt

\def\printword#1: '#2'#3pointsize:'#4'#5font_name:'#6'#7\relax{%
\fontsize{#4}{\numexpr#4+6\relax}\selectfont\dofont{#6}#2 }

\def\dofont#1{\csname do #1\endcsname}
\expandafter\def\csname do Verdana_Bold\endcsname{\bfseries\fontspec{Verdana}}

\def\partest{\par}
\begin{document}

\raggedright
\loop
\ifeof\dfile\else
\read\dfile to \tmp
\ifx\tmp\partest
\par
\else
\expandafter\printword\tmp\relax
\fi
\repeat


\end{document}

对于新问题和新数据文件,您需要使用图片模式

在此处输入图片描述

虽然对于 48pt 文本来说坐标似乎相当接近,但这确实符合要求吗?

字体可以缩放到指定大小的比例(比如说一半)。

\documentclass{article}
\usepackage{fontspec}
\textwidth60cm
\pdfpagewidth80cm

\makeatletter
\newread\dfile
\openin\dfile=text2.txt

\def\printword#1: '#2'#3pointsize:'#4'#5font_name:'#6'#7\relax{%
\edef\tmp{\zap@space#7 \@empty}%
\expandafter\getcoords\tmp\relax
{\fontsize{#4}{\numexpr#4+6\relax}\selectfont\dofont{#6}#2}}

\def\dofont#1{\csname do #1\endcsname}
\expandafter\def\csname do Verdana_Bold\endcsname{\bfseries\fontspec{Verdana}}

\def\getcoords#1X1:'#2'#3Y1:'#4'#5\relax{%
\typeout{#2/#4}%
\put(#2,4)}
\def\partest{\par}
\begin{document}

\hspace*{-10cm}\begin{picture}(200,200)
\loop
\ifeof\dfile\else
\read\dfile to \tmp
\ifx\tmp\partest
\par
\else
\expandafter\printword\tmp\relax
\fi
\repeat
\end{picture}

\end{document}

答案2

我知道 Python 不是 C++,但我想练习一下这种语言。

即使字体大小缩小了 75% 左右,指定的字体大小和区域位置也不太匹配。因此,我习惯将\resizebox文本强制为指定区域位置的大小。单词是通过环境放置的\putpicture还有更强大的绘图环境,如 TikZ 或pstricks。但这里不需要高级功能,而且picture效率更高、速度更快。

坐标经过变换,因为垂直轴的方向与环境所需的 y 值相反picture。程序计算最小值和最大值,并将左下角设置为新原点。

在设置单词之前,程序会设置一些线条来显示指定的矩形。

可以使用文本文件名作为参数来调用 Python 程序。如果没有参数,则文本数据将从标准输入中获取。输出是标准输出,可以重定向到 TeX 文件。

字体和大小设置经过优化,字体只需定义一次。如果字体发生变化,也只需为一个单词设置字体。

由于有包,生成的文件会用 LuaLaTeX 或 XeLaTeX 进行处理fontspec。这样就可以更轻松地使用任意字体名称,只要 LuaTeX 或 XeTeX 知道在哪里可以找到它们即可。

有些字符在 TeX 中需要特殊处理,请参阅程序代码作为示例,了解如何处理这些字符。

更优雅一点的方法是将 TeX 序言放入新的 LaTeX 类文件中。这样生成的 TeX 文件就只包含\documentclass{...}整个序言。

#!/usr/bin/env python

import fileinput;
import re;

line_pattern = re.compile(
        r"word:\s*'(?P<word>[^']+)';\s*"
        r"conf:\s*[0-9\.]+;\s*"
        r"pointsize:\s*'(?P<pointsize>\d+)':,"
        r"font_name:\s*'(?P<font_name>[^']+)',\s*"
        r"X1:\s*'(?P<X1>\d+)',\s*"
        r"X2:\s*'(?P<X2>\d+)',\s*"
        r"Y1:\s*'(?P<Y1>\d+)',\s*"
        r"Y2:\s*'(?P<Y2>\d+)'\s*")

# Mapping from character to TeX representation
tex_char_map = {}
for c in "%#$&":
    tex_char_map[c] = "\\" + c
for c in "_^~\\{}":
    tex_char_map[c] = r"\symbol{" + str(ord(c)) + "}"

fonts = set()
words = []
x_min = None
x_max = None
y_min = None
y_max = None

for line in fileinput.input():
    match = line_pattern.match(line)
    if match:
        word = match.group("word")
        pointsize = match.group("pointsize")
        font_name = match.group("font_name")
        X1 = int(match.group("X1"))
        X2 = int(match.group("X2"))
        Y1 = int(match.group("Y1"))
        Y2 = int(match.group("Y2"))
        fonts.add(font_name)
        data = (word, pointsize, font_name, X1, X2, Y1, Y2)
        words.append(data)
        # assuming X1 <= X2 and Y1 <= Y2
        if x_min is None or X1 < x_min:
            x_min = X1
        if x_max is None or X2 > x_max:
            x_max = X2
        if y_min is None or Y1 < y_min:
            y_min = Y1
        if y_max is None or Y2 > y_max:
            y_max = Y2

tex_preamble = r"""\NeedsTeXFormat{LaTeX2e}
\documentclass[border=10pt]{standalone}
\usepackage{fontspec}
\newcommand*{\NewFont}[1]{%
  \expandafter\newfontfamily\csname#1\endcsname{#1}%
}
\newcommand*{\SetFont}[1]{%
  \csname#1\endcsname
  \ignorespaces
}
\newdimen\FontSize
\newdimen\FontUnitLength
\setlength{\FontUnitLength}{.75bp}
\newcommand*{\SetSize}[1]{%
  \setlength{\FontSize}{#1\FontUnitLength}%
  \fontsize{\FontSize}{1.2\FontSize}\selectfont
  \ignorespaces
}
%\usepackage{graphicx}
\newcommand*{\Put}{}
\def\Put(#1,#2)(#3,#4)#5{%
  \put(#1,#2){\line(1,0){#3}\line(0,1){#4}}%
  \put(#1,#2){\line(0,1){#4}}%
  \put(#1,#2){\put(0,#4){\line(1,0){#3}}}%
  %\put(#1,#2){\makebox(#3,#4)[lb]{\resizebox{#3\unitlength}{!}{#5}}}%
  \put(#1,#2){%
    \makebox(#3,#4)[lb]{%
      \resizebox{#3\unitlength}{#4\unitlength}{%
        \raisebox{\depth}{#5}%
      }%
    }%
  }%
  %\put(#1,#2){\makebox(#3,#4)[lb]{#5}}%
}
\setlength{\unitlength}{1bp}"""
print(tex_preamble)

for font in fonts:
    print(r"\NewFont{" + font + "}")

print(r"\begin{document}")

picture_width = x_max - x_min
picture_height = y_max - y_min
print(r"\begin{picture}(%d,%d)" % (picture_width, picture_height))

current_font = ""
current_pointsize = ""
for word, pointsize, font_name, X1, X2, Y1, Y2 in words:
    if font != current_font:
        print(r"\SetFont{" + font + "}")
        current_font = font

    if pointsize != current_pointsize:
        print(r"\SetSize{" + pointsize + "}")
        current_pointsize = pointsize

    w = ""
    for c in word:
        if c in tex_char_map:
            w += tex_char_map[c]
        else:
            w += c
    width = X2 - X1
    height = Y2 - Y1
    x = X1 - x_min
    y = picture_height - (Y2 - y_min)
    print(r"\Put(%d,%d)(%d,%d){%s}" % (x, y, width, height, w))

print(r"\end{picture}")

print(r"\end{document}")

输入数据(为 的值添加了结束单引号Y2):

word: 'Swine';      conf: 92.03;pointsize:'48':,font_name:'Verdana_Bold',X1:'152', X2:'283', Y1: '166', Y2: '202'
word: 'flu';    conf: 93.43;pointsize:'48':,font_name:'Verdana_Bold',X1:'299', X2:'354', Y1: '164', Y2: '202'
word: 'tightens';   conf: 90.12;pointsize:'48':,font_name:'Verdana_Bold',X1:'370', X2:'551', Y1: '164', Y2: '211'
word: 'its';    conf: 96.04;pointsize:'48':,font_name:'Verdana_Bold',X1:'568', X2:'617', Y1: '166', Y2: '202'
word: 'grip';   conf: 90.41;pointsize:'48':,font_name:'Verdana_Bold',X1:'632', X2:'716', Y1: '166', Y2: '211'
word: 'over';   conf: 94.29;pointsize:'48':,font_name:'Verdana_Bold',X1:'732', X2:'831', Y1: '175', Y2: '202'
word: 'India';      conf: 94.00;pointsize:'48':,font_name:'Verdana_Bold',X1:'848', X2:'953', Y1: '164', Y2: '202'

生成的 LaTeX 文件:

\NeedsTeXFormat{LaTeX2e}
\documentclass[border=10pt]{standalone}
\usepackage{fontspec}
\newcommand*{\NewFont}[1]{%
  \expandafter\newfontfamily\csname#1\endcsname{#1}%
}
\newcommand*{\SetFont}[1]{%
  \csname#1\endcsname
  \ignorespaces
}
\newdimen\FontSize
\newdimen\FontUnitLength
\setlength{\FontUnitLength}{.75bp}
\newcommand*{\SetSize}[1]{%
  \setlength{\FontSize}{#1\FontUnitLength}%
  \fontsize{\FontSize}{1.2\FontSize}\selectfont
  \ignorespaces
}
%\usepackage{graphicx}
\newcommand*{\Put}{}
\def\Put(#1,#2)(#3,#4)#5{%
  \put(#1,#2){\line(1,0){#3}\line(0,1){#4}}%
  \put(#1,#2){\line(0,1){#4}}%
  \put(#1,#2){\put(0,#4){\line(1,0){#3}}}%
  %\put(#1,#2){\makebox(#3,#4)[lb]{\resizebox{#3\unitlength}{!}{#5}}}%
  \put(#1,#2){%
    \makebox(#3,#4)[lb]{%
      \resizebox{#3\unitlength}{#4\unitlength}{%
        \raisebox{\depth}{#5}%
      }%
    }%
  }%
  %\put(#1,#2){\makebox(#3,#4)[lb]{#5}}%
}
\setlength{\unitlength}{1bp}
\NewFont{Verdana_Bold}
\begin{document}
\begin{picture}(801,47)
\SetFont{Verdana_Bold}
\SetSize{48}
\Put(0,9)(131,36){Swine}
\Put(147,9)(55,38){flu}
\Put(218,0)(181,47){tightens}
\Put(416,9)(49,36){its}
\Put(480,0)(84,45){grip}
\Put(580,9)(99,27){over}
\Put(696,9)(105,38){India}
\end{picture}
\end{document}

结果

相关内容