Dlaczego ten program jest błędnie odrzucany przez trzy kompilatory C ++?


468

Mam trudności z kompilacją napisanego przeze mnie programu C ++.

Ten program jest bardzo prosty i, zgodnie z moją najlepszą wiedzą, jest zgodny ze wszystkimi zasadami określonymi w standardzie C ++. Dla pewności przeczytałem w całości ISO / IEC 14882: 2003.

Program jest następujący:

wprowadź opis zdjęcia tutaj

Oto dane wyjściowe, które otrzymałem podczas próby skompilowania tego programu za pomocą Visual C ++ 2010:

c:\dev>cl /nologo helloworld.png
cl : Command line warning D9024 : unrecognized source file type 'helloworld.png', object file assumed
helloworld.png : fatal error LNK1107: invalid or corrupt file: cannot read at 0x5172

Zawstydzony, wypróbowałem g ++ 4.5.2, ale było to równie nieprzydatne:

c:\dev>g++ helloworld.png
helloworld.png: file not recognized: File format not recognized
collect2: ld returned 1 exit status

Uznałem, że Clang (wersja 3.0 trunk 127530) musi działać, ponieważ jest tak bardzo chwalony za zgodność ze standardami. Niestety nie dał mi nawet jednego z ładnych, podświetlonych komunikatów o błędach:

c:\dev>clang++ helloworld.png
helloworld.png: file not recognized: File format not recognized
collect2: ld returned 1 exit status
clang++: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)

Szczerze mówiąc, tak naprawdę nie wiem, co oznacza jakikolwiek z tych komunikatów o błędach.

Wiele innych programów w C ++ ma pliki źródłowe z rozszerzeniem .cpp , więc pomyślałem, że może potrzebuję zmienić nazwę mojego pliku. Zmieniłem jego nazwę na helloworld.cpp , ale to nie pomogło. Myślę, że w Clang jest bardzo poważny błąd, ponieważ kiedy próbowałem go użyć do skompilowania programu o zmienionej nazwie, wywrócił się i wydrukował „84 ostrzeżenia i 20 wygenerowanych błędów”. i sprawił, że mój komputer wydał duży dźwięk!

Co zrobiłem tutaj źle? Czy przegapiłem jakąś krytyczną część standardu C ++? A może wszystkie trzy kompilatory są tak po prostu zepsute, że nie mogą skompilować tego prostego programu?

Odpowiedzi:


173

W normie § 2.1.1 określa:

Znaki fizycznego pliku źródłowego są odwzorowywane, w sposób zdefiniowany w implementacji, na podstawowy zestaw znaków źródłowych (wprowadzając znaki nowej linii dla wskaźników końca linii), jeśli to konieczne.

Twój kompilator nie obsługuje tego formatu (aka nie może zamapować go na podstawowy zestaw znaków źródłowych ), więc nie może przejść do dalszych etapów przetwarzania, stąd błąd. Jest całkowicie możliwe, że Twój kompilator obsługuje mapowanie z obrazu na podstawowy źródłowy zestaw znaków, ale nie jest to wymagane.

Ponieważ to odwzorowanie jest zdefiniowane w ramach implementacji, należy zapoznać się z dokumentacją implementacji, aby zobaczyć obsługiwane formaty plików. Zazwyczaj każdy główny dostawca kompilatora obsługuje pliki tekstowe (zdefiniowane kanonicznie): każdy plik utworzony przez edytor tekstowy, zwykle ciąg znaków.


Zauważ, że standard C ++ opiera się na standardzie C (§1.1 / 2), a standard C (99) mówi w §1.2:

Niniejszy standard międzynarodowy nie określa
- mechanizmu, za pomocą którego programy C są przekształcane do wykorzystania przez system przetwarzania danych;
- mechanizm, za pomocą którego programy C są wywoływane do wykorzystania przez system przetwarzania danych;
- mechanizm, za pomocą którego dane wejściowe są przekształcane do wykorzystania przez program w C;

Zatem znowu traktowanie plików źródłowych jest czymś, co należy znaleźć w dokumentacji kompilatora.


23
Myślę, że to zdanie jest co najwyżej dwuznaczne. Słownik Merriam-Webster mówi, że tekst jest oryginalnym słowem i formą dzieła pisanego lub drukowanego lub dzieła zawierającego taki tekst . Ten plik źródłowy wyraźnie mieści się w tej definicji. Czy uważasz, że powinienem złożyć raport o defektach w grupie roboczej Core Language?
James McNellis,

