Bạn đã rất gần, tôi thậm chí không chắc chắn nguyên nhân thực sự của sự thất bại là gì, bởi vì, đối với việc cắt giảm đầu tiên, tôi chỉ áp dụng [hầu hết] các bản sửa lỗi được đề xuất bởi người khác và có một chương trình làm việc .
Mặc dù nó hoạt động, tôi thấy rằng cách bạn thực hiện cuộc gọi "một trước" make_structure
sẽ kém linh hoạt hơn khi bạn mở rộng chương trình để thực hiện những việc khác. Ví dụ: bạn sẽ có bản ghi "ma" treo nếu thay vì thêm bản ghi mới, bạn quyết định không thêm thêm bản ghi mới, nhưng thực hiện một số thống kê hoặc thao tác các bản ghi hiện có.
Vì vậy, tôi đã tạo phiên bản thứ hai của chương trình có tính cách ly và tổng quát hơn.
Dưới đây là phiên bản thay đổi tối thiểu [xin vui lòng tha thứ cho việc dọn dẹp phong cách vu vơ]:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
struct pat {
char surn[16];
char name[16];
struct pat *next;
};
static FILE *h;
static struct pat *osp;
static struct pat *first;
struct pat *make_structure(void);
int
main()
{
int rlen;
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
clear();
osp = make_structure();
first = osp;
h = fopen("archivio", "r");
if (h == NULL)
printw("Archivio inesistente\n");
else {
while (1) {
printw("Lungh. nome = %d\n", sizeof osp->name);
// leave early on EOF or badly formed entry
rlen = fread(osp->surn, sizeof osp->surn, 1, h);
if (rlen != 1)
break;
// leave early on EOF or badly formed entry
fread(osp->name, sizeof osp->name, 1, h);
if (rlen != 1)
break;
printw("Cognome: %s\tNome: %s\n", osp->surn, osp->name);
osp->next = make_structure();
osp = osp->next;
}
fclose(h);
}
// NOTE: this just chews the first character (debug, I suppose?)
#if 0
getch();
#endif
// add new element
echo();
printw("Surname: ");
scanw("%15s", osp->surn);
printw("Name: ");
scanw("%15s", osp->name);
noecho();
h = fopen("archivio", "w");
osp = first;
while (osp != NULL) {
fwrite(osp->surn, sizeof osp->surn, 1, h);
fwrite(osp->name, sizeof osp->name, 1, h);
osp = osp->next;
}
fclose(h);
return 0;
}
struct pat *
make_structure(void)
{
struct pat *a;
a = malloc(sizeof(struct pat));
// NOTE: do this for good measure
a->next = NULL;
return (a);
}
Dưới đây là phiên bản tổng quát hơn có thể cung cấp cho bạn một số ý tưởng khi bạn mở rộng khả năng của chương trình :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
struct pat {
char surn[16];
char name[16];
struct pat *next;
};
static FILE *h;
static struct pat *osp;
static struct pat *first;
static struct pat *prev;
void read_archive(const char *file);
void add_new_elements(void);
void write_archive(const char *file);
struct pat *make_structure(void);
void add_to_list(struct pat *pat);
int
main()
{
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
clear();
read_archive("archivio");
// NOTE: this just chews the first character (debug, I suppose?)
#if 0
getch();
#endif
// NOTE: instead of just automatically adding new elements, this might
// be replaced with a menu, such as:
// Enter Operation:
// (1) Add new names
// (2) Calculate statistics
// (3) Backup database
add_new_elements();
write_archive("archivio");
return 0;
}
// read_archive -- read in archive
void
read_archive(const char *file)
{
int rlen;
h = fopen(file, "r");
if (h == NULL)
printw("Archivio inesistente\n");
else {
while (1) {
osp = make_structure();
// leave early on EOF or badly formed entry
rlen = fread(osp->surn, sizeof osp->surn, 1, h);
if (rlen != 1)
break;
// leave early on EOF or badly formed entry
fread(osp->name, sizeof osp->name, 1, h);
if (rlen != 1)
break;
printw("Cognome: %s\tNome: %s\n", osp->surn, osp->name);
add_to_list(osp);
}
// NOTE: this is _always_ for EOF or bad entry, so free it
free(osp);
fclose(h);
}
}
// add_new_elements -- prompt for new elements
void
add_new_elements(void)
{
echo();
while (1) {
osp = make_structure();
printw("Surname: ");
osp->surn[0] = 0;
scanw("%15s", osp->surn);
if (osp->surn[0] == 0)
break;
printw("Name: ");
osp->name[0] = 0;
scanw("%15s", osp->name);
if (osp->name[0] == 0)
break;
add_to_list(osp);
}
noecho();
free(osp);
}
// write_archive -- write out archive
void
write_archive(const char *file)
{
h = fopen(file, "w");
for (osp = first; osp != NULL; osp = osp->next) {
fwrite(osp->surn, sizeof osp->surn, 1, h);
fwrite(osp->name, sizeof osp->name, 1, h);
}
fclose(h);
}
struct pat *
make_structure(void)
{
struct pat *a;
a = malloc(sizeof(struct pat));
// NOTE: do this for good measure
a->next = NULL;
return (a);
}
void
add_to_list(struct pat *pat)
{
if (first == NULL)
first = pat;
else
prev->next = pat;
prev = pat;
}
UPDATE:
tôi vẫn cố gắng tìm ra nguyên nhân của sự thất bại của tôi
Tôi không debug/đơn bước mã ban đầu của bạn bởi vì tôi nghĩ rằng logic danh sách liên kết của bạn sẽ cần sửa chữa và tôi muốn đến đó nhanh chóng. Tuy nhiên, sau khi tôi xem xét nó, logic vẫn ổn. Dựa trên phân tích phỏng đoán tốt nhất của tôi, lỗi có thể xảy ra là feof
mà tôi đã thay đổi để kiểm tra độ dài trên fread
.
Tất nhiên tôi sẽ tổ chức tốt hơn các chương trình sử dụng các hàm
Tôi cho rằng bạn sẽ. Sự phân chia trong chương trình thứ hai là nhiều hơn của một công cụ giảng dạy để làm rõ và minh họa một nguyên tắc và là không phải là một phê bình về tính mô-đun.
Trong mã ban đầu của bạn, bạn có để thêm bản ghi mới vì osp
trống nhưng đã được liên kết trong danh sách. Một cách lỏng lẻo, một kỷ lục "zombie", nếu bạn muốn.
Tức là danh sách có mục nhập được liên kết trong trước nó đã được điền và xác thực. Nói cách khác, sau vòng lặp đọc, nhưng trước khi người dùng được nhắc về mục nhập mới, danh sách có thể bị coi là không đúng định dạng (nghĩa là vi phạm "nhỏ" lập trình hợp đồng hoặc "thiết kế theo hợp đồng") .
Chức năng tách trong chương trình thứ hai chỉ là nhấn mạnh điều này. Đặc biệt, bằng cách di chuyển vòng lặp đọc đến một hàm riêng biệt, nó minh họa/thực thi thiết kế theo hợp đồng.
Tức là, khi nhập cảnh, danh sách là toàn bộ và được hình thành tốt [mặc dù, trống]. Khi trả lại, nó hoặc là trống rỗng [nếu tệp đầu vào không không phải là tồn tại] hoặc chỉ có các bản ghi hoàn chỉnh/được hoàn thành trong đó.
Trong chương trình thứ hai, mục nhập một phần/không đúng định dạng là không bao giờ được liên kết. add_to_list
luôn được thực hiện lần cuối [chỉ cho toàn bộ/toàn bộ bản ghi].
Vì vậy, đối với cả hai số read_archive
và add_new_entries
, khi chúng được gọi, cả hai đều được cung cấp danh sách toàn bộ/hoàn chỉnh chỉ với các bản ghi hợp lệ hoàn chỉnh. Đó là "hợp đồng" với chúng.
Và để hoàn thành một phần của "hợp đồng", các chức năng này phải để mọi thứ theo cùng một cách, duy trì tính toàn vẹn của danh sách khi thoát. Đó là 'hợp đồng' của các chức năng với thế giới bên ngoài
CẬP NHẬT # 2:
tha cho tôi cho Cựu Ước, nhưng bạn có thể gợi ý cho tôi một IDE tốt cho C - C++ hoạt động tốt với Debian/GNU Linux?
Tôi có thể không phải là người tốt nhất khuyên bạn về điều này vì tôi không sử dụng. Tôi đã viết C rất lâu trước khi chúng tồn tại, vì vậy tôi đã phát triển bộ công cụ của riêng mình, nó mạnh mẽ hơn nhiều so với bất kỳ IDE nào mà tôi từng thấy. Ngoài ra, khi tôi nhìn vào chúng, tôi không bao giờ có thể tìm được cách để kết nối cả hai.
tôi đang ở nhà với Code :: Blocks, nhưng tiếc là cái gọi là đêm xây dựng là lỗi và tai nạn rất thường xuyên
Nếu bạn đang ở nhà với CodeBlocks, nhưng đêm xây dựng là lỗi, có lẽ giải pháp đơn giản là chuyển bản cập nhật của bạn sang cây "ổn định", nếu có thể. Đó có thể là "câu trả lời ngắn" tốt nhất.
(tiện ích hoàn thành mã rất hữu ích nhưng tôi không được gõ str ..., nếu không nó bị đóng băng) và điều đó rất bực bội!
Có thể bạn có thể kiểm tra cơ sở dữ liệu lỗi và xem liệu sự cố bạn gặp phải có báo cáo lỗi đã biết hay không. Nếu không, bạn có thể/nên nộp một.
Tôi đã cài đặt codeblocks
. Nó trông sạch sẽ và đơn giản, đủ. Tôi cũng đã cài đặt eclipse
và xem kdevelop
. Từ một số trang web, nhật thực được đánh dấu cao, với netbeans
đóng một giây thứ hai
Tôi đã cố gắng sử dụng chúng trên tệp nguồn tôi đã nằm xung quanh được xây dựng bằng Makefile. codeblocks đủ trực quan để tôi có thể làm nó nhanh chóng. Tôi gặp rắc rối với những người khác. eclipse ban đầu được thiết kế bởi IBM để sử dụng nội bộ và sau đó được phát hành như một dịch vụ công cộng. Nó được hỗ trợ tốt và trưởng thành.
Tôi đã chạy eclipse mà không CDT, nhưng một khi tôi nói thêm rằng, eclipse
được phiếu bầu của tôi, bởi vì nó dường như có đủ các tính năng kiểm soát tất cả những gì tôi sẽ để phàn nàn về dưới đây ;-)
Một IDE là một lựa chọn hơi cá nhân [trừ khi công ty bạn ủy quyền một], vì vậy bạn nên sử dụng những gì bạn thích. Nói cách khác, hãy thử một số và xem những tính năng nào họ có và cách chúng hoạt động. Đây là trang liệt kê một số: https://en.wikipedia.org/wiki/Comparison_of_integrated_development_environments
Khi chọn IDE, bạn phải xem xét các tính năng "được sử dụng nhiều nhất". Điều thường xuyên nhất bạn làm là cuộn xung quanh trong tệp nguồn. Vì vậy, trình chỉnh sửa phải hỗ trợ bí danh hjkl
cho các phím mũi tên, chẳng hạn như vi
. Có để di chuyển bàn tay phải của bạn qua các phím mũi tên và trở lại làm chậm những thứ xuống rất nhiều mà nó không khởi động.
sử dụng nhật thực gvim
[đồ họa vim
], vì vậy đó là dấu cộng.
Tôi là không một người hâm mộ chỉnh sửa với một số cửa sổ soạn thảo WYSIWYG đơn giản chỉ có các tính năng tìm kiếm/thay thế thô. Tương tự như vậy, vim
cho phép tìm kiếm regex chỉ đơn giản bằng cách gõ /
, vì vậy một lần nữa, các hoạt động phổ biến nhất là "trong tầm tay của bạn"
tôi không sử dụng [cũng không muốn] autocompletion tính năng. Khi tôi đã thử họ, họ thường xuyên nhận được những điều sai trái và phải mất nhiều thời gian để backspace hơn những gì họ đã làm. Tôi là một người đánh máy rất nhanh.
Tôi cũng tắt tính năng tô sáng và tô màu cú pháp của nguồn. Khi nhập mã nguồn, màu sắc thay đổi chỉ với mỗi ký tự được nhập vì biên tập viên cho rằng Tôi đang nhập (ví dụ: tôi đang nhập nhận xét, nhưng nó cho rằng đó là mã, v.v.) mất tập trung.
Ngoài ra, khi xem kết quả cuối cùng, tôi thấy rằng kết quả được tô màu là "quá bận" (tức là tôi cần phải lọc thêm thông tin) thay vì điều gì đó giúp tôi xem những gì tôi cần xem.
Tôi khá khăng khăng về thụt lề, chia nhỏ các khối mã dài với các dòng trống để cải thiện khả năng đọc. Và, tất nhiên, ý kiến tốt. Đối với tôi, chúng quan trọng hơn nhiều so với màu. Tôi có một công cụ tùy chỉnh cho thụt lề [Như bạn có thể nhớ lại, khi tôi đăng mã ở trên, nó đã được reindented vì tôi chạy nó thông qua công cụ của tôi trước khi đăng bài.
Một tính năng khác là trình gỡ lỗi đồ họa. Nó có đầy đủ tính năng không? Ví dụ: ddd
là trình bao bọc đồ họa xung quanh [rất mạnh] gdb
.ddd
cung cấp trình bao bọc đồ họa và cửa sổ cho những thứ thông thường nhưng vẫn cho phép cửa sổ văn bản trực tiếp hiển thị lời nhắc gdb
, vì vậy bạn có thể nhập thủ công các lệnh nâng cao hơn (ví dụ: watch symbol
).
IDE có thể mở rộng không? Bạn có thể thêm các plugin không? Bạn có thể dễ dàng thêm/tạo của riêng bạn?
IDE sử dụng hệ thống kiểm soát mã nguồn nào? Tôi đã sử dụng nhiều trong nhiều năm và, hiện tại, được bán hoàn toàn trên git
. Vì vậy, nếu IDE không hỗ trợ git
, nó không phải là khởi động.
Cần lưu ý rằng git
có nên tính năng nhiều hơn những gì họ có thể không được chứa trong một GUI. Vì vậy, các công cụ thực sự mạnh mẽ sử dụng một công cụ dòng lệnh trong một cửa sổ thiết bị đầu cuối.
IDE của tôi? Một số cửa sổ xterm
, vi
, git
và bộ công cụ của tôi [hiện tại là 250.000 dòng của perl
tập lệnh ;-)] IDE có buộc bạn thực hiện theo cách của nó không? Việc nhập/xuất cấu hình, vv dễ dàng như thế nào với các công cụ và IDE bên ngoài khác?
Tôi có một kịch bản xây dựng rất mạnh mẽ về thiết kế của riêng tôi. Vì vậy, tôi muốn IDE, khi tôi nhấp vào nút "xây dựng" để không làm bất cứ điều gì bình thường, nhưng chuyển quyền kiểm soát sang kịch bản xây dựng của tôi. Tương tự như vậy cho bất kỳ hoạt động nào khác mà IDE cung cấp là.
IDE có thể di động và có sẵn trên tất cả các nền tảng chính: linux, OSX và windows không? Trong quá khứ, đó là một lý do khác mà tôi tránh xa các IDE. Chúng sẽ chỉ có sẵn trên một nền tảng. Hoặc, kể từ khi tôi đang làm công việc tư vấn, tôi sẽ đi vào một môi trường mà sẽ không cho phép cài đặt/sử dụng IDE vì chính sách [sysadmin].
Bạn nên đóng các tệp, đặc biệt là trước khi bạn mở lại chúng. (Điều này không nên khắc phục vấn đề của bạn, chỉ cần một mẹo.) – Jashaszun
'scanw ("% s ", osp-> name);' cần giới hạn để tránh đọc quá nhiều ký tự. Với 'name [16]', có thể một cái gì đó như 'scanw ("% 15s ", osp-> name);' – chux
BTW: tên và họ cuối cùng có dấu cách trong đó làm cho '"% s "' không đầy đủ. – chux