Почему эта программа ошибочно отклонена тремя компиляторами C ++?


468

У меня возникли трудности с компиляцией написанной мной программы на C ++.

Эта программа очень проста и, насколько мне известно, соответствует всем правилам, изложенным в стандарте C ++. Я перечитал весь ISO / IEC 14882: 2003 дважды, чтобы быть уверенным.

Программа выглядит следующим образом:

введите описание изображения здесь

Вот вывод, который я получил при попытке скомпилировать эту программу с помощью 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

Встревоженный, я попробовал g ++ 4.5.2, но это было одинаково бесполезно:

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

Я полагал, что Clang (магистраль версии 3.0 127530) должен работать, поскольку он так высоко ценится за соответствие стандартам. К сожалению, это даже не дало мне одно из его красивых, выделенных сообщений об ошибках:

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)

Если честно, я не знаю, что означают эти сообщения об ошибках.

Многие другие программы на C ++ имеют исходные файлы с расширением .cpp , поэтому я подумал, что, возможно, мне нужно переименовать мой файл. Я изменил его имя на helloworld.cpp , но это не помогло. Я думаю, что в Clang есть очень серьезная ошибка, потому что когда я пытался использовать ее для компиляции переименованной программы, она выскочила, напечатав «84 предупреждений и 20 сгенерированных ошибок». и заставил мой компьютер много гудеть!

Что я здесь не так сделал? Я пропустил какую-то критическую часть стандарта C ++? Или все три компилятора действительно настолько сломаны, что не могут скомпилировать эту простую программу?

Ответы:


173

В стандарте §2.1 / 1 определяет:

Физические символы исходного файла отображаются, в соответствии с реализацией, в базовый исходный набор символов (ввод символов новой строки для индикаторов конца строки), если это необходимо.

Ваш компилятор не поддерживает этот формат (он же не может сопоставить его с базовым исходным набором символов ), поэтому он не может перейти к дальнейшим этапам обработки, что приводит к ошибке. Вполне возможно, что ваш компилятор поддерживает отображение из изображения в основной исходный набор символов, но это не обязательно.

Поскольку это отображение определяется реализацией, вам нужно просмотреть документацию по реализации, чтобы увидеть поддерживаемые форматы файлов. Как правило, каждый крупный поставщик компиляторов поддерживает (канонически определенные) текстовые файлы: любой файл, созданный текстовым редактором, обычно последовательность символов.


Обратите внимание, что стандарт C ++ основан на стандарте C (§1.1 / 2), а стандарт C (99) говорит в §1.2:

Настоящий международный стандарт не определяет
- механизм, с помощью которого программы на C преобразуются для использования системой обработки данных;
- механизм, с помощью которого C-программы вызываются для использования системой обработки данных;
- механизм преобразования входных данных для использования программой на Си;

Итак, опять же, обработка исходных файлов - это то, что вам нужно найти в документации компилятора.


23
Я думаю, что предложение в лучшем случае неоднозначно. В словаре Merriam-Webster говорится, что текст - это оригинальные слова и форма письменного или печатного произведения или произведения, содержащего такой текст . Этот исходный файл явно подпадает под это определение. Как вы думаете, я должен подать отчет о дефектах в Рабочую группу по основным языкам?
Джеймс МакНеллис,

15
Ой; Я полностью забыл прочитать все упомянутые документы. Я думаю, что этот абзац вырван из контекста, поэтому я пойду и прочитаю полностью ISO / IEC 9899: 1990 и опубликую здесь, как только я полностью его пойму.
Джеймс МакНеллис

575

Первоначально из Overv @ Reddit .


19
Лучший. Формат BMP. Спецификация иллюстрации. Когда-либо.
Тобиас Кинцлер,

49
Таким образом, ошибка OPs заключалась в использовании png вместо bmp?
subsub

1
Вдохновленный этим прекрасным ответом, я решил, что сделаю нечто подобное для brainf ***: blog.dreasgrech.com/2011/04/…
Андреас Греч


211

Ваши <и >, (и ), {и }, кажется, не очень хорошо совпадают; Попробуйте нарисовать их лучше.


44
Хотя я не ценю, что вы смеетесь над моим почерком, это может быть реальной проблемой и объясняет ошибку, которую я получаю, когда пытаюсь скомпилировать переименованный файл helloworld.cpp с Visual C ++: «фатальная ошибка C1004: неожиданный конец файл найден "Я попробую еще раз и скоро сообщу. Спасибо!
Джеймс МакНеллис,