15
O; Zupełnie zapomniałem przeczytać wszystkie odnośne dokumenty. Myślę, że ten akapit został wyjęty z kontekstu, więc przejdę do całości ISO / IEC 9899: 1990 i opublikuję ją tutaj, gdy w pełni ją zrozumiem.
James McNellis,



211

Twoje <i >, (i ), {i }wydają się nie pasować bardzo dobrze; Spróbuj narysować je lepiej.


44
Chociaż nie doceniam tego, że żartujesz sobie z mojego pisma odręcznego, może to być prawdziwy problem i wyjaśniłbym błąd, który pojawia się, gdy próbuję skompilować zmienioną nazwę helloworld.cpp z Visual C ++: „błąd krytyczny C1004: nieoczekiwany koniec- plik znaleziony „Spróbuję ponownie i wkrótce zgłoś się. Dzięki!
James McNellis

37
@James upewnij się, że wyłączyłeś wszystkie optymalizacje png. ułatwia debugowanie.
wilhelmtell

5
@James: „nieoczekiwany koniec pliku” prawie na pewno oznacza, }że przyczyną problemu jest twój . Spróbuj skupić się na dopasowaniu tego do{
Carson63000,

156

Możesz wypróbować następujący skrypt Pythona. Pamiętaj, że musisz zainstalować PIL i Pytesser .

from pytesser import *
image = Image.open('helloworld.png')  # Open image object using PIL
print image_to_string(image)     # Run tesseract.exe on image

Aby z niego skorzystać:

python script.py > helloworld.cpp; g++ helloworld.cpp

110

Zapomniałeś użyć Comic Sans jako czcionki, dlatego się myli.


73
Niestety, jest to jedyna czcionka obsługiwana przez moją rękę. Byłoby to bardzo smutne, gdybym nie mógł programować w C ++ z tego powodu. Czy uważasz, że Java obsługuje tę czcionkę?
James McNellis,

8
Będziesz potrzebować Komiksów, jeśli i tak będziesz rysować komiksy, więc powinieneś poważnie rozważyć ulepszenie rąk.
sharptooth

8
C ++ wymaga całorocznego szkolenia w zakresie kaligrafii. Jeśli nie masz czasu, wypróbuj Visual Basic lub po prostu binarny kod maszynowy (wtedy musisz tylko uzyskać zera i jedynki).
Frank Osterfeld

1
@Frank C ++ 0x §42.1 / 1 określa „Wszystkie ciągi muszą być w stylu gotyckim”.
Mateen Ulhaq,

75

Nie widzę nowej linii po tym ostatnim klamrze.

Jak wiecie: „Jeśli plik źródłowy, który nie jest pusty, nie kończy się znakiem nowej linii, ... zachowanie jest niezdefiniowane”.


16
Hmmm. Na szczęście ta śmieszna zasada została usunięta w C ++ 0x. To powiedziawszy, jak można zakończyć taki plik nową linią? Myślałem, że zostawiłem wystarczającą ilość miejsca na końcu tekstu (jeśli zaznaczysz plik źródłowy, powinieneś zobaczyć dodatkowe miejsce, które zostawiłem). Dziękuję za wskazówkę!
James McNellis,

8
Jeśli nie masz wystarczająco dużo białych znaków, mogę spróbować skompilować go w moim systemie. Mam cztery monitory, więc mogłem spróbować skompilować z mojego najbardziej lewego.
Tin Man

74

Ten program jest prawidłowy - nie mogę znaleźć błędów.

Domyślam się, że masz wirusa na swoim komputerze. Najlepiej byłoby sformatować dysk i ponownie zainstalować system operacyjny.

Poinformuj nas, jak to działa, lub jeśli potrzebujesz pomocy w ponownej instalacji.

Nienawidzę wirusów.


17
Tak, spróbuj zainstalować Linuksa. Winię Windows za twój problem.
Raedwald,

62

Odkryłem, że pomaga nie pisać kodu na szybie mojego monitora za pomocą magicznego markera, nawet jeśli wygląda ładnie, gdy jest naprawdę czarny. Ekran zapełnia się zbyt szybko, a następnie ludzie, którzy dają mi czysty monitor, dzwonią do mnie co tydzień.

Kilku moich pracowników (jestem kierownikiem) włamuje się, żeby kupić mi jeden z tych czerwonych komputerów z gałkami. Powiedzieli, że nie będę potrzebować markerów i sam mogę wyczyścić ekran, gdy jest pełny, ale muszę go ostrożnie potrząsać. Podejrzewałem, że jest delikatny.

Dlatego zatrudniam mądrych ludzi.


2
Wacom Cintiq jest znacznie bardziej odpowiedni dla menedżera. Jest drogi i sprawia, że ​​czujesz się naprawdę ważny. Każdy projektant graficzny w Twojej firmie będzie miał znacznie niższy status i dlatego powinien używać monitorów EGA. Dozorcy powinni używać monitorów CGA. Programiści powinni używać używanych monochromatycznych terminali.
Steve314,

7
Przez długi czas miałem monitor „Life Like”. To było tak realistyczne, że przysięgasz, że wygaszacz ekranu pływania ryb był prawdziwy, a mały nurek wyglądał, jakby pływał. Moczyłem rękę, próbując wyciągnąć skrzynię skarbów z dołu, to było takie prawdziwe. Jedynym problemem było to, że wygaszacz ekranu był cały czas włączony, a realistyczne, bulgotane dźwięki utrudniały słyszenie. Aha, i powiedzieli na potrzeby konserwacji, że muszę codziennie spryskiwać coś w górnej części monitora, inaczej wygaszacz ekranu przestanie działać. Zrobił to raz, a chłopak, zapach dwa dni później był naprawdę realistyczny.
Tin Man

59

File format not recognizedMusisz poprawnie sformatować plik. Oznacza to użycie odpowiednich kolorów i czcionek dla twojego kodu. Zobacz szczegółowe dokumentacje dla każdego kompilatora, ponieważ te kolory różnią się w zależności od kompilatora;)


