【问题标题】:How do I reverse the a array of chars and store them in a new file?如何反转字符数组并将它们存储在新文件中?
【发布时间】:2017-01-31 14:13:23
【问题描述】:

我一直试图在不使用指针的情况下解决这个问题,只使用基础知识(我是学生),但我无法很好地解决这个问题。

void ReverseFile() {

FILE *originalM, *fin;

fopen_s(&originalM, "original.txt", "r");
fopen_s(&fin, "inverted.txt", "w");

char arr[100];

for (int i = 0; i < 100 && !feof(originalM); i++)
{
    fscanf_s(originalM, "%c ", &arr[i]);
    cout << arr[i] ;
}
cout << endl;
fclose(originalM);

for (int i = 0, k = 100; i < 100; i++, k--) 
{
    arr[k] = arr[i];
    cout << arr[k];
}
fclose(fin);}

到目前为止,我有这个函数和一个包含字符(中间有空格)的文本文件(originalM.txt):

e e a a e e a a e e a a

在第一个循环中,我获取文件的每个字符并将其保存在数组中。问题出现在第二个循环中,我想在其中反转它们。我该如何解决这个问题?我试图创建一个新数组并存储字符,但这不起作用。我也试图用这个将它打印到新文件中:

fprintf(fin, "%c ", &arr[k]);

如果有任何帮助,我将不胜感激。

【问题讨论】:

  • 你乐意使用 std::reverse 吗?
  • 您已经标记了 C 和 C++ 。它们是不同的语言。
  • 你写在同一个数组中。和@YuriyIvaskevych 这不能是C,因为C 没有cout
  • 你听说过std::vector吗?
  • @KamiKaze - 我认为迫使学生使用cstring 图书馆而不是std::string 的态度正好相反。他们不会只是“全神贯注于编程”,因为他们经常需要追逐你声称他们不受保护的非常复杂的细节。执行std::string str = "Hello World"; 比在定义char *str = "Hello World!"; 后想知道为什么程序段错误要直观得多

标签: c++ arrays char reverse


【解决方案1】:

在 C++ 中,通过使用向量和流迭代器,您可以做到这一点(泛化为任意数量的字符):

void reverseFile(const string& in, const string& out)
{
    ifstream input(in);
    ofstream output(out);
    istream_iterator<char> inStart(input), inEnd;
    // load from the input file
    vector<char> data(inStart, inEnd);
    // copy back to the output file in reversed order
    copy(data.rbegin(), data.rend(), ostream_iterator<char>(output));
}

如果您想保留字符之间的空格,ostream_iterator 还支持delimiter 参数,因此要保留空格,您只需将其添加到该行:

copy(data.rbegin(), data.rend(), ostream_iterator<char>(output, " "));

【讨论】:

  • 现在这是一件美丽的事情:)
  • 好吧,我有点理解,但我明白了。
【解决方案2】:

您可以使用std::reverse 原地反转arr。除非您始终确定 arr 的所有 100 值都将包含有意义的值,否则您需要跟踪您读取的值的数量。

当您使用惯用的 C++ 时,一切都变得微不足道:

void ReverseFile() 
{
    std::ifstream ifs{"original.txt"};

    // Read from `ifs` into a `arr` vector.
    // (From "http://stackoverflow.com/questions/7241871").
    std::ostringstream oss;
    ss << file.rdbuf();
    const auto& s = ss.str();
    std::vector<char> arr(s.begin(), s.end());

    // Reverse `arr` in place:
    std::reverse(std::begin(arr), std::end(arr));

    // Save `arr` to file.
    std::ofstream ofs{"inverted.txt"};
    for(auto x : arr) ofs << x;
    ofs.flush(); 
    ofs.close();
} 

【讨论】:

  • 除了使用for(auto)还有其他方法吗?我可以用正常的方式来做吗?
  • @Kamelo10:是的,但你为什么要这样做?
  • 嗯...为什么要读取全部 100 个字符?
  • @StoryTeller:旨在反转 OP 代码中的值的错误循环正在循环所有 100 个元素,这就是我做出假设的原因。
  • @VittorioRomeo - OP 做错了。维护它的答案是错误的。毕竟,这不仅仅是展示闪亮的 C++ 特性。
【解决方案3】:

您正在使用此代码进行反转:

for (int i = 0, k = 100; i < 100; i++, k--) 
{
    arr[k] = arr[i];
    cout << arr[k];
}

想想吧。在前 50 次迭代中,您 rewrite 数组的前半部分使用镜像的第二部分的数据,在第二个 50 次迭代中,您 rewrite 第二部分使用复制到第一的。你需要的是:

for (int i = 0; i < 50; i++) 
{
    char tmp; //you can use std::swap instead.
    tmp = arr[i];
    arr[i] = arr[100-i];
    arr[100-i] = tmp;
}

当然,像 std::reverse 这样的解决方案更好。

【讨论】:

  • 好吧,我明白了。
  • 但是……你有介绍过它吗?对于仅 100 个字符,时间差异应该不会很明显,但对于更大的大小,您的算法可能会破坏 locality 并使硬件缓存的用处降低,从而导致代码效率降低。始终仔细分析所有低级优化尝试!
【解决方案4】:

好的,假设您已将一些字符串读入数组char arr[100];。现在要反转它,您可以使用以下内容:

size_t length = strlen(arr);
for (int i = 0; i < length / 2; ++i)
{
    char swapChar = arr[i];
    arr[i] = arr[length-i-1];
    arr[length-i-1] = swapChar;
}

您可以使用std::swap,而不是 for 循环中的 3 个语句:

std::swap(arr[i], arr[length-i-1]);

另一种方法是使用@VittorioRomeo 已经回答的std::reverse

编辑 1: 感谢 @StoryTeller 指出您的数组应该以 NULL 结尾,以便 strlen 工作。所以在你读完数据之后(比如l 字符)做arr[l] = '\0';

【讨论】:

  • 使用 strlen 获取 C 样式数组的长度是个坏主意。您可以在编译时使用sizeof 静态获取大小(更好的主意是using a template function。其余答案对于教育目的很有趣,但我强烈建议使用 std::reverse 而不是重新发明轮子。
  • 调用 strlen 是未定义的行为,因为该数组是用不确定的值归档的,并且 OP 不会 NUL 终止它。
  • @VittorioRomeo 也可以使用std::stringstd::vector&lt;char&gt; 来存储数据。那么回到sizeof - 如果我们读取的字符少于 100(或任何分配的大小)怎么办?
  • @StoryTeller 是的,感谢您指出这一点,已修复和编辑。
【解决方案5】:

为什么不按相反的顺序保存呢?

void ReverseFile() {
    FILE *originalM, *fin;
    fopen_s(&originalM, "original.txt", "r");
    fopen_s(&fin, "inverted.txt", "w");

    char arr[100];
    for (int i = 0; i < 100 && !feof(originalM); i++)
    {
        fscanf_s(originalM, "%c ", &arr[i]);
        cout << arr[i] ;
    }
    cout << endl;
    fclose(originalM);

    for (int k = i - 1, k >= 0; k--) 
    {
        cout << arr[k];
    }
    fclose(fin);
}

【讨论】:

    猜你喜欢
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 2014-06-25
    • 2021-06-09
    相关资源
    最近更新 更多