Bug

Photo by Joanne Gerber on Unsplash

不知道大家有沒有想過在 C++ 裡將 string 型態轉換成 int,在 C 語言中可以使用 atoi() 進行轉換,但是在 C++ 內就會出錯,我之前打 ACM 比賽時就遇上這個問題了,可能是當時比賽心情緊張,搞了很久都沒找到原因,後來總算知道問題在那了,也把解決問題的方法記錄下來給其他人看。

先來一段範例程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include<iostream>
#include<cstdlib>
#include<string>
using namespace std;
int main(int argc, char const *argv[])
{
    string str;
    cin >> str;
    cout << atoi(str) + 10 << endl;
    return 0;
}

使用 g++ -std=c++11 編譯會出現以下錯誤。

1
2
3
4
5
$ g++ -std=c++11 string.cpp -o string.exe
string.cpp: In function 'int main(int, const char**)':
string.cpp:9:21: error: cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}' to 'const char*' for argument '1' to 'int atoi(const char*)'
     cout << atoi(str) + 10 << endl; // a??a﹐? c_str() a?? string e??a?? char
                     ^

原因

atoi() 函數定義在 C 語言內的 stdlib.h,由於 C 語言並沒有 string 這個 class,atoi 是給 char 型態進行轉換的,無法應用於 C++ 的 string 型態。

解決

C++ 的 string 函式庫中提供了 c_str() 函數,只要在字串變數後面加上 c_str() 便能將 string 型態轉換成原生的 char 型態,這樣一來也能夠使用 stdlib.h 的字串轉 int 函數,記得下次轉換 string 類型時注意一下。

如果想在 C++ 中引入 C 語言的標準函式庫,只要在前面加上 c 然後去掉 .h,像是 stdio.h 在 C++ 引入就寫 cstdio 就好。

最後貼上可以正常編譯執行的程式碼。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <iostream>
#include <cstdlib> // atoi 函數所在函式庫
#include <string>
using namespace std;
int main(int argc, char const *argv[])
{
    string str;
    cin >> str;
    cout << atoi(str.c_str()) + 10 << endl; // 加上 c_str() 把 string 轉成 char
    return 0;
}

執行結果:

1
2
3
$ ./string.exe
10
20