14
Och, to ma sens ... Mam pudełko 96 kredek, więc jestem pewien, że mam właściwy kolor pierwszego planu. Jutro wezmę kolorowy papier budowlany i wypróbuję go na innym kolorze papieru.
James McNellis,

3
Dla bezpieczeństwa lepiej zaopatrzyć się w kredki i farby na bazie oleju. Powszechnie wiadomo, że C ++ ma być bardzo trudnym językiem do prawidłowego sformatowania.
helloworld922,

Tak, i nie zapomnij użyć znacznika podświetlania.
sharptooth

6
@sharptooth - podświetlanie składni jest funkcją IDE - nie musisz tego robić ręcznie. Upewnij się więc, że masz ramię robota pasujące do tego wyróżniającego znacznika.
Steve314,

56

Zapomniałeś preprocesora. Spróbuj tego:

pngtopnm helloworld.png | ocrad | g++ -x 'c++' -

8
O! Myślałem, że preprocesor został dołączony do kompilatora! Spróbuję znaleźć preprocesor, który działa na moim laptopie z systemem Windows.
James McNellis,

3
@James McNellis: Preprocesor nie jest programem, to sprzęt, który wygląda jak marker wyróżniający - przesuwasz go nad tekstem i jest on wstępnie przetwarzany.
sharptooth

49

Czy napisałeś program ręcznie, a następnie zeskanowałeś go do komputera? To właśnie sugeruje „helloworld.png”. W takim przypadku należy pamiętać, że standard C ++ (nawet w jego najnowszym wydaniu) nie wymaga obecności optycznego rozpoznawania znaków i niestety nie jest zawarty jako opcjonalna funkcja w żadnym obecnym kompilatorze.

Możesz rozważyć przeniesienie grafiki do formatu tekstowego. Można użyć dowolnego edytora zwykłego tekstu; użycie edytora tekstu, mimo że jest w stanie wygenerować ładny wydruk, najprawdopodobniej spowoduje taki sam błąd, jak podczas próby skanowania.

Jeśli jesteś naprawdę żądny przygód, możesz spróbować napisać kod w edytorze tekstu. Wydrukuj go, najlepiej używając czcionki takiej jak OCR-A . Następnie weź wydruk i zeskanuj go ponownie. Skanowanie można następnie uruchomić za pomocą pakietu OCR innej firmy w celu wygenerowania formularza tekstowego. Formularz tekstowy można następnie skompilować przy użyciu jednego z wielu standardowych kompilatorów.

Uważaj jednak na wielki koszt papieru, który poniesie on w fazie debugowania.


Dylemat kurczaka i jajka: Czy można napisać kod C ++ dla oprogramowania OCR i skompilować go bez OCR?
jweyrich,

5
No cóż, używasz assemblera do oryginalnego OCR.
Kevin Lacquement

