0

问题是该文件不会被读取......显然数组有问题,但我真的不知道如何解决这个问题......我是 C++ 'arrays' 和 'strings' 的初学者.. .

我的文件应该读取代码,然后翻译文件,然后将文本输出到新文件中。

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <string.h>
using namespace std;

int main()    
{    
    // Declarations
    string reply;    
    string inputFileName;

    ifstream inputFile;
    ofstream outFile;
    char character;

    cout << "Input file name: ";
    getline(cin, inputFileName);

    // Open the input file.    
    inputFile.open(inputFileName.c_str());

    // Check the file opened successfully.    
    if ( ! inputFile.is_open()) {

        cout << "Unable to open input file." << endl;    
        cout << "Press enter to continue...";

        getline(cin, reply);

        return 1;
    }

    // This section reads and echo's the file one character (byte) at a time.
    while (inputFile.peek() != EOF) {

        inputFile.get(character);

        //cout << character;
      //Don't display the file...

        char cipher[sizeof(character)];

      //Caesar Cipher code...
        int shift;
        do {
            cout << "enter a value between 1-26 to encrypt the text: ";
            cin >> shift;
        } 
        while ((shift <1) || (shift >26));

        int size = strlen(character);
        int i=0;

        for(i=0; i<size; i++)
        {
            cipher[i] = character[i];

            if (islower(cipher[i])) {
                cipher[i] = (cipher[i]-'a'+shift)%26+'a';
            }
            else if (isupper(cipher[i])) {
                cipher[i] = (cipher[i]-'A'+shift)%26+'A';
            }
        }

        cipher[size] = '\0';
        cout << cipher << endl;  
    }

    cout << "\nEnd of file reached\n" << endl;

    // Close the input file stream
    inputFile.close();

    cout << "Press enter to continue...";
    getline(cin, reply);

    return 0;   
}
4

3 回答 3

2

简而言之:您使用的是 c++,所以不要使用整个 C 的东西。

  • 不要使用字符数组,使用std::string
  • 不使用islower(char)但使用std::islower(char,locale)
  • 不要使用 C 风格的数组,而是std::array(编译时常量大小)或std::vector(动态大小)

你会希望它更像这样:

#include <string>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <locale>

int main (void)
{
  std::string input_filename;
  std::cout << "Input file name: ";
  std::getline(std::cin, input_filename);
  unsigned int shift;
  do 
  {
    std::cout << "Enter a value between 1-26 to encrypt the text: ";
    std::cin >> shift;
  } 
  while ((shift == 0) || (shift > 26));
  try
  {
    std::string filestring;
    std::ifstream input(input_filename, std::ios_base::in);
    if (input)
    {
      input.seekg(0, std::ios::end);   
      filestring.reserve(input.tellg());
      input.seekg(0, std::ios::beg);
      filestring.assign
        (std::istreambuf_iterator<char>(input), 
          std::istreambuf_iterator<char>());
    } 
    else
    {
      std::string error_string("Reading failed for: \"");
      error_string.append(input_filename);
      error_string.append("\"");
      throw std::runtime_error(error_string);
    }
    std::string result;
    result.reserve(filestring.size());
    std::locale const loc;
    for (auto character : filestring)
    {
      char const shifter(std::islower(character, loc) ? 'a' : 'A');
      result.push_back((character-shifter+shift)%26+shifter);
    }
    std::cout << result << std::endl;
  }
  catch (std::exception & e)
  {
    std::cout << "Execution failed with an exception: " << std::endl;
    std::cout << e.what() << std::endl;
  }
}

此解决方案需要 C++11 支持。如果您没有 C++11,您可以将循环替换为:

size_t const N(filestring.length());
for (size_t i(0u); i<N; ++i)
{
  char const shifter(std::islower(filestring[i], loc) ? 'a' : 'A');
  result.push_back((filestring[i]-shifter+shift)%26+shifter);
}
于 2013-08-01T21:08:56.193 回答
0

您正在使用单个字符,例如,只有一个字母或一个数字。因此,大小处理的整个过程都是无用的,因为大小始终为 1。您可能应该使用 const char*。但是你根本不能使用 filestream.get(),因为它只返回一个 char(而不是 cstring aka const char*)。而且您可以使用 fstream.get() 作为循环的条件,因此您不需要询问 eof 标志。

    char my_char;
    std::ifstream infstream("filename.txt");
    if(!infstream.isopen())
        return -1;
    while(infstream.get(my_char) {
        //do some stuff
    }

或者

   std::string my_string;
    std::ifstream infstream("filename.txt");
    if(!infstream.isopen())
        return -1;
    while(infstream >> my_string) {
        //do some stuff
    }

对于 C++ 中的动态数组,请使用 std::vector 或 std::list 或...其他 STL 容器之一,因此您不必在内存管理和使用静态大小的数组上浪费时间。std::string 是在 C++ 中处理字符串的方法。它类似于 STL 容器,但仅适用于 char。

于 2013-08-01T20:54:54.217 回答
0

通过查看您的代码,“字符”被声明为 a char,这意味着它只能存储一个字节的信息。然而后来你开始使用它,就好像它是一个字符数组一样。

您还将“密码”声明为您手动管理的字符数组,就像一个容易出错的字符串。然而,真正的问题是您在 C++ 中混合了类似 C 的代码。换句话说,您的代码编写方式不被视为惯用的 C++。

Pixelchemist 已经讨论了重点,因此我将仅提供上述代码的最小重构工作示例:

#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
using namespace std;

int main()
{    
    string filename;
    cout << "enter input file: ";
    cin >> filename;

    ifstream inputFile( filename.c_str() );
    string plaintext;
    do
    {
      plaintext += inputFile.get();
    }while(inputFile);
    cout << plaintext << endl;

    string  &ciphertext = plaintext;

    //Caesar Cipher code...
    int shift = rand() % 26 + 1;
    for(size_t i = 0; i < ciphertext.size(); ++i)
    {
        if (islower(ciphertext[i])) {
            ciphertext[i] = (ciphertext[i] - 'a' + shift) % 26 + 'a';
        }
        else if (isupper(ciphertext[i])) {
            ciphertext[i] = (ciphertext[i] - 'A' + shift) % 26 + 'A';
        }
    }

    cout << ciphertext << endl;
}

您会注意到在重构中我完全取消了charchar[]数组,并将其替换为std::string. 我还在明文输入上就地执行密码操作。这是通过为plaintext调用ciphertext的可读性创建一个引用别名来完成的。同样在我的示例中,转换是随机完成的,用于原型制作,但您应该将其更改为将其作为用户输入。

于 2013-08-01T22:05:09.980 回答