Byłaś tak blisko, nie jestem nawet pewien, co było prawdziwą przyczyną awarii, gdyż z pierwszego cięcia, po prostu zastosować [większość] rozwiązywanych je przez innych i dostał program roboczy .
Mimo że zadziałało, odkryłem, że sposób, w jaki robiłeś "jedno z wyprzedzeniem" make_structure
, jest mniej elastyczny, gdy rozszerzasz program, by robić inne rzeczy.
Na przykład, masz zawieszony rekord "widmowy", jeśli zamiast dodawać nowy rekord, zdecydujesz się na , a nie dodać nowy rekord, ale zrób statystyki lub manipuluj nimi.
Stworzyłem więc drugą wersję programu, który ma więcej izolacji i ogólności.
Oto minimalnie zmieniona wersja [proszę wybaczyć oczyszczanie stylu nieodpłatne]:
#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);
}
Oto bardziej uogólniona wersja, która może dać Ci kilka pomysłów, kiedy rozszerzyć możliwości programu :
#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:
ja wciąż próbuje dowiedzieć się powód mojego niepowodzenia
ja nie debug/jednoetapowy oryginalnego kodu, bo myślałem, że połączone lista logika wymagałoby naprawy i chciałem do tego szybko dojść. Jednak po jego przejrzeniu logika była w porządku. Opierając się na mojej najlepszej analizie domyślnej, prawdopodobną porażką był feof
, który już zmieniłem na sprawdzanie długości na fread
.
Oczywiście miałem zamiar zorganizować lepszy program wykorzystujący funkcje
Przypuszczałem, że tak. Podział w drugim programie był raczej narzędziem dydaktycznym do wyjaśnienia i zilustrowania zasady i był krytyką modułowości.
W swoim oryginalnym kodzie użytkownik miał, aby dodać nowy rekord, ponieważ osp
był pusty, ale został już połączony z listą. Luźno, rekord "zombie", jeśli chcesz.
Oznacza to, że na liście był wpis związany przed został wypełniony i zatwierdzony. Innymi słowy, po pętli odczytu, ale zanim użytkownik zostanie poproszony o wprowadzenie nowego wpisu, lista może zostać uznana za zniekształconą (tj. [Małe] naruszenie zasad "programowania kontraktowego" lub "zasady projektowania po zawarciu umowy") .
Funkcja podziału w drugim programie miała właśnie to podkreślić. W szczególności, przesuwając pętlę odczytu do oddzielnej funkcji, zilustrowano/wzmocniono projekt po kontrakcie.
Oznacza to, że po wejściu lista jest pełna i dobrze sformułowana [aczkolwiek pusta]. Po powrocie jest puste (jeśli plik wejściowy ma wartość , a nie) lub zawiera tylko dobrze utworzone/kompletne rekordy.
W drugim programie wpis częściowy/zniekształcony to nigdy nie jest powiązany z. add_to_list
jest zawsze wykonywany jako ostatni [tylko dla całego/kompletnego rekordu].
Tak, zarówno dla read_archive
, jak i add_new_entries
, gdy są wywoływane, otrzymują one pełną/kompletną listę z poprawnymi, w pełni uformowanymi rekordami. To jest "kontrakt" z im.
I aby wypełnić swoją część "umowy", funkcje te muszą pozostawiać rzeczy w ten sam sposób, zachowując integralność listy po wyjściu. Że jest "umowa" funkcji do świata zewnętrznego
Aktualizacja # 2:
wybaczcie za OT, ale można zasugerować mi dobre IDE dla C - C++ który działa dobrze z systemem Debian/GNU Linux?
Mogę nie być najlepszą osobą, która doradziłaby ci w tej sprawie, ponieważ ja jej nie używam. Pisałem C na długo przed ich istnieniem, więc opracowałem własny zestaw narzędzi, który jest o wiele potężniejszy niż jakikolwiek IDE jaki widziałem. Ponadto, gdy na nie spojrzałem, nigdy nie mogłem znaleźć sposobu na połączenie tych dwóch elementów.
jestem w domu z Code :: Blocks, ale niestety tzw nightly zbudować ma błędy i awarie bardzo często
Jeśli jesteś w domu z CodeBlocks, ale nightly build jest buggy, być może prostym rozwiązaniem jest zamiana aktualizacji na "stabilne" drzewo, jeśli to możliwe. To może być najlepsza "krótka odpowiedź".
(narzędzie do uzupełniania kodu jest bardzo przydatne, ale nie wolno mi wpisywać str ..., w przeciwnym razie zawiesza się), a to bardzo frustrujące!
Być może możesz sprawdzić bazę danych błędów i sprawdzić, czy napotkane problemy nie zawierają znanych błędów. Jeśli nie, możesz/powinieneś złożyć jeden.
Zainstalowałem codeblocks
. Wygląda na to, że jest czysty i wystarczająco prosty. Zainstalowałem także eclipse
i przyjrzałem się kdevelop
. Z kilku stron internetowych, eclipse dostaje wysokie oceny, z netbeans
o blisko sekundę
Próbowałem użyć ich na pliku źródłowym, który leżałem wokół, który został zbudowany z pliku Makefile. blockblocks był na tyle intuicyjny, że mogłem go szybko uruchomić. Miałem więcej kłopotów z innymi. Zaćmienie zostało pierwotnie zaprojektowane przez IBM do użytku wewnętrznego, a następnie wydane jako usługa publiczna. Jest dobrze wspierany i dojrzały.
I został uruchomiony zaćmienie bez CDT, ale raz dodać, że eclipse
dostaje mój głos, ponieważ wydaje się mieć wystarczająco dużo możliwości kontrolowania wszystkich co zamierzam narzekać o poniżej ;-)
IDE to nieco osobisty wybór [chyba że firma go wymaga], więc powinieneś używać tego, co lubisz. Innymi słowy, spróbuj i sprawdź, jakie funkcje mają i jak działają. Oto strona, która zawiera listę niektórych: https://en.wikipedia.org/wiki/Comparison_of_integrated_development_environments
Wybierając IDE, musisz spojrzeć na "najczęściej używane" funkcje. Najczęstszą rzeczą, którą robisz, jest przewijanie w pliku źródłowym. Tak więc edytor powinien obsługiwać aliasy hjkl
klawiszy strzałek, na przykład vi
. Konieczność przesunięcia prawej ręki na klawisze strzałek i spowolnienie powoduje spowolnienie pracy tak, że nie można jej uruchomić.
eclipse używa gvim
[graficzna vim
], więc to jest plus.
Nie jestem nie fanem edycji z prostym edytorem WYSIWYG, który ma tylko proste funkcje wyszukiwania/zamiany. Podobnie vim
umożliwia przeszukiwanie regex prostu wpisując /
, więc ponownie, najczęstsze operacje są „na wyciągnięcie ręki”
nie używam [ani chcą] funkcje autouzupełniania. Kiedy ich wypróbowałem, często popełniają błędy, a cofnięcie się do tego, co zrobili, zajmuje więcej czasu. Jestem bardzo szybką maszynistką.
Wyłączyłem także podświetlanie składni i kolorowanie źródła. Gdy wprowadzasz kod źródłowy, kolory zmieniają się prawie z każdym wprowadzonym znakiem, ponieważ myślisz, że redaktor pisze (np. Piszę komentarz, ale myśli, że to kod, itp.). Stwierdziłem, że rozpraszać.
Ponadto, patrząc na końcowy wynik, stwierdzam, że kolorowany wynik jest "zbyt zajęty" (tj. Więcej informacji muszę filtrować), a nie coś, co pomaga mi zobaczyć, co muszę zobaczyć.
Jestem dość uporczywy wobec wcięć, dzielenia długich bloków kodu z pustymi liniami, aby poprawić czytelność. I, oczywiście, dobre komentarze. Dla mnie są one o wiele ważniejsze niż kolorystyka. Mam własne narzędzie do wcięcia [Jak możesz sobie przypomnieć, kiedy opublikowałem powyższy kod, został on ponownie uruchomiony, ponieważ przeprowadziłem go przez moje narzędzie przed opublikowaniem.
Kolejną funkcją jest graficzny debugger. Czy jest w pełni funkcjonalny? Na przykład: ddd
jest graficznym opakowaniem wokół [bardzo potężnego] gdb
.ddd
zapewnia graficzne opakowanie i okna dla zwykłych rzeczy, ale nadal pozwala na bezpośrednie okno tekstowe dla zapytania gdb
, dzięki czemu można ręcznie wpisać bardziej zaawansowane polecenia (np. watch symbol
).
Czy IDE można rozszerzyć? Czy możesz dodać wtyczki? Czy możesz łatwo dodać/stworzyć swój własny?
Z jakiego systemu kontroli kodu źródłowego korzysta IDE? Przez wiele lat używałem wielu i teraz jestem całkowicie sprzedany pod numerem git
. Tak więc, jeśli IDE nie obsługuje git
, to nie jest uruchamianie.
Należy zauważyć, że git
ma więc wiele funkcji niż mogą nieznajdować się w GUI. Tak więc naprawdę potężne rzeczy używają narzędzia wiersza poleceń w oknie terminala.
Moje IDE? Kilka okien: xterm
Windows, vi
, git
i mój pakiet narzędzi (obecnie 250 000 wierszy skryptów perl
;-)] Czy IDE zmusza Cię do robienia rzeczy po swojemu? Jak łatwo jest importować/eksportować konfigurację itp. Do innych zewnętrznych narzędzi i IDE?
Mam bardzo potężny skrypt budujący mój własny projekt. Tak, chciałbym IDE, aby po kliknięciu przycisku "kompilacji" na nie zrobić, co normalnie zrobić, ale przełączyć kontrolę na mój skrypt budowania. Podobnie jak w przypadku innejinnej operacji, którą IDE ma do zaoferowania.
Czy IDE jest przenośny i dostępny na wszystkich głównych platformach: Linux, OSX i Windows? W przeszłości był to kolejny powód, dla którego uciekałem przed IDE. Będą dostępne tylko na jednej platformie. Lub, od kiedy robiłem konsultacje, chodziłem do środowiska, które nie pozwoliłoby zainstalować/używać IDE z powodu zasad [sysadmin].
Powinieneś zamknąć pliki, szczególnie przed ich ponownym otwarciem. (To nie powinno naprawiać twojego problemu, tylko napiwek.) – Jashaszun
'scanw ("% s ", osp-> name);' potrzebuje limitu, aby uniknąć czytania zbyt wielu znaków. Z 'name [16]', może coś takiego jak 'scanw ("% 15s ", osp-> name);' – chux
BTW: imiona i nazwiska mają jakieś spacje, czyniąc '"% s "' niewystarczającym. – chux