【问题标题】:How do I read a string from a text file and stop at a certain character? C++如何从文本文件中读取字符串并在某个字符处停止? C++
【发布时间】:2014-12-16 03:45:50
【问题描述】:

我正在解密使用我的加密程序制作的加密文件。我将尝试解释整个场景,以便每个人都能了解我的程序到底在做什么。

我的加密程序让用户输入一个字符串,然后将字符向右移动一个 8 到 15 之间的随机数。然后它将加密文件发送到名为 secret.dat 的目的地

它在加密文件中读取的是

10rovvys1237123&5#10

它首先告诉您字符被移动的数字为 (10),然后是加密字符串 (hello 123 123),空格使用空格之前的字符并将该字符替换为 4('y ' 和 '7'),而 '&' 字符显示加密终止的时间。在 '&' 字符之后有由 '#' 字符分隔的数字,表示空格的位置。

因此,首先使用解密程序,我使用 ifstream 打开文件并读取一个整数,以用作我向左移动来加密它,然后我遇到了问题。我不知道如何将字符读入字符串直到 '&' 字符,以便我可以将这些字符恢复正常。我找到了一种获取它们的方法,但我不知道如何将它们放入字符串中。

这就是我所做的,我能够将字符抓取到“&”字符:

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main()
{
    //Declare Variables
    int shift;
    char character;
    char endOfFile = '&';
    ifstream inData;

    //Open file
    inData.open("secret.dat");

    //Begin program
    inData >> shift;
    cout << shift << endl;

    inData.get(character);

    while(character != endOfFile)
    {
        if (character >= 'a' && character <= 'z')
        {
            character = ((character - 'a' - shift) % 26) + 'a';
        }
        if (character >= '0' && character <= '9')
        {
            character = ((character - '0' - shift) & 10) + '0';
        }
        cout << character;
        inData.get(character);
    }
    return 0;
}

我的第二个问题是我用来将字符移回的公式,因为它似乎无法正常工作,因为我认为我需要做的就是更改我的加密公式,它只是将移位添加到减去移位。但这是一个不同的问题,主要问题是抓取字符并将它们放入字符串中,以便我以后可以使用它们。现在循环只是抓取每个字符并将其输出,但除了循环外的第一个字符之外,我无法访问其他字符。

任何帮助将不胜感激,因为我似乎无法在其他任何地方找到我的解决方案。

【问题讨论】:

  • 您可能想了解std::getline,它允许您停止阅读任何指定的字符,而不仅仅是换行符(顾名思义)。
  • std::string 允许追加,因此您可以在循环中追加字符。或者如果使用std::getline 函数,则在输入后遍历字符串并进行转换。
  • 最后,您应该考虑一下如果输入文件的格式不正确,或者从它读取错误会发生什么。现在你将进入一个无限循环。
  • 是的,如果文件无法读取,我会添加,但我会放在最后。

标签: c++ encryption


【解决方案1】:

我将介绍另一种基于boost::spirit 的方法,因为它可以满足您的大部分需求。我在搜索解析器时发现了精神。文档很好且全面,但可能需要花费一些时间来适应(我才刚刚开始,所以将我的答案作为可行性研究而不是作为精神可以做什么的真正参考

动作是调用函数parse_encr

int main()
{
    int my_shift;
    string encrypted_str("10rovvys1237123&5#10");

    bool success = parse_encr(encrypted_str.begin(),encrypted_str.end(),my_shift);
    cout    << "Parse Succeed ? "
            << (success ? "Yes":"no")
            << endl << "shift:" << endl
            << (success ? my_shift:0)
            << endl;

    cout << "Encrypted data are: " << str_buf.str() << endl;
    //...
}

结果是

Parse Succeed ? Yes
shift:
10
Encrypted data are: rovvys1237123

如何做到这一点?使用 Spirit(这里只调用 qi::phrase_parse):

template <typename Iterator>
bool parse_encr(Iterator first, Iterator last,int & shift)
{
    bool r = qi::phrase_parse(
            first,
            last,
            qi::int_[boost::phoenix::ref(shift) = _1] >>
            qi::lexeme[ *qi::char_("a-zA-Z_ 0-9")[&cat_char<char>] ] >>
            qi::char_('&') >>
            qi::int_ >>
            qi::char_('#') >>
            qi::int_,
            qi::space
        );
    if (first != last) // fail if we did not get a full match
        return false;
    return r;
}

我会让你自己发现精神,但很快就解释了:

您通过使用规则 qi::int_ 来指定您正在等待一个 int 的事实。如果您正在等待字符 '&',则使用 qi::char('&')。 你不需要 qi::lexeme 但我让这个例子(关闭空格跳过)

星*表示一个或多个...

如果某些规则成功,您可以执行操作。该操作包含在方括号 [ ]

之间

例如第一个调用精神调用凤凰的另一个方面,它允许您绑定到一个参数。第二个是调用函数cat_char

stringstream str_buf;

template <typename T>void cat_char(T & item)
{
    str_buf << item;
}

这个方法更强大,因为你检查你的语法会得到不同的字段 。

一堆包含...以便您可以重播代码(您至少需要安装 boost 或 boost 标头...)

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_lit.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>


using namespace std;
using namespace boost::spirit;

【讨论】:

    【解决方案2】:

    您可以使用 std::getline 从输入流中读取字符串,直到某个字符/分隔符:)

    // Assume your inData stream contains "10rovvys1237123&5#10"
    
    int shift = 0;
    std::string encrypted;
    
    inData >> shift;
    std::getline(inData, encrypted, '&');
    
    // Here
    // shift = 10
    // encrypted = "rovvys1237123"
    

    至于向后移动,只要您只是将一个整数值添加到每个字符以移动您的字符串,您应该能够通过循环遍历每个字符并减去相同的值来执行相反的操作。比如:

    std::string decrypted = "";
    for (auto& character : encrypted) {
        decrypted += character - shift;
    }
    

    【讨论】:

    • 我真是个白痴哈哈。我一直在尝试使用getline,但一直收到一条我无法理解的错误消息,现在才发现这是因为我使用的是“cin”而不是“inData”xD。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多