【问题标题】:Redirecting input using stdin使用标准输入重定向输入
【发布时间】:2011-08-29 15:33:09
【问题描述】:

我正在编写一个简短的程序来对整数数组进行排序。我无法打开我的输入文件“prog1.d”。作业要求在程序目录中创建符号链接,我在创建对象和可执行文件后,按如下方式调用程序...

prog1.exe < prog1.d &> prog1.out

我知道我的冒泡排序工作正常且高效,因为我使用了自己的测试“txt”文件。

作业说:

您的程序从标准输入中获取随机整数并将它们放入一个数组中,将数组中的整数按升序排序,然后在标准输出上显示该数组的内容。

如何在 EOF 之前使用 'cin' 读取文件并将整数添加到我的数组 a[] 中?

到目前为止,这是我的代码:

int main( int argc, char * argv[] )
{
    int a[SIZE];

    for ( int i=1; i<argc; i++)
    {
        ifstream inFile; // declare stream
        inFile.open( argv[i] ); // open file
        // if file fails to open...
        if( inFile.fail() )
        {
            cout << "The file has failed to open";
            exit(-1);
        }
        // read int's & place into array a[]
        for(int i=0; !inFile.eof(); i++)
        {
            inFile >> a[i];
        }
        inFile.close(); // close file
    }

    bubbleSort(a); // call sort routine
    printArr(a); // call print routine

    return 0;
}

我知道打开流是错误的方法,我只是将它用于我用来确保排序正常的测试“txt”文件。老师说我们应该把输入重定向到“cin”,就像有人在键盘上输入整数一样。

任何帮助将不胜感激。

【问题讨论】:

  • 您的冒泡排序有效吗?这是一个矛盾。
  • 大声笑,很好。我的意思是它按预期工作。更好?
  • @Benjamin Lindley:在极少数情况下,实施良好的冒泡排序优于所有其他常用排序算法。
  • @Nobody:你指的是鸡尾酒排序还是梳子排序?因为这些不再是冒泡排序了。
  • @Mooing Duck:不。我说的是气泡排序实现,它的平均案例复杂度为 O(n²),但在快速排序和其他需要 O(n log n) 的特殊情况下可以在 O(n) 中运行。一种这样的特殊情况是排序序列或每个第二个元素与其前一个元素交换位置的序列。

标签: c++ sorting stdin


【解决方案1】:

当您在命令行上使用重定向时,argv 不包含重定向。相反,指定的文件只是成为您的stdin/cin。因此,您不需要(也不应该尝试)显式打开它——只需从标准输入读取,就像在输入未重定向时从终端读取一样。

【讨论】:

    【解决方案2】:

    由于您在标准输入上传输文件,因此您在 argv[1] 上没有文件名,只需在用户在控制台输入时读取标准输入,例如使用cin

    cin.getline (...);
    

    【讨论】:

    • +1,直到你提到gets(),它应该得到-1。
    • 你能举个例子吗?我基本上是在问如何从整个文件中读取输入,就好像他们在控制台上打字一样
    • @Oli 已修复,我误解是 c 不是 c++
    • @bluetickk,使用 完全相同的代码,就像您从控制台读取所写的一样。这就是 i/o 重定向的美妙之处:您的程序甚至不知道它是从文件读取还是从控制台读取。
    • @bluetickk,在read int's &amp; place into array a[] 评论后面已经有了代码。只需使用cin 而不是inFile
    【解决方案3】:

    其他答案完全正确,但这里是重写的代码来澄清:

    int main( int argc, char * argv[] )
    {
        int a[SIZE];
        int count = 0;
    
        // read int's & place into array a[]
        //ALWAYS check the boundries of arrays
        for(int i=0; i<SIZE; i++) 
        {
            std::cin >> a[i];
            if (std::cin)
                count = count + 1;
            else
                break;
        }
    
        bubbleSort(a, count); // call sort routine
        printArr(a, count); // call print routine
    
        return 0;
    }
    

    【讨论】:

    • 请不要鼓励使用std::ios::eof 来测试输入是否结束。测试&gt;&gt;表达式的bool值更容易更可靠。
    • 请参阅 ideone.com/79dyqideone.com/FH6xQ 了解为什么 std::ios::eof 是邪恶的示例。
    • 已更正。我通常会尝试以最小的变化来纠正样本,这就是我最初留下那部分的原因。
    • 这些示例中的错误与 eof 无关,而与检查错误位置的流状态有关。虽然我承认这是 istreams 的一个非常常见的错误。
    • 我不同意。不管你把eof()放在哪里,你都会有一个错误。考虑:ideone.com/1Obb8ideone.com/UAzAa
    【解决方案4】:

    正如大家所说,直接使用std::cin——你不需要打开输入文件,你的shell已经为你完成了。

    但是,请,请,请不要使用cin.eof() 来测试您是否已到达输入的末尾。如果您的输入有缺陷,您的程序将挂起。即使您的输入没有缺陷,您的程序也可能(但不一定)多运行一次循环。

    试试这个循环:

    int a[SIZE];
    int i = 0;
    while( std::cin >> a[i]) {
      ++i;
    }
    

    或者,使用会自动增长的std::vector 来增加健壮性:

    std::vector<int> a;
    int i;
    while(std::cin >> i) {
      a.push_back(i);
    }
    

    或者,使用通用算法:

    #include <iterator>
    #include <algorithm>
    ...
    std::vector<int> a;
    std::copy(std::istream_iterator<int>(std::cin),
              std::istream_iterator<int>(),
              std::back_inserter(a));
    

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      相关资源
      最近更新 更多