2013-02-16 34 views
2

我試圖建立一個程序,從用戶採取短句,並以相反的順序顯示它們。不幸的是,我剛開始使用C++,我需要知道這麼做。 例如:如果用戶輸入的輸入:C++使用指針以相反的順序顯示句子

I like the red color 
blue is also nice 
and green is lovely 
but I don't like orange 

輸出:

but I don't like orange 
and green is lovely 
blue is also nice 
I like the red color 

提前感謝!

#include<iostream> 
#include<string> 
using namespace std; 

const int SIZE= 500; 

int main() 
{ 

    const int SIZE = 500; 
    char mystring[SIZE]; 
int i; 
for(i=0; i<SIZE; i++) 
{ 

    cout<<"Enter a string: "; 
    cin.getline(mystring, SIZE); 
    } while (mystring != 0); 

     char * reverse= new char[strlen(mystring) + 1]; 
     char *p1 = mystring+ strlen(mystring); 
     char *p2 = reverse; 


     while(p1 != mystring) 
     { 
     p1--; 
     *p2= *p1; 
     p2++; 
    } 

    *p2 = '\0'; 
    cout << reverse<<endl; 


    system("PAUSE"); 
    return 0; 
} 
+0

是std :: string和反向迭代器的一個選項嗎? – billz 2013-02-16 02:34:22

+1

當您從用戶讀取字符串時,請將其複製並推入堆棧。然後彈出堆棧直到它爲空 – James 2013-02-16 02:36:00

+1

@billz OP正試圖重新實現'tac'。 string.reverse()將不會提供。 – kay 2013-02-16 02:37:49

回答

2

你打算這是下面的算法接近相當方式:

  1. 將文件加載到一個緩衝區,用空字符終止它。
  2. 將指針p定位到最後一個緩衝槽的位置。
  3. 雖然p沒有指向緩衝區開始執行以下操作:
    • 如果字符是一個換行符('\n')然後
      1. 發送字符串過去換行(p+1)到標準輸出。
      2. 用空字符覆蓋p指向的換行符。
    • 減量p退回一個字符位置。
  4. 上述循環結束後,剩下一行:第一個。發送到標準輸出,你就完成了。

左右我被引導相信。需要考慮的重要事項如下:

  1. 該算法是否適用於空文件?
  2. 該算法是否僅與包含換行符的文件一起使用?
  3. 該算法是否適用於多行文件WITH NO拖尾換行符?
  4. 該算法是否可以在單行文件中使用WITH NO拖尾換行符?
  5. 該算法是否適用於帶有拖尾換行符的多行文件?
  6. 該算法是否適用於帶有拖尾換行符的單行文件?

話雖這麼說,這裏是一個潛在的候選人:

#include <iostream> 
#include <fstream> 
#include <iterator> 
#include <vector> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    // assume the file to reverse-print is the first 
    // command-line parameter. if we don't have one 
    // we need to leave now. 
    if (argc < 2) 
     return EXIT_FAILURE; 

    // will hold our file data 
    std::vector<char> data; 

    // open file, turning off white-space skipping 
    ifstream inf(argv[1]); 
    inf.seekg(0, inf.end); 
    size_t len = inf.tellg(); 
    inf.seekg(0, inf.beg); 

    // resize buffer to hold (len+1) chars 
    data.resize(len+1); 
    inf.read(&data[0], len); 
    data[len] = 0; // terminator 

    // walk the buffer backwards. at each newline, send 
    // everything *past* it to stdout, then overwrite the 
    // newline char with a nullchar (0), and continue on. 
    char *start = &data[0]; 
    char *p = start + (data.size()-1); 
    for (;p != start; --p) 
    { 
     if (*p == '\n') 
     { 
      if (*(p+1)) 
       cout << (p+1) << endl; 
      *p = 0; 
     } 
    } 

    // last line (the first line) 
    cout << p << endl; 

    return EXIT_SUCCESS; 
} 

輸入

I like the red color 
blue is also nice 
and green is lovely 
but I don't like orange 

輸出

but I don't like orange 
and green is lovely 
blue is also nice 
I like the red color 

一個相當簡單的方法

簡單的方法可以做到這一點,我將解釋在前進的道路上評論的每一步。機會是你不能使用這樣的事情,但重要的是你瞭解什麼是提供給您,當您可以

#include <iostream> 
#include <fstream> 
#include <iterator> 
#include <vector> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    // assume the file to reverse-print is the first 
    // command-line parameter. if we don't have one 
    // we need to leave now. 
    if (argc < 2) 
     return EXIT_FAILURE; 

    // collection that will hold our lines of text 
    vector<string> lines; 

    // read lines one at a time until none are returned 
    // pushing each line in to our vector. 
    ifstream inf(argv[1]); 
    string line; 
    while (getline(inf, line)) 
     lines.push_back(line); 
    inf.close(); 

    // a LOT happens in the next single line of code, and 
    // I will try to describe each step along the way. 
    // 
    // we use std::copy() to copy all "items" from 
    // a beginning and ending iterator pair. the 
    // target of the copy is another iterator. 
    // 
    // our target iterator for our formatted ouput 
    // is a special iterator class designed to 
    // perform an output-stream insertion operation 
    // (thats the << operator) to the stream it is 
    // constructed with (in our case cout) using each 
    // item we give it from our copy-iteration. to use 
    // this class the "copied" item must support the 
    // traditional insertion operator <<, which of 
    // course, std::string does. after each item is 
    // written, the provided suffix (in our case \n) 
    // is written as well. without this all the lines 
    // would be ganged together. 
    // 
    // lastly, to glue this together (and the whole 
    // reason we're here), we use a pair of special 
    // iterators designed to work just like the regular 
    // begin() and end() iterators you're familiar with, 
    // when traversing forward in a sequence, but these 
    // ones, rbegin() and rend(), move from the last 
    // item in the sequence to the first item, which is 
    // *exactly* what we need. 

    copy(lines.rbegin(), lines.rend(), 
     ostream_iterator<string>(cout, "\n")); 

    // and thats it. 
    return EXIT_SUCCESS; 
} 