37
@James убедитесь, что вы отключили все оптимизации png. это облегчает отладку.
wilhelmtell

5
@James: «неожиданный конец файла» почти наверняка означает, что }проблема возникла именно у вас. Попробуйте сосредоточиться на сопоставлении этого с{
Carson63000

156

Вы можете попробовать следующий скрипт Python. Обратите внимание, что вам нужно установить PIL и pytesser .

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

Чтобы использовать это, сделайте:

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

110

Вы забыли использовать Comic Sans в качестве шрифта, поэтому его ошибка.


73
К сожалению, это единственный шрифт, который поддерживает моя рука. Это было бы очень грустно, если я не могу программировать на C ++ из-за этого. Как вы думаете, Java будет поддерживать этот шрифт?
Джеймс МакНеллис,

8
Comic Sans вам понадобится, когда вы все равно будете рисовать комиксы, поэтому вам следует серьезно подумать об улучшении рук.
sharptooth

8
С ++ требует годичного обучения каллиграфии. Если у вас нет времени, попробуйте Visual Basic или просто двоичный машинный код (тогда вам просто нужно получить 0 и 1).
Фрэнк Остерфельд

1
@Frank C ++ 0x §42.1 / 1 определяет «Все строки должны быть в готическом стиле».
Матин Улхак,

75

Я не вижу новой строки после этой последней скобки.

Как вы знаете: «Если исходный файл, который не является пустым, не заканчивается символом новой строки, ... поведение не определено».


16
Хммм. К счастью, это нелепое правило было удалено в C ++ 0x. Тем не менее, как один конец такого файла с новой строки? Я думал, что оставил достаточно места в конце текста (если вы выделите исходный файл, вы должны увидеть дополнительную комнату, которую я оставил). Спасибо за совет, хотя!
Джеймс МакНеллис,

8
Если у вас недостаточно свободного места, я могу попробовать скомпилировать его в моей системе. У меня четыре монитора, поэтому я могу попробовать скомпилировать с моего самого левого.
Жестянщик

74

Эта программа действительна - я не могу найти ошибок.

Я думаю, у вас есть вирус на вашей машине. Было бы лучше, если вы переформатируете свой диск и переустановите операционную систему.

Дайте нам знать, как это работает, или если вам нужна помощь с переустановкой.

Я ненавижу вирусы.


17
Да, попробуйте установить Linux. Я виню винду за твою проблему.
Raedwald

62

Я обнаружил, что это помогает не писать мой код на стекле моего монитора с помощью волшебного маркера, даже если он выглядит действительно черным. Экран заполняется слишком быстро, и тогда люди, которые дают мне чистый монитор, называют меня именами каждую неделю.

Пара моих сотрудников (я менеджер) собиралась купить мне один из этих красных компьютеров с кнопками. Они сказали, что мне не понадобятся маркеры, и я могу самостоятельно почистить экран, когда он заполнится, но я должен быть осторожен, встряхивая его. Я предполагал, что это так деликатно.

Вот почему я нанимаю умных людей.


2
Wacom Cintiq гораздо больше подходит для менеджера. Это дорого, и заставляет тебя чувствовать себя действительно важным. Любой графический дизайнер в вашей компании будет иметь гораздо более низкий статус, и поэтому должен использовать мониторы EGA. Дворники должны использовать мониторы CGA. Программисты должны использовать подержанные монохромные терминалы.
Steve314

7
У меня был монитор "Life Like" в течение длительного времени. Это было настолько реалистично, что вы могли поклясться, что заставка с плавающей рыбой была настоящей, а маленький ныряльщик выглядел так, будто плавал. Я продолжал промокать руку, пытаясь достать сундук с сокровищами снизу, это было так реально. Единственная проблема заключалась в том, что экранная заставка всегда была включена, а реалистичные пузырьки не позволяли слышать. О, и они сказали, что для технического обслуживания я должен ежедневно разбрызгивать вещи в верхней части монитора, иначе заставка перестанет работать. Он сделал это однажды, и мальчик, запах два дня спустя был действительно реалистичным.
Жестянщик

59

File format not recognizedВам нужно правильно отформатировать ваш файл. Это означает использование правильных цветов и шрифтов для вашего кода. Смотрите конкретные документы для каждого компилятора, так как эти цвета варьируются в зависимости от компилятора;)


14
О, это имеет смысл ... У меня есть коробка с 96 карандашами, поэтому я уверен, что у меня правильный цвет переднего плана. Завтра я возьму цветную бумагу и попробую ее на бумаге другого цвета.
Джеймс МакНеллис,

