2012-01-11 20 views
7

Tôi có bài tập về nhà C++. Bài tập về nhà đang yêu cầu chuyển đổi một chương trình c thành C++. Dưới đây là câu hỏi:cần trợ giúp chuyển đổi c thành C++ (lỗi đơn giản nhưng không thể sửa)

Bạn được yêu cầu để chuyển đổi chức năng C sau vào một hàm C++ và sau đó nhúng nó vào một chương trình hoàn chỉnh và thử nghiệm nó. Lưu ý rằng hàm này sao chép tệp nhị phân của số nguyên chứ không phải tệp văn bản . Chương trình phải chấp nhận các đối số (tệp cần sao chép và tệp được sao chép vào) từ dòng lệnh.

/* ==================== cpyFile ===================== 

This function copies the contents of a binary file 
of integers to a second file. 
Pre fp1 is file pointer to open read file 
fp2 is file pointer to open write file 
Post file copied 
Return 1 is successful or zero if error 
*/ 
int cpyFile (FILE *fp1, FILE *fp2) 
{ 
    /* Local Definitions */ 
    int data; 

    /* Statements */ 
    fseek (fp1, 0, SEEK_END); 
    if (!ftell (fp1)) 
    { 
    printf ("\n\acpyFile Error : file empty\n\n"); 
    return 0; 
    } /* if open error */ 
    if (fseek (fp1, 0, SEEK_SET)) 
    return 0; 
    if (fseek (fp2, 0, SEEK_SET)) 
    return 0; 

    while (fread (&data, sizeof (int), 1, fp1)) 
    fwrite (&data, sizeof (int), 1, fp2); 
    return 1; 
} /* cpyFile */ 

tôi đã làm hết sức mình và cố gắng chuyển đổi nó, nhưng tiếc là khi tôi đang sử dụng nó, các tập tin mà tôi nhận được sau khi copy trống. Dưới đây là câu trả lời của tôi:

#include <fstream> 
#include <cstdlib> 
#include <iostream> 
using namespace std; 
int main(int argc,char* argv[]) 
{ 
    if(argc!=3) 
    {cerr<<"invalid number of arguments. must be 3."<<endl;exit(1);} 

    fstream fp1(argv[1],ios::in); 
    if(!fp1)+{cerr<<argv[1]<<" could not be opened"<<endl;exit(1);} 

    fstream fp2(argv[2],ios::out); 
    if(!fp2)+{cerr<<"file could not be found."<<endl;exit(1);} 


    int data; 

    fp1.seekg (0,ios::end); 
    if (!fp1.tellg()) 
    { 
    cout<<"\n\acpyFile Error : file empty\n\n"; 
    return 0; 
    } /* if open error */ 
    if (fp1.seekg (0, ios::beg)) 
    return 0; 
    if (fp2.seekg (0, ios::beg)) 
    return 0; 

    while (fp1.read (reinterpret_cast<char*>(&data), sizeof (int))) 
    { 
    fp2.seekp(0); 
    fp2.write (reinterpret_cast<char*>(&data), sizeof (int)); 
    } 
    return 1; 
} 

Tôi đã làm hết sức mình và mọi thứ hoạt động tốt, ngoại trừ khi tôi sao chép tệp nhị phân, tệp tôi nhận được trống và tôi không biết tại sao.

+5

Một nỗ lực tốt, tôi khen bạn đã cho nó một phong nha đi thay vì cảm ơn chỉ đơn giản là yêu cầu người khác làm điều đó cho bạn. – dreamlax

+3

Đừng làm điều này trên bài tập về nhà của bạn, nhưng để tham khảo trong tương lai: 'std :: ofstream (argv [2]) << std :: ifstream (argv [1]); ' –

+0

Tại sao bạn có' fp2.seekp (0) '* trong * vòng lặp? – celtschk

Trả lời

7

Bạn cần phải mở tập tin trong chế độ nhị phân, như những người khác đã nói, bằng cách làm

fstream fp1(argv[1], ios::in | ios::binary); // combine ios::in with ios::binary 

fstream fp2(argv[2], ios::out | ios::binary); // combine ios::out with ios::binary 

Hoặc bạn có thể làm cho họ ifstream (trong file stream chỉ đọc) và ofstream (ra tập tin dòng, chỉ viết) và loại bỏ các ios::inios::outifstream ngụ ý ios::inofstream ngụ ý ios::out:

ifstream fp1(argv[1], ios::binary); 

ofstream fp2(argv[2], ios::binary); 

Bạn cần làm điều này bởi vì nếu bạn không làm như vậy, tệp sẽ được dịch khi bạn đọc hoặc viết cho những thứ như chuyển kết thúc dòng từ \r\n hoặc \r thành chỉ \n, v.v. dữ liệu nhị phân có thể xảy ra để có các byte đó trong chúng.

này:

if (fp1.seekg (0, ios::beg)) 
    return 0; 

