C ++ readline和write to file(行环境卫生)

时间:2016-09-13 02:38:17

标签: c++

我似乎遇到了一些奇怪的问题,我的部分代码涉及从现有文件中读取一行并将一部分写入另一个文件:

这是我所看到的一个例子(我只想要元音)。

image

以下是我涉及的三个功能。在尝试找出原因时,我有点.c_str()快乐:

void do_file_magic(string file){
    fstream source;
    string outfile,
               line,
               vowels,
               temp;

    // Name the outfile
    outfile = "vowels_" + file;

    source.open(file);
    if (!source.is_open()) {
        die_a_clean_death("Unable to open source file:", file);
    };

    ofstream destination(outfile);
    if (!destination.is_open()) {
        source.close();
        die_a_clean_death("Unable to open destination file:", file);
    };

    // read source file and output vowels to destination file.
    do {
        for (int i = 1; !source.eof(); i++ ){
            getline(source, line);
            temp = vowels_on_a_line(line) + "\n";
            destination << temp.c_str();
        };
    } while (!source.eof());

    // Close the files
    source.close();
    destination.close();
};

string vowels_on_a_line(string input){
    int input_size = input.size(),
    vowel_counter = 0;

    // this will not be larger than input_size
    char vowelarray[input_size];

    // find the vowels with the vowel test
    for (int i = 0; i < input_size; i++){
        if (vowel_test(input[i])){
            vowelarray[vowel_counter] = input[i];
            vowel_counter++;
        };
    };

    // convert array to string
    string vowels(vowelarray);

    // return the stringi
    printf("%s\n", vowels.c_str());
    return vowels;
};

bool vowel_test(char c){
    if(
        c=='a'||c=='A'||
        c=='e'||c=='E'||
        c=='i'||c=='I'||
        c=='o'||c=='O'||
        c=='u'||c=='U'
    ) {
        return true;
    } else {
        return false;
    };
};

有谁看到我在做错了什么?

这是运行时的终端输出。我注意到有?U?代替文本编辑器输出:

Mac Shell: Homework2/>$ ./Homework2 

Enter a filename:
-----------------
test.txt
oeiuooiaeoeeuaiiieiaeeaiiaoeiea
uueeaoaeaoiouaiueeiiuaeeeueiiueia?U?
uuoeuaeoeiiuoeeauueuiuioiiuieiuuaaoi?
aeueeieoioooeauaieoaiuiaeuaoeuaiiu?U?
oieuuuiiauoeuoiiaeieieiaeuaaiii
UeaooaiuaeuueieieiauiiaIeeoioeieiiue?
aueuuuuaueieuiaaeuaauaeeeaeeeeuee?U?
aauueiuauaiuoeieeoeeooiiuiiaiaueiuuo?
aeieeaiaieouo

auiooiiaeauiaeuuuaeeuouuaaauoua
eueuoeeuiaeeuuaoiiiuoeieuiuaue
iaeeoaoiaieoiauiuauouiaeiaeuuoi
eueeeueeeiueeieuioauieeuaeuaa
?
iaueeiaeeeueuaoeauueuiauiiauiuieuu?U?
eeeueeeoaeuoioiuIauioeieueiua
eeeuiiieaeeoiiuioueiaoaiuaaiiai
aeaiaeiuauaeeauieoiaeeiiuieeeuui??U?
aiuaaaeuaaoooiouiaiaaiueaeuaa
?
aeeeueuouauueauaeeuUeeoieueioioeua?U?
eeaueueiuaaeuuuooeeeiuaeuuiie
auiieuioeuaaaaieieeeeuiaiieieeuIee?U?
aeaieaeiiaeuaoeauieiuaeueieeeeueua?U?
uoueuuuiaai

euaeioaeuieuiaeaiiaiaeoiouaiuaeeeuauue
iauoieuauiuaeauaoeAeeaiiauiuUeaiueoe?
eaiiaeieiuuoueaeeieuuaoeaeeaiuuaea#

iieuoeuaeeaauEiauiieuaoeaiueaaeoi?U?
auiaeaeiaeeuiauioeiieiieaaoeeuioeeu

uieueeeueuieoeuauiieauieeiueaiueuiiU?
eiuuoiuiieooaaiuiauoaeeiuaiaeuio??U?
H?U?
Mac Shell: Homework2/>$

3 个答案:

答案 0 :(得分:3)

显示的代码中存在多个错误。

   for (int i = 1; !source.eof(); i++ ){
         getline(source, line);

在循环条件is always a bug.

中检查eof()
 char vowelarray[input_size];

 // You put something into vowelarray.

 string vowels(vowelarray);

显示的代码实例化了vowelarrayvowelarray未初始化。随后的代码继续填充vowealarray的初始内容。

vowelarray传递给std::string的构造函数会将char数组衰减为const char *

const char *构造函数的std::string参数必须是以`\ 0'结尾的字符串。

显示的代码无法使用\0字节终止字符串。因此,结果字符串通常会包含随机垃圾,这就是您所看到的。

您需要将数组的最大大小增加1,以便考虑额外的'\ 0'字符:

char vowelarray[input_size+1];

然后在从char数组中正确添加终止'\ 0',然后再从中构建std::string

答案 1 :(得分:1)

vowels_on_a_line()中,您需要对vowelarray中存储的字符串进行空终止,以避免在行尾添加垃圾字符。

答案 2 :(得分:1)

您没有正确地将vowels数组转换为string。您没有空终止数组,也没有告诉string构造函数数组中有多少个字符。因此它最终超出范围并从周围的内存中复制数据,直到遇到空字节(或崩溃)。

我建议根本不使用数组(特别是因为你也依赖于非标准的编译器扩展来首先分配数组)。尝试更像这样的东西:

void do_file_magic(const string &file)
{
    string outfile = "vowels_" + file;
    string line;

    ifstream source(file.c_str());
    if (!source.is_open()) {
        die_a_clean_death("Unable to open source file:", file);
    };

    ofstream destination(outfile.c_str());
    if (!destination.is_open()) {
        die_a_clean_death("Unable to open destination file:", outfile);
    };

    // read source file and output vowels to destination file.
    while (getline(source, line)) {
        destination << vowels_on_a_line(line) << "\n";
    }
}

string vowels_on_a_line(const string &input)
{
    int input_size = input.size(),
    ostringstream oss;

    // find the vowels with the vowel test
    for (int i = 0; i < input_size; i++){
        if (vowel_test(input[i])) {
            oss << input[i];
        }
    }

    // convert array to string
    string vowels = oss.str();

    // return the string
    cout << vowels << "\n";
    return vowels;
};

bool vowel_test(char c)
{
    return (
        (c=='a')||(c=='A')||
        (c=='e')||(c=='E')||
        (c=='i')||(c=='I')||
        (c=='o')||(c=='O')||
        (c=='u')||(c=='U')
    );
}