3
Просто чтобы быть в безопасности, вам лучше взять несколько цветных карандашей и краски на масляной основе. Общеизвестно, что C ++ является очень сложным языком для правильного форматирования.
helloworld922

Да, и не забудьте использовать маркер выделения.
sharptooth

6
@sharptooth - подсветка синтаксиса является функцией IDE - вы не должны делать это вручную. Поэтому убедитесь, что у вас есть рука робота, чтобы идти с этим маркером выделения.
Steve314

56

Вы забыли препроцессор. Попробуй это:

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

8
Ой! Я думал, что препроцессор был включен в компилятор! Я постараюсь найти препроцессор, который работает на моем ноутбуке с Windows.
Джеймс МакНеллис,

3
@James McNellis: препроцессор - это не программа, это аппаратная вещь, которая выглядит как маркер выделения - вы перемещаете его по тексту, и он подвергается предварительной обработке.
sharptooth

49

Вы написали программу от руки, а затем отсканировали ее в компьютер? Это то, что подразумевается под "helloworld.png". Если это так, вы должны знать, что стандарт C ++ (даже в его новейшей редакции) не требует наличия оптического распознавания символов, и, к сожалению, он не включен в качестве дополнительной функции в любой текущий компилятор.

Вы можете рассмотреть вопрос о переносе графики в текстовый формат. Любой текстовый редактор может быть использован; использование текстового процессора, способного генерировать красивые распечатки, скорее всего, приведет к той же ошибке, что и вы, пытаясь сканировать.

Если вы действительно любите приключения, вы можете попытаться написать свой код в текстовом редакторе. Распечатайте его, желательно с помощью шрифта, например OCR-A . Затем возьмите распечатку и отсканируйте ее обратно. Затем можно выполнить сканирование с помощью стороннего пакета OCR для создания текстовой формы. Текстовая форма может быть скомпилирована с использованием одного из множества стандартных компиляторов.

Остерегайтесь, однако, больших затрат бумаги, которые она понесет на этапе отладки.


Дилемма "курица и яйцо": можно ли написать код C ++ для программного обеспечения OCR и скомпилировать его без OCR?
jweyrich

5
Ну, вы используете сборку для оригинального распознавания текста.
Кевин Лакмент

@jweyrich - Я думаю, вам нужно сначала загрузить C ++ / OCR с помощью цепочки инструментов asm / OCR.
Майкл Берр,


46

Нарисуйте включаемый файл ниже, чтобы он скомпилировался:

#include <ChuckNorris>

Я слышал, что он может компилировать синтаксические ошибки ...


46
Я лично предпочитаю #include <JonSkeet>.
Icode4food

40

К сожалению, вы выбрали три компилятора, которые поддерживают несколько языков, а не только C ++. Все они должны угадать, какой язык программирования вы использовали. Как вы, наверное, уже знаете, формат PNG подходит для всех языков программирования, а не только для C ++.

Обычно компилятор может выяснить сам язык. Например, если PNG явно нарисован мелками, компилятор будет знать, что он содержит Visual Basic. Если он выглядит так, как будто он нарисован механическим карандашом, легко узнать инженера на работе, пишущего код на языке FORTRAN.

Этот второй шаг также не помогает компилятору, в этом случае. C и C ++ выглядят слишком похоже, вплоть до #include. Следовательно, вы должны помочь компилятору решить, какой это на самом деле язык. Теперь вы можете использовать нестандартные средства. Например, компилятор Visual Studio принимает аргументы командной строки / TC и / TP , или вы можете использовать опцию «Компилировать как: C ++» в файле проекта. GCC и CLang имеют свои собственные механизмы, которые я не знаю.

Поэтому я бы рекомендовал вместо этого использовать стандартный метод, чтобы сообщить компилятору, что следующий код написан на C ++. Как вы уже обнаружили, компиляторы C ++ очень требовательны к тому, что они принимают. Поэтому стандартным способом идентификации C ++ является использование программистами запугивания в своем коде C ++. Например, следующая строка разъяснит вашему компилятору, что ниже следует C ++ (и он лучше скомпилирует его без нареканий).

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

10
Я думал, что #pragmaбыл правильный способ «получить сообщение» компилятору?
Лев Епископ

33

Попробуй это:

Вы видите динозавра в космическом шаттле?


4
Я думаю, что есть опечатка - это должно быть endl(L), а не end1(один). Но +1 красиво сделано!
Rup

