Latex nach ASCII
-
Gibt es irgendwelche Programme oder sonstiges, die von LaTeX nach ASCII konvertieren können?
Ich habe mir einige angesehen, aber die waren mehr für Strukturierungen und Crosreferences zu gebrauchen. Mir geht es aber mehr um die Formeln ^^
Zum Beispiel so:
wird zu:
5 / | 2 | x dx | / 2
Felix :xmas2:
-
Da es das offensichtlich nicht gibt, habe ich mich mal drangesetzt und habe selbst ein Programm gefrickelt. Ihr könnt es euch ja mal ansehen, über Kritik bin ich dankbar (Features, Coding-Style,...), ich lerne ja noch ^^
Ich hoffe mal, dass der Code nicht zu lang ist um ihn zu posten, mal probieren
#include <iostream> #include "Formula.h" using namespace std; int main() { while(true) { //cout << "Please type in the formula in LaTeX syntax" << endl; StringType formulaText; getline(cin, formulaText); cout << endl; Formula theFormula(formulaText); theFormula.Print(); } return (0); }
#ifndef FORMULA_H #define FORMULA_H #include <string> #include "FormulaRepresentation.h" class Formula { public: Formula(const StringType &formulaText); void Print(); ~Formula(); private: static void RemoveSpaces(StringType &text); StringArray formulaGraphic; FormulaObject *formulaRepresentation; int GraphicWidth; int GraphicHeigth; }; #endif
#include "Formula.h" #include "FormulaRepresentation.h" #include <iostream> using namespace std; Formula::Formula(const StringType &formulaTextPar) : GraphicWidth(0), GraphicHeigth(0) { StringType formulaText = formulaTextPar; RemoveSpaces(formulaText); formulaRepresentation = new Text(formulaText); GraphicWidth = GetCumulativeWidth(formulaRepresentation); GraphicHeigth = GetCumulativeBottomHeight(formulaRepresentation) + GetCumulativeTopHeight(formulaRepresentation); //Must be thought over GraphicHeigth += 2; //GraphicHeigth += 4; GraphicWidth += 2; { StringType tempString; tempString.assign(GraphicWidth, ' '); formulaGraphic.assign(GraphicHeigth, tempString); } PrintCumulative(formulaRepresentation, formulaGraphic, 0, GetCumulativeBottomHeight(formulaRepresentation) + 1); } void Formula::Print() { for(StringArray::reverse_iterator it = formulaGraphic.rbegin(); it != formulaGraphic.rend(); ++it) { cout << *it << endl; } } void Formula::RemoveSpaces(StringType &text) { StringType::iterator it = text.begin(); while(it != text.end()) { if(*it == ' ') { it = text.erase(it); } else { ++it; } } } Formula::~Formula() { delete formulaRepresentation; }
#ifndef FORMULA_REPRESENTATION_H #define FORMULA_REPRESENTATION_H #include <string> #include <vector> #include <utility> typedef std::string StringType; typedef char CharacterType; typedef std::vector<StringType> StringArray; class FormulaObject { public: FormulaObject(); virtual ~FormulaObject(); virtual int GetTopHeight() = 0; virtual int GetBottomHeight() = 0; virtual int GetWidth(); /* {return GetObjectWidth() + GetSubSuperWidth();}*/ virtual void Print(StringArray &Output, int xPosition, int yPosition) = 0; FormulaObject* GetRest() {return rest_;} protected: FormulaObject* GetSubScript() {return subScript_;} FormulaObject* GetSuperScript() {return superScript_;} virtual int GetObjectWidth() = 0; void ProcessRest(const StringType &text, unsigned int index); virtual void PrintSubScript(StringArray &Output, int xPosition, int yPosition); virtual void PrintSuperScript(StringArray &Output, int xPosition, int yPosition); private: FormulaObject *rest_; FormulaObject *subScript_; FormulaObject *superScript_; }; int GetCumulativeTopHeight(FormulaObject *begin); int GetCumulativeBottomHeight(FormulaObject *begin); int GetCumulativeWidth(FormulaObject *begin); void PrintCumulative(FormulaObject *begin, StringArray &Output, int xPosition, int yPosition); class Text : public FormulaObject { public: Text(const StringType &text); virtual int GetTopHeight() {return 1 + GetCumulativeBottomHeight(GetSuperScript()) + GetCumulativeTopHeight(GetSuperScript());} virtual int GetBottomHeight() {return 1 + GetCumulativeBottomHeight(GetSubScript()) + GetCumulativeTopHeight(GetSubScript());} virtual void Print(StringArray &Output, int xPosition, int yPosition); protected: virtual int GetObjectWidth(); private: void AfterProcessing(); StringType text_; }; class Delimiter : public FormulaObject { public: Delimiter(const StringType &text); virtual int GetTopHeight(); virtual int GetBottomHeight(); virtual void Print(StringArray &Output, int xPosition, int yPosition); virtual ~Delimiter(); protected: virtual int GetObjectWidth(); private: FormulaObject *content_; CharacterType leftDelimiterType_; CharacterType rightDelimiterType_; int GetFullHeight(); }; class Fraction : public FormulaObject { public: Fraction(const StringType &text); virtual int GetTopHeight(); virtual int GetBottomHeight(); virtual void Print(StringArray &Output, int xPosition, int yPosition); virtual ~Fraction(); protected: virtual int GetObjectWidth(); private: FormulaObject *numerator_; FormulaObject *denominator_; }; class Integral : public FormulaObject { public: Integral(const StringType &text); virtual int GetTopHeight() {return 3 + GetCumulativeBottomHeight(GetSuperScript()) + GetCumulativeTopHeight(GetSuperScript());} virtual int GetBottomHeight() {return 3 + GetCumulativeBottomHeight(GetSubScript()) + GetCumulativeTopHeight(GetSubScript());} virtual void Print(StringArray &Output, int xPosition, int yPosition); virtual int GetWidth(); protected: virtual int GetObjectWidth() {return 3;} virtual void PrintSubScript(StringArray &Output, int xPosition, int yPosition); virtual void PrintSuperScript(StringArray &Output, int xPosition, int yPosition); private: }; class Root : public FormulaObject { public: Root(const StringType &text); virtual int GetTopHeight(); virtual int GetBottomHeight(); virtual void Print(StringArray &Output, int xPosition, int yPosition); virtual ~Root(); protected: virtual int GetObjectWidth(); private: FormulaObject *content_; //FormulaObject *degree_; int GetFullHeight(); }; template<class T> FormulaObject* CreateFormulaObject(const StringType &text) { return new T(text); } class SymbolFactory { public: static SymbolFactory& TheSymbolFactory(); FormulaObject* MakeSymbol(const StringType &text); typedef FormulaObject* (*CreatorFunction)(const StringType&); private: SymbolFactory(); std::vector<std::pair<StringType, CreatorFunction> > creatorEntries; }; #endif
#include "FormulaRepresentation.h" #include <cassert> using namespace std; //TO BE DONE: Unknown patterns beginning with a \ . // \sum //Greek Letters (Unicode) int GetCumulativeTopHeight(FormulaObject *begin) { int maxTopHeight = 0; while(begin != 0) { if(begin->GetTopHeight() > maxTopHeight) { maxTopHeight = begin->GetTopHeight(); } begin = begin->GetRest(); } return maxTopHeight; } int GetCumulativeBottomHeight(FormulaObject *begin) { int maxBottomHeight = 0; while(begin != 0) { if(begin->GetBottomHeight() > maxBottomHeight) { maxBottomHeight = begin->GetBottomHeight(); } begin = begin->GetRest(); } return maxBottomHeight; } int GetCumulativeWidth(FormulaObject *begin) { int WidthSum = 0; while(begin != 0) { WidthSum += begin->GetWidth(); begin = begin->GetRest(); } return WidthSum; } void PrintCumulative(FormulaObject *begin, StringArray &Output, int xPosition, int yPosition) { int xOffset = 0; while(begin != 0) { begin->Print(Output, xPosition + xOffset, yPosition); xOffset += begin->GetWidth(); begin = begin->GetRest(); } } SymbolFactory::SymbolFactory() { creatorEntries.push_back(pair<StringType, CreatorFunction>("\\left",&CreateFormulaObject<Delimiter>)); creatorEntries.push_back(pair<StringType, CreatorFunction>("\\frac",&CreateFormulaObject<Fraction>)); creatorEntries.push_back(pair<StringType, CreatorFunction>("\\int",&CreateFormulaObject<Integral>)); creatorEntries.push_back(pair<StringType, CreatorFunction>("\\sqrt",&CreateFormulaObject<Root>)); } SymbolFactory& SymbolFactory::TheSymbolFactory() { static SymbolFactory theSymbolFactory = SymbolFactory(); return theSymbolFactory; } FormulaObject* SymbolFactory::MakeSymbol(const StringType &text) { for(unsigned int i = 0; i < creatorEntries.size(); ++i) { if(text.find(creatorEntries[i].first, 0) == 0) { return creatorEntries[i].second(text); } } assert(!"SpecialSymbol nicht gefunden..."); return 0; } FormulaObject::FormulaObject() : rest_(0), subScript_(0), superScript_(0) { } FormulaObject::~FormulaObject() { delete rest_; rest_ = 0; delete subScript_; subScript_ = 0; delete superScript_; superScript_ = 0; } void FormulaObject::ProcessRest(const StringType &text, unsigned int index) { if(index >= text.size()) { return; } for(int i = index; (text[i] == '^') || (text[i] == '_'); ) { StringType scriptContent; int braceDepth = 1; assert(text[i+1] == '{'); if(text[i] == '^') { for(unsigned int j = i+2; j < text.size(); ++j) { if(text[j] == '{') { ++braceDepth; } else if(text[j] == '}') { --braceDepth; } if(braceDepth == 0) { scriptContent.assign(text, i+2, j-i-2); superScript_ = new Text(scriptContent); index = j+1; i = j+1; break; } } } else if(text[i] == '_') { for(unsigned int j = i+2; j < text.size(); ++j) { if(text[j] == '{') { ++braceDepth; } else if(text[j] == '}') { --braceDepth; } if(braceDepth == 0) { scriptContent.assign(text, i+2, j-i-2); subScript_ = new Text(scriptContent); index = j+1; i = j+1; break; } } } } StringType restString; restString.assign(text.c_str(), index, text.size() - index); if(restString.size() != 0) { if(text[index] == '\\') { rest_ = SymbolFactory::TheSymbolFactory().MakeSymbol(restString); } else { rest_ = new Text(restString); } } } int FormulaObject::GetWidth() { int additionalWidth = GetCumulativeWidth(subScript_); if(GetCumulativeWidth(superScript_) > additionalWidth) { additionalWidth = GetCumulativeWidth(superScript_); } return GetObjectWidth() + additionalWidth; } void FormulaObject::PrintSubScript(StringArray &Output, int xPosition, int yPosition) { PrintCumulative(GetSubScript(), Output, xPosition + GetObjectWidth(), yPosition - GetBottomHeight() + GetCumulativeBottomHeight(GetSubScript()) + 1); } void FormulaObject::PrintSuperScript(StringArray &Output, int xPosition, int yPosition) { PrintCumulative(GetSuperScript(), Output, xPosition + GetObjectWidth(), yPosition + GetTopHeight() - GetCumulativeTopHeight(GetSuperScript()) - 1); } Text::Text(const StringType &text) : FormulaObject() { unsigned int maxIndex = text.find_first_of("\\^_"); { unsigned int ende = maxIndex; if(ende == StringType::npos) { ende = text.size(); } text_.assign(text.c_str(), ende); } if(maxIndex != StringType::npos) { ProcessRest(text, maxIndex); } AfterProcessing(); } int Text::GetObjectWidth() { return text_.size(); } void Text::AfterProcessing() { for(unsigned int i = 0; i < text_.size(); ++i) { switch(text_[i]) { case '=': case '<': case '>': case '+': case '-': case '*': case '/': text_.insert(i, 1, ' '); ++i; text_.insert(i+1, 1, ' '); break; } } } void Text::Print(StringArray &Output, int xPosition, int yPosition) { for(unsigned int i = 0; i < text_.length(); ++i) { Output[yPosition][xPosition + i] = text_[i]; } PrintSubScript(Output, xPosition, yPosition); PrintSuperScript(Output, xPosition, yPosition); } Delimiter::Delimiter(const StringType &text) : content_(0) { StringType contentString; leftDelimiterType_ = text[5]; int delimiterDepth = 1; unsigned int end = 0; for(unsigned int i = 6; i < text.size()-5; ++i) { if(text[i] == '\\') { if((text[i+1] == 'l') && (text[i+2] == 'e') && (text[i+3] == 'f') && (text[i+4] == 't')) { ++delimiterDepth; } else if((text[i+1] == 'r') && (text[i+2] == 'i') && (text[i+3] == 'g') && (text[i+4] == 'h') && (text[i+5] == 't')) { --delimiterDepth; } } if(delimiterDepth == 0) { end = i; break; } } //6 = strlen("\\right") rightDelimiterType_ = text[end + 6]; //6 = strlen(\\left) + 1 contentString.assign(text.c_str(), 6, end - 6); end += 7; content_ = new Text(contentString); //rest... ProcessRest(text, end); } int Delimiter::GetObjectWidth() { return GetCumulativeWidth(content_) + 4; } int Delimiter::GetFullHeight() { int topHeight = GetCumulativeTopHeight(content_); int bottomHeight = GetCumulativeBottomHeight(content_); if(topHeight > bottomHeight) { return 2 * topHeight; } else { return 2 * bottomHeight; } } void Delimiter::Print(StringArray &Output, int xPosition, int yPosition) { int height = GetFullHeight(); switch(leftDelimiterType_) { case '(': case ')': if(height == 1) { Output[yPosition][xPosition + 1] = '('; } else { Output[yPosition - height/2][xPosition + 1] = '\\'; for(int i = 1; i <= height-1; ++i) { Output[yPosition + i - height/2][xPosition + 1] = '|'; } Output[yPosition+height/2][xPosition + 1] = '/'; } break; case '{': case '}': break; case '[': case ']': break; } PrintCumulative(content_, Output, xPosition + 2, yPosition); switch(rightDelimiterType_) { case '(': case ')': if(height == 1) { Output[yPosition][xPosition + GetObjectWidth() - 2] = ')'; } else { Output[yPosition - height/2][xPosition + GetObjectWidth() - 2] = '/'; for(int i = 1; i <= height-1; ++i) { Output[yPosition + i - height/2][xPosition + GetObjectWidth() - 2] = '|'; } Output[yPosition + height/2][xPosition + GetObjectWidth() - 2] = '\\'; } break; case '{': case '}': break; case '[': case ']': break; } PrintSubScript(Output, xPosition, yPosition); PrintSuperScript(Output, xPosition, yPosition); } Delimiter::~Delimiter() { delete content_; content_ = 0; } int Delimiter::GetTopHeight() { return GetFullHeight()/2 + ((GetFullHeight()/2) % 2) + GetCumulativeBottomHeight(GetSuperScript()) + GetCumulativeTopHeight(GetSuperScript()); } int Delimiter::GetBottomHeight() { return GetFullHeight()/2 + ((GetFullHeight()/2) % 2) + GetCumulativeBottomHeight(GetSubScript()) + GetCumulativeTopHeight(GetSubScript()); } int Fraction::GetObjectWidth() { int objectWidth = 0; if(GetCumulativeWidth(denominator_) > GetCumulativeWidth(numerator_)) { objectWidth = GetCumulativeWidth(denominator_); } else { objectWidth = GetCumulativeWidth(numerator_); } if(objectWidth == 1) { return objectWidth + 2; } else { return objectWidth + 4; } } int Fraction::GetTopHeight() { return 1 + GetCumulativeTopHeight(numerator_) + GetCumulativeBottomHeight(numerator_) + GetCumulativeBottomHeight(GetSuperScript()) + GetCumulativeTopHeight(GetSuperScript()); } int Fraction::GetBottomHeight() { return 1 + GetCumulativeTopHeight(denominator_) + GetCumulativeBottomHeight(denominator_) + GetCumulativeBottomHeight(GetSubScript()) + GetCumulativeTopHeight(GetSubScript()); } Fraction::~Fraction() { delete numerator_; numerator_ = 0; delete denominator_; denominator_ = 0; } Fraction::Fraction(const StringType &text) { int braceDepth = 0; unsigned int end = 0; for(unsigned int i = 5; i < text.size(); ++i) { if(text[i] == '{') { ++braceDepth; } else if(text[i] == '}') { --braceDepth; } if(braceDepth == 0) { end = i; break; } } StringType contentString(text, 6, end-6); numerator_ = new Text(contentString); braceDepth = 0; int denominatorBegin = end+1; for(unsigned int i = denominatorBegin; i < text.size(); ++i) { if(text[i] == '{') { ++braceDepth; } else if(text[i] == '}') { --braceDepth; } if(braceDepth == 0) { end = i; break; } } contentString.assign(text, denominatorBegin+1, end-(denominatorBegin+1)); denominator_ = new Text(contentString); //rest... ProcessRest(text, end+1); } void Fraction::Print(StringArray &Output, int xPosition, int yPosition) { int xOffset = 0; { if(GetObjectWidth() == 3) { xOffset = 1; } else { xOffset = 2; } } int tempXOffset = xOffset; if(GetCumulativeWidth(numerator_) > GetCumulativeWidth(denominator_)) { tempXOffset += (GetCumulativeWidth(numerator_) - GetCumulativeWidth(denominator_))/2; } int yOffset = GetCumulativeTopHeight(denominator_); PrintCumulative(denominator_, Output, xPosition + tempXOffset, yPosition - yOffset); for(int i = 1; i < GetObjectWidth()-1; ++i) { Output[yPosition][xPosition + i] = '-'; } tempXOffset = xOffset; if(GetCumulativeWidth(denominator_) > GetCumulativeWidth(numerator_)) { xOffset += (GetCumulativeWidth(denominator_) - GetCumulativeWidth(numerator_))/2; } yOffset = GetCumulativeBottomHeight(numerator_); PrintCumulative(numerator_, Output, xPosition + xOffset, yPosition + yOffset); PrintSuperScript(Output, xPosition, yPosition); PrintSubScript(Output, xPosition, yPosition); } Integral::Integral(const StringType &text) { ProcessRest(text, 4); } int Integral::GetWidth() { int maxWidth = GetObjectWidth(); if(GetCumulativeWidth(GetSubScript()) > maxWidth) { maxWidth = GetCumulativeWidth(GetSubScript()); } if(GetCumulativeWidth(GetSuperScript()) > maxWidth) { maxWidth = GetCumulativeWidth(GetSuperScript()); } return maxWidth; } void Integral::Print(StringArray &Output, int xPosition, int yPosition) { int XIntOffset = (GetWidth() - GetObjectWidth()) / 2; Output[yPosition + 2][xPosition + XIntOffset + 2] = '/'; Output[yPosition + 1][xPosition + XIntOffset + 1] = '|'; Output[yPosition + 0][xPosition + XIntOffset + 1] = '|'; Output[yPosition - 1][xPosition + XIntOffset + 1] = '|'; Output[yPosition - 2][xPosition + XIntOffset + 0] = '/'; int subXOffset = (GetWidth() - GetCumulativeWidth(GetSubScript()) + 1)/2; PrintSubScript(Output, xPosition + subXOffset, yPosition); int superXOffset = (GetWidth() - GetCumulativeWidth(GetSuperScript()) + 1)/2; PrintSuperScript(Output, xPosition + superXOffset, yPosition); } void Integral::PrintSubScript(StringArray &Output, int xPosition, int yPosition) { PrintCumulative(GetSubScript(), Output, xPosition, yPosition - GetBottomHeight() + GetCumulativeTopHeight(GetSubScript()) + 1); } void Integral::PrintSuperScript(StringArray &Output, int xPosition, int yPosition) { PrintCumulative(GetSuperScript(), Output, xPosition, yPosition + GetTopHeight() - GetCumulativeBottomHeight(GetSuperScript()) - 1); } Root::Root(const StringType &text) { //ignores [n] in this (early) version int braceDepth = 0; unsigned int end = 0; for(unsigned int i = 5; i < text.size(); ++i) { if(text[i] == '{') { ++braceDepth; } else if(text[i] == '}') { --braceDepth; } if(braceDepth == 0) { end = i; break; } } StringType contentString(text, 6, end-6); content_ = new Text(contentString); ProcessRest(text, end+1); } Root::~Root() { delete content_; } int Root::GetFullHeight() { int contentHeight = GetCumulativeBottomHeight(content_) + GetCumulativeTopHeight(content_); if(contentHeight == 1) { return 3; } else { return contentHeight + 1; } } int Root::GetTopHeight() { return GetFullHeight()/2 + (GetFullHeight()%2) + GetCumulativeBottomHeight(GetSuperScript()) + GetCumulativeTopHeight(GetSuperScript()); } int Root::GetBottomHeight() { return GetFullHeight()/2 + (GetFullHeight()%2) + GetCumulativeBottomHeight(GetSubScript()) + GetCumulativeTopHeight(GetSubScript()); } int Root::GetObjectWidth() { int contentWidth = GetCumulativeWidth(content_); return contentWidth + GetFullHeight() + 1; } void Root::Print(StringArray &Output, int xPosition, int yPosition) { int height = GetFullHeight(); Output[yPosition - height/2][xPosition] = 'v'; for(int i = 1; i < height; ++i) { Output[yPosition - height/2 + i][xPosition + i] = '/'; } int contentWidth = GetCumulativeWidth(content_); for(int i = 0; i < contentWidth; ++i) { Output[yPosition + (height)/2][xPosition + GetFullHeight() + i] = '-'; } int xOffset = GetFullHeight(); PrintCumulative(content_, Output, xPosition + xOffset, yPosition); PrintSuperScript(Output, xPosition, yPosition); PrintSubScript(Output, xPosition, yPosition); }
Felix
P.S.:
Output-Beispiel:
gamma = \frac{1}{\sqrt{1-\frac{v^{2}}{c^{2}}}}
wird zu
1 gamma = ------------------------ /---------- / / / 2 / v / 1 - ---- / / 2 / c / v
Ein kleiner Fehler im Gegensatz zur Standard-LaTeX-Syntax ist, dass man auch bei einzelnen Zahlen/Buchstaben in super- und subscripts die geschweiften Klammern braucht. Außerdem ist das ganze noch nicht sehr fehlertolerant :p
-
das is ja abgefahren
-
foll geil ey!
-
-
-
Das ist für mich der Code des Monats!
-
Fafuritt für den Informatiknobelpreis!
-
Ich habe auf der Arbeit mal was ähnliches gemacht. Da wurde der TeX-Code, allerdings mit ähnlichen Einschränkungen wie bei dir, geparst und anschließend als Grafik gerendert. Aber die Sache mit der ASCII-Ausgabe gefällt mir auch sehr gut
. Da könnte man ein nettes Kommandozeilenprogramm draus basteln, was sicher ganz hilfreich wäre, wenn man in Foren unterwegs ist, die kein Rendering für LaTeX haben oder z.B. in Newsgroups.