2013-08-23 40 views
6

Cố gắng sao chép toàn bộ tệp .txt vào một mảng char. Mã của tôi hoạt động nhưng nó rời khỏi các khoảng trắng. Vì vậy, ví dụ nếu tập tin .txt tôi đọc "I Like Pie" và tôi sao chép nó vào myArray, nếu tôi cout mảng của tôi sử dụng một vòng lặp for tôi nhận được "ILikePie"Cách sao chép tệp .txt vào một mảng char trong C++

Đây là mã của tôi

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

int main() 
{ 
    int arraysize = 100000; 
    char myArray[arraysize]; 
    char current_char; 
    int num_characters = 0; 
    int i = 0; 

    ifstream myfile ("FileReadExample.cpp"); 

    if (myfile.is_open()) 
     { 
      while (!myfile.eof()) 
      { 
       myfile >> myArray[i]; 
       i++; 
       num_characters ++; 
      }  

for (int i = 0; i <= num_characters; i++) 
     { 

     cout << myArray[i]; 
     } 

     system("pause"); 
    } 

bất kỳ đề xuất? :/

+0

arraySize nên const. – Rapptz

+0

Việc sử dụng '! Myfile.eof()' không chính xác. Thậm chí nếu bạn muốn đọc các từ, thay vì tất cả các ký tự, bạn đang sử dụng kết quả của 'myfile >> myArray [i]' mà không xác minh rằng nó đã thành công, điều đó là không chính xác. Nếu bạn muốn đọc tất cả các ký tự, thì 'while (myfile.get (myArray [i])) ++ i; 'sẽ hoạt động (nhưng bạn vẫn cần kiểm tra giới hạn). Nhưng câu trả lời của Nemanja vượt trội hơn rất nhiều. –

Trả lời

27

Với

myfile >> myArray[i]; 

bạn đang đọc từ tập tin bằng lời mà gây bỏ qua của không gian.

Bạn có thể đọc toàn bộ tập tin vào chuỗi với

std::ifstream in("FileReadExample.cpp"); 
std::string contents((std::istreambuf_iterator<char>(in)), 
    std::istreambuf_iterator<char>()); 

Và sau đó bạn có thể sử dụng contents.c_str() để có được mảng char.

Làm thế nào các công trình này

std::string có dao động xây dựng mà sao chép chuỗi các ký tự trong khoảng [đầu tiên, họ) lưu ý rằng nó sẽ không sao chép cuối cùng, trong cùng một thứ tự:

template <class InputIterator> 
    string (InputIterator first, InputIterator last); 

std::istreambuf_iterator trình lặp là bộ lặp đầu vào đọc các phần tử liên tiếp từ bộ đệm luồng.

std::istreambuf_iterator<char>(in) 

sẽ tạo iterator cho ifstream in của chúng tôi (đầu tập tin), và nếu bạn không vượt qua bất kỳ tham số cho các nhà xây dựng, nó sẽ tạo ra end-of-stream iterator (vị trí cuối cùng):

Công cụ xây dựng mặc định :: istreambuf_iterator được gọi là trình lặp cuối dòng. Khi một std hợp lệ :: istreambuf_iterator đến cuối dòng bên dưới, nó sẽ trở thành bằng trình lặp cuối dòng. Dereferencing hoặc incrementing nó tiếp tục gọi hành vi không xác định.

Vì vậy, điều này sẽ sao chép tất cả ký tự, bắt đầu từ tệp đầu tiên trong tệp cho đến khi ký tự tiếp theo kết thúc luồng.

+0

Đây là, tất nhiên, câu trả lời đúng, nhưng có hai chi tiết đáng chú ý: đầu tiên, nếu bạn muốn xem chính xác các byte trong tệp, bạn nên mở nó ở chế độ nhị phân và đảm bảo rằng tệp được nhúng với miền địa phương '" C "'; nếu không, các bản dịch khác nhau có thể xảy ra. Thứ hai, nếu tệp chứa các ký tự null, 'contents.c_str()' không phải là cách để đi. Nói chung, trong những trường hợp như vậy, tôi muốn sử dụng 'contents.data()' (nhưng tôi không thấy bất kỳ lý do nào không làm việc trực tiếp trên chuỗi). –

+0

@JamesKanze, cảm ơn bạn đã đề xuất. Tôi không sử dụng chế độ nhị phân, và tôi đã gợi ý 'c_str', như tôi đã giả định rằng OP đang sử dụng các tệp txt ASCII. Tuy nhiên, cảm ơn bạn đã bình luận, vì đây là cách tốt nhất cho tôi (và cho những người khác) để học cái gì đó mới (như "C" miền địa phương - tôi không biết nó là gì, vì vậy tôi sẽ tìm nó). –

+1

Nó không rõ ràng với tôi cho dù OP muốn các byte chính xác của tập tin trong chuỗi, hoặc cho dù ông muốn có một đại diện văn bản của chuỗi. Ý kiến ​​của tôi đề cập đến trường hợp anh ta muốn các byte chính xác; mã của bạn, chính xác như văn bản, là tốt cho một đại diện nội bộ của văn bản trong tập tin (giả sử nó là văn bản --- nhưng nếu không, 'std :: vector ' sẽ làm cho ý nghĩa hơn so với chuỗi –

8

Sử dụng đoạn mã sau:

FILE *f = fopen("textfile.txt", "rb"); 
fseek(f, 0, SEEK_END); 
long fsize = ftell(f); 
fseek(f, 0, SEEK_SET); 

char *string = (char *)malloc(fsize + 1); 
fread(string, fsize, 1, f); 
fclose(f); 

string[fsize] = 0; 
+0

Chỉ cần sửa nó, thêm cờ 'b' trong hàm fopen() –

+1

'void *' không thể trực tiếp truyền sang 'char *' (trên dòng malloc) –

1

Một giải pháp đơn giản nếu bạn đang bị ràng buộc để sử dụng mảng char, và sửa đổi tối thiểu để mã của bạn. Đoạn mã dưới đây sẽ bao gồm tất cả các khoảng trống và ngắt dòng cho đến khi kết thúc tệp.

 while (!myfile.eof()) 
     { 
      myfile.get(myArray[i]); 
      i++; 
      num_characters ++; 
     } 
+0

Đây là định nghĩa về hiệu năng kém. vì đọc byte theo byte thực sự đánh thuế đĩa –

+0

Cảm ơn bạn đã phản hồi, bạn có thể cung cấp giải pháp tốt hơn cho người đọc trong tương lai không? – Blake

+0

Bạn có nói là thi s là có khả năng nghèo, hoặc chỉ nghèo? Ngoài ra, người nghèo như tốc độ hay độ phức tạp? Tôi không biết nhiều về lớp phần cứng, nhưng tôi cho rằng trình biên dịch sẽ thực hiện một số unrolling/vectorization mà có thể làm cho hiệu năng có thể so sánh được (đặc biệt vì dữ liệu chỉ phụ thuộc vào từng cặp.) Theo quy tắc chung, tôi sử dụng 'one-liner 'các phương thức có sẵn trên các vòng lặp, nhưng nếu tôi lo ngại về * tốc độ *, tôi cũng sẽ quan tâm đến các hình phạt phương pháp ảo đằng sau hậu trường và tương tự. –

1

Một cách tiếp cận đơn giản hơn nhiều sẽ sử dụng get() chức năng thành viên:

while(!myfile.eof() && i < arraysize) 
{ 
    myfile.get(array[i]); //reading single character from file to array 
    i++; 
} 
Các vấn đề liên quan