44
Я смотрел на это три часа, но до сих пор не вижу ни динозавра, ни космического челнока. :-(
oosterwal

32

Ваш компилятор установлен в экспертном режиме ?! Если да, он не должен компилироваться. Современные компиляторы устали от "Hello World!"


27

OCR говорит:

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 _ |
_|

Что чертовски хорошо, если быть честным.


4
Ничего себе, распознавание текста улучшилось с тех пор, как я попытался отсканировать свой почерк (тоже потратил много времени на его написание).
Джеймс П.

40
Я думаю, что нам нужно добавить тег Perl.
MSalters

26

helloworld.png: файл не распознан: формат файла не распознан

Очевидно, вы должны отформатировать жесткий диск.

На самом деле, эти ошибки не так сложно прочитать.


20

Я конвертировал вашу программу из PNG в ASCII, но она еще не компилируется. К вашему сведению, я пробовал с шириной строки 100 и 250 символов, но оба дают сравнимые результаты.

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

8
Вы, вероятно, должны использовать 80 или даже 72 столбца вместо этого
Тобиас Кинцлер

16

Первая проблема заключается в том, что вы пытаетесь вернуть неправильное значение в конце основной функции. Стандарт C ++ диктует, что тип возвращаемого значения main () - int, но вместо этого вы пытаетесь вернуть пустой набор.

Другая проблема - по крайней мере с g ++ - в том, что компилятор выводит язык, используемый из суффикса файла. Из g ++ (1):

Для любого входного файла суффикс имени файла определяет, какой тип компиляции будет выполнен:

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

Исходный код C ++, который должен быть предварительно обработан. Обратите внимание, что в .cxx последние две буквы должны быть буквально x. Аналогично, .C относится к буквальному букву C.

Их исправление должно оставить вас с полностью работающим приложением Hello World, как видно из демонстрации здесь .


3
У меня был профессор, когда кто-то снимал баллы с вашей домашней работы или экзаменов, если вы ставили косую черту через ноль, поскольку ноль не является нулевым набором. Он был бы признателен за этот ответ.
Майкл Берр


13

Ваши компиляторы ожидают ASCII , но эта программа, очевидно, написана с использованием EBCDIC .


Последнее, что я слышал, C ++ не указывает, что программы должны быть написаны на ASCII, UTF-8 или чем-то еще.
Адриан Ратнапала

8

Вы пытаетесь скомпилировать изображение.

Напечатайте то, что вы написали от руки, в документе с именем main.cpp, запустите этот файл через ваш компилятор, затем запустите выходной файл.


23
Проверьте дату на вашем компьютере.
Джеймс П.

14
Ха-ха, но я, наконец, нашла легкий ответ
Коди Грей

10
Это глупо. Мы все знаем, что компилятор оптимизировал бы пустое пространство, оставляя только сильно сжатое черное пространство, которое является единицами, и сжимал бы до двоичного 1, который был бы возвращен как ошибка. Код должен быть написан с использованием white-out, который компилируется в 0 и не возвращает ошибку.
Жестянщик

7

Вам нужно указать точность вашего вывода, которому предшествует двоеточие непосредственно перед последней закрывающей скобкой . Поскольку вывод не является числовым, точность равна нулю, поэтому вам нужно это-

: 0}


5

Добавить :

using namespace std;

сразу после включения: P: D


5
Я предпочитаю печатать stdвсе время. Напоминает мне, чтобы не получить один.
Матин Улхак,


5

Проблема заключается в определении синтаксиса, попробуйте использовать линейку и компас для более классического описания!

Ура,


5

Попробуйте переключить интерфейс ввода. C ++ ожидает, что клавиатура будет подключена к вашему компьютеру, а не сканер. Здесь могут быть проблемы конфликта периферийных устройств. В стандарте ISO я не проверял, является ли интерфейс ввода с клавиатуры обязательным, но это верно для всех компиляторов, которые я когда-либо использовал. Но, возможно, вход для сканера теперь доступен в C99, и в этом случае ваша программа действительно должна работать. Если нет, вам придется ждать следующего стандартного выпуска и обновления компиляторов.


5

Вы можете попробовать разные цвета для скобок, может быть, немного зеленого или красного поможет? Я думаю, что ваш компилятор не может распознать черные чернила: P


5

Я единственный, кто не может распознать символ между «возвращением» и точкой с запятой? Это может быть так!


4
Это заглавная буква O со специальной линией, которую мы называем «диаметр», которая указывает компилятору, очевидно, использовать алгоритм окружности средней точки. Я думаю, вы должны проверить свои глаза.
Матеин Улхак,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.