@jweyrich - Myślę, że najpierw musisz uruchomić C ++ / OCR ze swoim łańcuchem narzędzi asm / OCR.
Michael Burr


46

Narysuj dołączenie poniżej, aby skompilować:

#include <ChuckNorris>

Słyszałem, że potrafi skompilować błędy składniowe ...


46
Ja osobiście wolę #include <JonSkeet>.
Icode4food

40

Niestety wybrałeś trzy kompilatory, które obsługują wiele języków, nie tylko C ++. Wszyscy muszą zgadnąć, jakiego języka programowania użyłeś. Jak zapewne już wiesz, format PNG jest odpowiedni dla wszystkich języków programowania, nie tylko C ++.

Zwykle kompilator może sam zrozumieć język. Na przykład, jeśli PNG jest oczywiście rysowany kredkami, kompilator będzie wiedział, że zawiera Visual Basic. Jeśli wygląda na to, że jest narysowany ołówkiem mechanicznym, łatwo jest rozpoznać inżyniera w pracy, pisząc kod FORTRAN.

W tym przypadku drugi krok nie pomaga kompilatorowi. C i C ++ po prostu wyglądają zbyt podobnie, aż do #include. Dlatego musisz pomóc kompilatorowi w wyborze języka. Teraz możesz użyć niestandardowych środków. Na przykład kompilator Visual Studio akceptuje argumenty wiersza polecenia / TC i / TP lub można użyć opcji „Kompiluj jako: C ++” w pliku projektu. GCC i CLang mają własne mechanizmy, których nie znam.

Dlatego zaleciłbym użycie standardowej metody zamiast poinformowania kompilatora, że ​​poniższy kod jest w C ++. Jak już odkryłeś, kompilatory C ++ są bardzo wybredne w kwestii tego, co akceptują. Dlatego standardowym sposobem identyfikacji C ++ jest dodawanie przez programistów zastraszających ich kodu C ++. Na przykład poniższy wiersz wyjaśni Twojemu kompilatorowi, że to, co następuje, to C ++ (i lepiej skompiluje go bez skarg).

// To the compiler: I know where you are installed. No funny games, capice?

10
Myślałem, że #pragmato właściwy sposób, aby „dostać wiadomość” do kompilatora?
Lew Biskup

33

Spróbuj tego:

Czy widzisz dinozaura w promie kosmicznym?


4
Myślę, że jest literówka - powinna być endl(L), a nie end1(jedna). Ale +1 ładnie zrobione!
Rup

44
Patrzę na to od trzech godzin, ale wciąż nie widzę dinozaura ani promu kosmicznego. :-(
oosterwal

32

Czy Twój kompilator jest ustawiony w trybie eksperta ?! Jeśli tak, to nie powinno się kompilować. Nowoczesne kompilatory są zmęczone „Hello World!”


27

OCR mówi:

N lml_e <loJ+_e__}

.lnt Mk.,n ( ln+ _rSC Lhc_yh )
h_S_
_l

s_l . co__ <, " H llo uo/_d ! '` << s l . ena_ .
TP__rn _ |
_|

Co jest cholernie dobre, żeby być uczciwym.


4
Wow, OCR poprawił się, odkąd próbowałem zeskanować moje pismo ręczne (spędziłem godziny, pisząc je prosto).
James P.

40
Myślę, że musimy dodać tag Perla.
MSalters

26

helloworld.png: plik nie został rozpoznany: format pliku nie został rozpoznany

Oczywiście należy sformatować dysk twardy.

Naprawdę te błędy nie są trudne do odczytania.


20