if (fp2.seekg (0, ios::beg)) 
    return 0; 

Sẽ luôn luôn làm cho trở lại mã của bạn vì seekg trả về đối tượng bạn gọi nó về. Nó không tương đương với fseek trong lĩnh vực này vì fseek trả về 0 khi thành công. Vì vậy, bạn không bao giờ đi đến vòng lặp while.Đi những ra khỏi if báo cáo để nó trông như thế này:

fp1.seekg(0, ios::beg); 
fp2.seekg(0, ios::beg); 

Hoặc nếu bạn cần phải có sự kiểm tra, bạn muốn làm

if (!fp1.seekg (0, ios::beg)) // notice the added ! 
    return 0; 

if (!fp2.seekg (0, ios::beg)) // notice the added ! 
    return 0; 

Ngoài ra, đây (bên trong while):

fp2.seekp(0); 

Cài đặt điểm bạn sẽ ghi vào đầu tệp. Vì vậy, bạn sẽ không bao giờ viết bất cứ điều gì nhưng ở đầu của tập tin. Chỉ cần loại bỏ hoàn toàn dòng đó.

Ngoài ra, bạn có một return bên trong vòng lặp mà làm cho nó trở lại trên lần lặp đầu tiên. Di chuyển return 1; bên ngoài vòng lặp để bạn chỉ trở lại sau khi kết thúc vòng lặp. Nevermind rằng, misread do phong cách cú đúp bất thường.

+0

tuyệt vời. tôi đã làm những gì bạn nói và nó hoạt động. cảm ơn bạn! – LebTech

0

file nhị phân cần phải được mở đặc biệt trong chế độ nhị phân, do đó, nơi bạn có fstream fp1(argv[1],ios::in); bạn cũng nên thêm một ios :: binary để nó như vậy: fstream fp1(argv[1], ios::in | ios::binary);

1

Mỗi khi bạn đọc một khối dữ liệu mới từ fp1, bạn tua lại fp2 vào đầu luồng, về cơ bản loại bỏ những gì bạn đã viết cho fp2. Hãy thử di chuyển fp2.seekp(0) ra khỏi vòng lặp chính của bạn.

0

Trong mã C++ bạn đang tìm kiếm đầu tệp đầu ra trước khi ghi mỗi số và do đó tệp đầu ra sẽ dài tối đa 2 byte.

+1

Nó sẽ * dài ít nhất * 2 byte. Kiểu 'int' có thể là bất kỳ kích thước nào miễn là nó lớn hơn hoặc bằng 2 byte. – dreamlax

+0

@dreamlax Bạn nói đúng. Tôi đoán với tôi đó là thời gian để đi ngủ –

1

Bạn có một vài vấn đề. Tôi muốn bắt đầu bằng cách sửa chữa bit này:

if (fp1.seekg (0, ios::beg)) 
    return 0; 
if (fp2.seekg (0, ios::beg)) 
    return 0; 

Phương pháp seekg trả về một tham chiếu đến istream nó được gọi vào, vì vậy ở trên là tương đương với điều này:

fp1.seekg (0, ios::beg); 
if (fp1) // i.e., if fp1 is in a valid state (as opposed to e.g. end-of-file) 
    return 0; 
fp2.seekg (0, ios::beg); 
if (fp2) // i.e., if fp2 is in a valid state (as opposed to e.g. end-of-file) 
    return 0; 

mà rõ ràng là không phải những gì bạn muốn.

Để gỡ lỗi mã của bạn, bạn có thể sử dụng các câu lệnh như std::cout << "Got to line " << __LINE__ << std::endl; để tìm ra phần nào của chương trình đang thực sự được chạy. Điều đó có thể đã tìm thấy vấn đề trên khá nhanh.

+0

Đừng quên về '__LINE__':' cout << "Hãy để dòng" << __LINE__ << endl; ':) –

+0

@ SethCarnegie: Bị đánh cắp, cảm ơn. ;-) Tôi đã bắt đầu đề xuất một loại thông điệp khác ('" Đến ____ trong khi vòng lặp "'), và sau đó chỉ một nửa di chuyển sang phương pháp dựa trên dòng trước khi đăng. :-P – ruakh

+1

Các câu lệnh gỡ lỗi như thế này rất hữu ích cho các chương trình nhỏ; rất nhiều người luôn nói "học cách sử dụng trình gỡ lỗi", nhưng sự thật là mọi người ở giai đoạn này đều biết cách sử dụng các câu lệnh in nên hiện tại có thể hiệu quả hơn để làm như vậy. Cuối cùng, việc học cách sử dụng trình gỡ lỗi là một kỹ năng vô giá, nhưng đôi khi việc đặt 'printf' hoặc' cout' dễ dàng hơn là thiết lập các điểm ngắt, các biến xem, v.v. – dreamlax

Các vấn đề liên quan