輸入

I like the red color 
blue is also nice 
and green is lovely 
but I don't like orange 

輸出

but I don't like orange 
and green is lovely 
blue is also nice 
I like the red color 

UPDATE:結合用戶輸入

結合用戶輸入的第二個版本將是一個例子:

#include <iostream> 
#include <iterator> 
#include <vector> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    // collection that will hold our lines of text 
    vector<string> lines; 
    do 
    { // prompt the user 
     cout << "Sentance (<enter> to exit): "; 
     string line; 
     if (!getline(cin, line) || line.empty()) 
      break; 
     lines.push_back(line); 
    } while (true); 

    // send back to output using reverse iterators 
    // to switch line order. 
    copy(lines.rbegin(), lines.rend(), 
     ostream_iterator<string>(cout, "\n")); 

    return EXIT_SUCCESS; 
} 
+0

非常感謝,但如果數據不是來自文件,我的意思是數據是由用戶給出的有區別嗎? – Todd 2013-02-17 03:40:38

+0

例如,如果用戶要求「輸入句子<0退出或ctl-z什麼:,,,,,,, – Todd 2013-02-17 03:42:10

+0

@Todd非常抱歉,我出去了,不能提前回答。有很多方法可以第二個實際上最容易實現,因爲你可以將輸入源改爲「cin」而不是本地文件流,並將其轉換爲do-prompt-read-test-loop,其餘的將最終完成 – WhozCraig 2013-02-17 04:38:49

1

也許是這樣的:

#include <string> 
#include <iostream> 
#include <vector> 
using namespace std; 
// include headers and avoid having to use std:: all the time 
int main(){ 
    vector<string> data; 
    string line; 
    do{ 
     std::getline(std::cin, line); 
     data.push_back(line); 
    }while(cin);//read lines and store to a vector 
    for (int i=data.size()-1;i>=0;--i)// traverse the vector in a reversed order (maybe size_t for i would be better) 
     cout<<data[i]<<endl; 
} 

看起來像它的一些功課,也許你被限制使用某些功能。 如果你堅持,我們可以寫一個作業安全版本:

// this is just intended to illustrate how RIDICULOUS it is not to use STL features. 
#include <cstring> 
#include <cstdio> 
#include <cstdlib> 
int main(){ 
#define MAXLEN (10000) 
    char* buffer = (char*)malloc(MAXLEN);//allocate space from heap 
    char* buffer_ptr = buffer + 1; 
    *buffer = '\0';//string terminator 
    while(fgets(buffer_ptr,buffer+MAXLEN-buffer_ptr , stdin)){ 
     buffer_ptr += strlen(buffer_ptr); 
     ++buffer_ptr;// reserve the '\0' 
    } 
    buffer_ptr -= 2; 
    while(buffer_ptr >= buffer){ 
     if (!*buffer_ptr)// find end of string 
      fputs(buffer_ptr+1,stdout); 
     --buffer_ptr;// traverse backward 
    } 
    free(buffer);//free space 
} 

避免了C++的擴展只要有可能。 (在一個可能是荒謬的方式)

+0

謝謝,實際上我需要使用指針,如果我可以使用vector,那將會很棒。 – Todd 2013-02-16 02:52:13

+0

@託德,你需要告訴我們你的任務的確切詞。如果你想使用指針,你可以使用char []而不是字符串。這會有點愚蠢,但它可能符合你的目的。 – kay 2013-02-16 02:55:06

+0

是啊,實際上我使用的是char,我在想什麼是如何指出每行的每一個第一個字符來顯示它,我不知道這是否正確! – Todd 2013-02-16 03:00:28

0
#include<iostream> 
using namespace std; 

int main(){ 
    char str[100][100]; 
    for(int i =0; i < 10 ; i++) { 
     cin.getline(str[i],100); 
    } 
    for(int i = 9 ; i >=0 ; i--) { 
     cout<<str[i]<<endl; 
    } 
} 
0

這是如何做到這一點相當。

template<class It> 
struct range_t { 
    It b; It e; 

    It begin() const { return b; } 
    It end() const { return e; } 
}; 

template<class It> 
range_t<It> range(It s, It f) { 
    return {s,f}; 
} 

range(start, finish)是一個輔助,可以讓你創建一個可重複for(:)在一定範圍內。

template<class C> 
auto backwards(C&& c) { 
    using std::rbegin; using std::rend; 
    return range(rbegin(c), rend(c)); 
} 

backwards(container)返回一個範圍,它向後遍歷容器。

一旦我們編寫了上述庫代碼,所有繁重的工作都完成了。剩下的代碼讀取幾乎一樣漂亮

int main() { 
    std::cout << "Enter some text (blank line to finish):\n"; 
    std::string line; 
    std::vector<std::string> lines; 
    while (std::getline(std::cin, line)) 
    lines.push_back(line); 
    for (auto&& line:backwards(lines)) 
    std::cout << line << "\n"; 
} 

我們得到線,緩衝它們,然後打印出來倒退。

Live example

這裏的目標是使主程序邏輯儘可能清晰。樣板backwardsrange正是滿足這種需求。