Przekształciłem twój program z PNG na ASCII, ale nie kompiluje się jeszcze. Dla twojej informacji próbowałem z szerokością linii 100 i 250 znaków, ale oba dają porównywalne wyniki.

   `         `  .     `.      `         ...                                                         
   +:: ..-.. --.:`:. `-` .....:`../--`.. `-                                                         
           `      `       ````                                                                      
                                                                      `                             
   ` `` .`       ``    .`    `.               `` .      -``-          ..                            
   .`--`:`   :::.-``-. : ``.-`-  `-.-`:.-`    :-`/.-..` `    `-..`...- :                            
   .`         ` `    ` .`         ````:``  -                  ` ``-.`  `                            
   `-                                ..                           ``                                
    .       ` .`.           `   `    `. ` .  . `    .  `    . . .` .`  `      ` ``        ` `       
           `:`.`:` ` -..-`.`-  .-`-.    /.-/.-`.-.  -...-..`- :```   `-`-`  :`..`-` ` :`.`:`- `     
            ``  `       ```.      ``    ````    `       `     `        `    `         `   `   .     
            : -...`.- .` .:/ `                                                                      
    -       `             `` .                                                                      
    -`                                                                                              
    `                                                                                               

8
Prawdopodobnie powinieneś zamiast tego użyć 80 lub nawet 72 kolumn
Tobias Kienzler

16

Pierwszy problem polega na tym, że próbujesz zwrócić niepoprawną wartość na końcu funkcji głównej. Standard C ++ nakazuje, aby typ zwracany przez main () to int, ale zamiast tego próbujesz zwrócić pusty zestaw.

Innym problemem jest - przynajmniej w przypadku g ++ - kompilator dedukuje język używany na podstawie sufiksu pliku. Od g ++ (1):

W przypadku każdego pliku wejściowego sufiks nazwy pliku określa rodzaj kompilacji:

file.cc file.cp file.cxx file.cpp file.CPP file.c ++ file.C

Kod źródłowy C ++, który musi zostać wstępnie przetworzony. Zauważ, że w .cxx dwie ostatnie litery muszą być dosłownie x. Podobnie .C odnosi się do literalnej litery C.

Naprawienie ich powinno dać ci w pełni działającą aplikację Hello World, co można zobaczyć tutaj .


3
Miałem profesora już dawno temu, kto zdejmuje punkty za pracę domową lub egzaminy, jeśli wstawisz ukośnik przez cyfrę zero, ponieważ zero nie jest zerowym ustawieniem. Doceniłby tę odpowiedź.
Michael Burr,

15

Twoja czcionka jest do bani, jak parser powinien być w stanie to odczytać? Weź udział w kursie kaligrafii.


13

Twoje kompilatory oczekują ASCII , ale ten program jest oczywiście napisany przy użyciu EBCDIC .


Ostatnio słyszałem, że C ++ nie określa, że ​​programy muszą być napisane w ASCII, UTF-8 lub czymkolwiek innym.
Adrian Ratnapala

8

Próbujesz skompilować obraz.

Wpisz to, co odręcznie zapisałeś w dokumencie o nazwie main.cpp, uruchom ten plik za pomocą kompilatora, a następnie uruchom plik wyjściowy.


23
Sprawdź datę na komputerze.
James P.

14
Haha, ale w końcu znalazłem łatwy, na który mógłbym odpowiedzieć!
Cody Gray

10
To niemądre. Wszyscy wiemy, że kompilator zoptymalizuje białe znaki, pozostawiając tylko mocno skompresowaną czarną przestrzeń, która jest jedyną, i skompresuje się do binarnego 1, który zostanie zwrócony jako błąd. Kod musiał zostać napisany przy użyciu białych znaków, które skompilowałyby się do zera i nie zwróciły błędu.
Tin Man

7

Musisz określić precyzję wyjścia poprzedzoną dwukropkiem bezpośrednio przed końcowym nawiasem zamykającym . Ponieważ dane wyjściowe nie są numeryczne, dokładność wynosi zero, więc potrzebujesz tego -

: 0}




5

Problem leży w definicji składni, spróbuj użyć linijki i kompasów, aby uzyskać bardziej klasyczny opis!

Twoje zdrowie,


5

Spróbuj zmienić interfejs wejściowy. C ++ oczekuje, że klawiatura zostanie podłączona do komputera, a nie skanera. Mogą występować tutaj problemy z konfliktem urządzeń peryferyjnych. Nie sprawdziłem w standardzie ISO, czy interfejs klawiatury jest obowiązkowy, ale dotyczy to wszystkich kompilatorów, których kiedykolwiek używałem. Ale może wejście skanera jest teraz dostępne w C99, w takim przypadku twój program rzeczywiście powinien działać. Jeśli nie, będziesz musiał poczekać na kolejną standardową wersję i aktualizację kompilatorów.


5

Możesz wypróbować różne kolory nawiasów, może pomoże Ci zielony lub czerwony? Myślę, że twój kompilator nie może rozpoznać czarnego tuszu: P


5

Czy jestem jedynym, który nie rozpoznaje znaku między „return” a średnikiem? To może być to!


4
Jest to wielka litera O ze specjalną linią, którą nazywamy „średnicą”, która mówi kompilatorowi, aby używał algorytmu okręgu punktu środkowego, oczywiście. Myślę, że powinieneś sprawdzić oczy.
Mateen Ulhaq
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.