File và các thao tác cơ bản với file trong C++

Bạn có thể cho mình xem đoạn code của bạn không ?

Em chỉ copy và chạy lại đoạn code cuối cùng của bài rồi chạy thôi anh ạ ! Em chỉ thắc mắc là câu nói “Vậy là nội dung file đã bị mã hóa dưới dạng nhị phân nên không thể đọc hoàn toàn nội dung lưu trong file được.” trong bài, tại sao lại không mã hóa kiểu chuỗi hả anh ?

chuỗi cũng là mã nhị phân, nhưng nó nằm trong vùng nhìn thấy của mảng mã ASCII
thực ra, khi ghi file, chương trình đều ghi dưới dạng nhị phân, chỉ có điều khi ta lưu vào chuỗi thì chính là ta lưu chỉ phần nhìn thấy dc của mã nhị phân trong bảng ASCII, vì vậy khi ghi 1 struct có kiểu chuỗi như bài này ta sẽ đọc dc phần đó, còn lại số và những thứ khác ở vùng ko nhìn thấy

Thực ra ghi số (vd: 60) có hai cách: text: viết chữ số 6, chữ số 0: (0x) 36 30
hoặc binary: (một số) byte biểu diễn số 60: (0x) 00 00 00 3C hoặc 3C 00 00 00 :smiley:

Em có câu hỏi:
Có cách nào dùng hàm fputs() để viết nhiều hơn một chuỗi vào file không?

Với C thuần:

  • Dùng fputs nhiều lần.

  • Dùng fprintf.

VD:

fprintf("%s\n%s", a, b);

Nếu bạn viết C++ (thuần) thì dùng ofstream với toán tử <<.

std::ofstream fo(filename);
std::string s1, s2;
fo << s1 << "\n" << s2 << endl;
2 Likes

Nếu dùng fputs nhiều lần thì code rất cồng kềnh

I’m newbie. Mình đã thử dùng vòng lặp nhưng không được.

Có cái gì mà không phải khổ đâu bạn :smile:

1 Like

Nhưng giả sử: mình muốn ghi vào chừng 1 tờ A4 thì không thể nào mà cứ dùng fputs hay fprintf được.

sao lại ko thể dùng được?

Vậy thì bạn in ra file .txt rồi chép vào file .doc nhé. Tha hồ in trên tờ A4.

1 Like

sorry. có thể dùng được nhưng mà phải dùng rất nhiều lần fputs()

thì làm 1 cái vòng for, nhìn code thấy chỉ có 1 cái fputs thôi :joy:

nếu em ko thích cout lẫn printf thì xài fmt

fmt::print("Hello, {}!", "world");  // uses Python-like format string syntax
fmt::printf("Hello, %s!", "world"); // uses printf format string syntax

std::string s = fmt::format("{0}{1}{0}", "abra", "cad");

sớm muộn gì fmt cũng được đưa vào thư viện chuẩn thôi :V

2 Likes

Ý mình kg phải thế. Ở đây mình chỉ muốn dùng dòng lệnh để ghi thông tin vào một file. Mà là khi mình làm việc với file, mình ghi thông tin qua console thì khi mình xuống hàng thì trong file nó vẫn phải xuống. Mình chỉ muốn hỏi xem mọi người có cách gì kg thôi.

đây là code của mình:

FILE* file=NULL;
file = fopen("test.txt", "w");
char write[100] = "";
gets(write);
fputs(write, file);

thế này thì chỉ có nhập được 1 dòng thôi

Đừng dùng fputs nữa là xong. Ở trên mình cũng đã nói giải pháp dùng ofstream.

1 Like
char write[100] = "";
while (1)
{
    gets(write);
    if (strlen(write) == 0) break; //muốn thoát thì enter 1 dòng trống
    //hoặc if (strcmp(write, "EXIT") == 0) break; //gõ đúng 4 chữ EXIT in hoa thì thoát
    fputs(write, file);
}

đây 1 vòng for :V

nhưng xài mảng char ko được tốt lắm vì lỡ nhập nhiều hơn 100 chữ thì sao

xài std::string:

#include <string>

std::string write;
while (1)
{
    std::getline(std::cin, write);
    if (write.empty()) break; //muốn thoát thì enter 1 dòng trống
    //hoặc if (write == "EXIT") break; //gõ đúng 4 chữ EXIT in hoa thì thoát
    fputs(write.c_str(), file); //xài phương thức .c_str() để lấy chuỗi C
}

nếu đã “lỡ” xài C++ rồi thì xài std::fstream luôn:

#include <string>
#include <fstream>

std::fstream file{"test.txt", std::ios::out);
//hoặc đơn giản hơn: std::ofstream file{"text.txt"};
std::string write;
while (1)
{
    std::getline(std::cin, write);
    if (write.empty()) break; //muốn thoát thì enter 1 dòng trống
    //hoặc if (write == "EXIT") break; //gõ đúng 4 chữ EXIT in hoa thì thoát
    file << write << "\n"; //xuất thẳng write luôn khỏi cần chuyển về chuỗi C
}
// khỏi cần gọi file.close(), xài FILE* thì phải nhớ gọi fclose(file);

em thích ngắn hơn nữa thì 1 dòng :V

for (std::string line; std::getline(std::cin, line) && !line.empty(); file << line << "\n");

C++17 thì em có thể phang kiểu này:

if (std::ofstream ofs{"text.txt"}) //viết tắt của if (std::ofstream ofs{"text.txt"}; ofs)
    for (std::string line; std::getline(std::cin, line) && !line.empty(); ofs << line << "\n");
//else { std::cerr << "Ko thể mở file `text.txt` để viết\n"; return 1; }

kiểu viết if (<khai báo biến>; <điều kiện if>) bá đạo, ko có ngôn ngữ nào có, vì thế cũng bị chửi khá nhiều vì khó đọc :joy: Giới hạn được phạm vi của biến ofs trong cái if đó nhưng vẫn ko đẹp bằng bên Python with open('text.txt', 'w') as f

em thấy xài std::string dễ đọc dễ hiểu hơn: kiểm tra chuỗi trống thì viết s.empty(), còn C phải viết s[0] == NULL hoặc strlen(s) == 0 não mình phải suy luận ra nó muốn làm gì nữa chứ ko như s.empty đọc phát hiểu liền. So sánh 2 chuỗi cũng dễ hơn, thay vì viết strcmp(s1, s2) > 0 thì ở đây viết thẳng s1 > s2 dễ hiểu hơn nhiều. Thêm cái nữa std::string muốn bao nhiêu chữ cũng được, char[100] thì giới hạn 99 chữ cái :V Code dễ hiểu hơn sao lại bắt khổ dâm mảng ký tự làm gì :V

6 Likes

Cảm ơn mọi người rất nhiều. Vấn để đã được giải đáp.:grinning::grinning::grinning:

1 Like

Trong Visual đường dẫn tới file.txt để đọc hoặc ghi phải 2 sọc nó mới chấp nhận thì sao đó ạ.

Trong nhiều ngôn ngữ, dấu sọc đơn kèm một ký tự sẽ để thể hiện 1 ký tự đặc biệt. Ví dụ :
\n , \r, \t, \0…

Những ký tự đặc biệt này là không hợp lệ trong đường dẫn cho nên dùng dấu sọc đơn hoặc sọc đơn kết hợp với nhiều ký tự lại không có ý nghĩa.

Do vậy sử dụng dấu sọc kép để biểu diễn ký tự “” thông thường.

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?