文字列リテラルの閉じ忘れで出るエラーの原因と直し方
文字列リテラルの閉じクォート(")を書き忘れたときに出るエラーです。閉じ忘れた行がそのままエラー行になり、後続の行でも連鎖的にエラーが出ることがあります。
エラーメッセージの読み方
main.cpp:3:18: error: missing terminating " character
main.cpp- ファイル名
3- 行番号
18- 列番号 — この位置でg++が構文解析に失敗しました
missing terminating " character- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 #include <iostream> 2 int main() { 3 std::cout << "hello << std::endl; ^ 4 return 0; 5 }
文字列リテラルの閉じクォートを忘れると、その行の終わりまで読んでも文字列が終わらないため、g++はそこでエラーにします。
直し方: "hello を "hello" にします。
パターン2
1 #include <iostream> 2 int main() { 3 std::string msg = "good morning ; ^ 4 std::cout << msg << std::endl; 5 return 0; 6 }
閉じクォートが無い文字列は改行をまたげないため、次の行が本来意図した続きであっても連結されません。
直し方: "good morning を "good morning" にします。
パターン3
1 #include <iostream> 2 int main() { 3 std::cout << "total: 100 << std::endl; ^ 4 return 0; 5 }
コロンや数字を含む文字列でも、閉じクォートが必要なことに変わりはありません。
直し方: "total: 100 を "total: 100" にします。
パターン4
1 #include <iostream> 2 int main() { 3 std::string name = "Al ; ^ 4 std::cout << name << std::endl; 5 return 0; 6 }
std::string型への代入でも同じ規則です。閉じクォートを忘れると未完成な文字列として扱われます。
直し方: "Al を "Al" にします。
パターン5
1 #include <iostream> 2 int main() { 3 std::cout << "bye << std::endl; ^ 4 return 0; 5 }
coutへ直接渡す文字列リテラルでも同様です。閉じクォートは省略できません。
直し方: "bye を "bye" にします。
よくある誤解
閉じクォートを忘れると「次の"までが1つの文字列として読まれる」と思われがちですが、実際にはC++の文字列リテラルは改行をまたげません。同じ行に閉じクォートが無い時点で即座にエラーとして報告されます。
実務での勘所
引用符やバックスラッシュを大量に含む文字列(正規表現のパターンなど)を書きたい場合、C++11以降はR"(...)"という生文字列リテラル(raw string literal)が使えます。この構文の中ではエスケープシーケンスが一切解釈されず、改行も含めてそのままの文字列として扱われるため、閉じ忘れや意図しないエスケープに悩まされにくくなります。ただし通常の文字列と同様、開いた行から実際に閉じる)"までの対応が崩れていないかは依然として確認が必要です。