4

こんにちは、私は文字列を読んで、各単語を分割し、名前の電子メールと電話番号に分類しています。文字列を使用しますjoe bloggs joeblog@live.com 12345。しかし、すべてを分解すると、名前、電子メール、電話番号を保持する個々の分離変数の末尾にゴミ文字が表示されます。理由がわかりません。

テストファイル

//test file
#include <iostream>
#include <string>
#include "iofunc.h"
using namespace std;
int main(){
    string str1 = "joe bloggs joeblog@live.com 12345";

    iofunc func;
    cout<<"|-----------------------getname DEMONSTRATION------------------|\n" << endl;
    func.getName(str1);

    cout<<"the names are: " << func.glob_name << endl;

    cout<<"\n|-----------------------getphone DEMONSTRATION------------------|\n" << endl;
    func.getPhone(str1);
    cout<<"the phone number is:" << func.glob_phone << endl;

    cout<<"\n|-----------------------getemail DEMONSTRATION------------------|\n" << endl;
    func.getEmail(str1);
    cout<<"the email address is:" << func.glob_email << endl;


    return 0;
}

これが私のgetname関数です。クラスが大きすぎてスクロールできません:)

void iofunc::getName(string arg){
    lineProcess(arg); 
    //make sure to call this depending on what function u are using

    int name_count = 0;
    int wspace_count = 0;
    int arg_len = arg.length();
    //int char_len = 0;
    char name_temp[80];

    name_count = numberofNames(); 
    //line process was called before so this will work, 
    //make sure you call line process before using this function

    //for special, condition when there is no space in front of names
    if (special_condition == true){
        int i = 0;
        while(i < arg_len){
            name_temp[i] = arg[i];
            i++;
        }
        glob_name = string(name_temp);

    }

    if (special_condition == false){
        if (name_count == 1){
            int i = 0;
            while (arg[i] != ' '){
                name_temp[i] = arg[i];
                i++;
            }
            glob_name = string(name_temp);
        }

        //for 2 names
        if (name_count == 2){
            for (int i = 0; i < arg_len;i++){
                if (arg[i] == ' '){
                    wspace_count++;
                }
                if (wspace_count !=2){
                    name_temp[i] = arg[i];
                }
            }
            glob_name = string(name_temp);
        }
        //for 3 names
        if (name_count == 3){
            for (int i = 0; i < arg_len;i++){
                if (arg[i] == ' '){
                    wspace_count++;
                }
                if (wspace_count !=3){
                    name_temp[i] = arg[i];
                }
            }
            glob_name = string(name_temp);
        }
    }

}

つまり、lineProcessという関数を使用して、引数文字列に電子メール、電話、名前が含まれているかどうかを確認します。numberofNames関数は、それに応じて動作できるように、名前の数を示します。

文字列から名前だけをコピーするために使用する必要がありました。char name_tempこれにより、名前だけを抽出して、stringという名前の変数に割り当てることができますglob_name。それは私が必要とするすべてをコピーします、しかしそれは私にそれぞれの抽出された文字列の後にそのゴミを与えます。

何か案が?。

編集済み

void iofunc::getName(string arg){
    lineProcess(arg); 
    //make sure to call this depending on what function u are using

    int name_count = 0;
    int wspace_count = 0;
    int arg_len = arg.length();
    //int char_len = 0;
    char name_temp[80];
    int index_track = 0;

    name_count = numberofNames(); 
    //line process was called before so this will work, 
    //make sure you call line process before using this function

    //for special, condition when there is no space in front of names
    if (special_condition == true){
        int i = 0;
        while(i < arg_len){
            name_temp[i] = arg[i];
            index_track = i;
            i++;
        }
        name_temp[index_track+1] = '\0';
        glob_name = string(name_temp);

    }

    if (special_condition == false){
        if (name_count == 1){
            int i = 0;
            while (arg[i] != ' '){
                name_temp[i] = arg[i];
                index_track = i;
                i++;
            }
            name_temp[index_track+1] = '\0';
            glob_name = string(name_temp);
        }

        //for 2 names
        if (name_count == 2){
            for (int i = 0; i < arg_len;i++){
                if (arg[i] == ' '){
                    wspace_count++;
                }
                if (wspace_count !=2){
                    name_temp[i] = arg[i];
                    index_track = i;
                }
            }
            name_temp[index_track+1] = '\0';
            glob_name = string(name_temp);
        }
        //for 3 names
        if (name_count == 3){
            for (int i = 0; i < arg_len;i++){
                if (arg[i] == ' '){
                    wspace_count++;
                }
                if (wspace_count !=3){
                    name_temp[i] = arg[i];
                    index_track = i;
                }
            }
            name_temp[index_track+1] = '\0';
            glob_name = string(name_temp);
        }
    }

}
4

4 に答える 4

2

それぞれの新しい文字列に追加'\0'文字列の終わりの記号

于 2010-08-21T08:00:25.820 に答える
2

あなたがこのようなことをするとき:

    while(i < arg_len){ 
        name_temp[i] = arg[i]; 
        i++; 
    } 

文字列の文字をname_tmpにコピーしていますが、文字列を終了する最後の0はコピーしていません。

于 2010-08-21T08:00:52.543 に答える
0

他の人はあなたを正しい方向に向けています、あなたはあなたのc文字列を適切に終了していません。長さ80のchar配列を宣言すると、メモリのブロックを指すだけで、配列は初期化されません。つまり、コピーした文字列を/ 0で終了しない限り、すべてのがらくたが横になります。最後に80文字まで。

私はおそらく15年間C++を作成していないので、以下のコードは機能しないかもしれませんが、よりエレガントで保守しやすいソリューションのアイデアが得られることを願っています。

void iofunc::getName(string arg){
    lineProcess(arg); 
    //make sure to call this depending on what function u are using

    int name_count = 0;
    int wspace_count = 0;
    int arg_len = arg.length();
    //int char_len = 0;
    string name_temp;

    // Let's assemble a c-str version if the inbound arg string
    char* cstr;
    cstr = new char [arg.size()+1];
    strcpy (cstr, arg.c_str());

    name_count = numberofNames(); 
    //line process was called before so this will work, 
    //make sure you call line process before using this function

    //for special, condition when there is no space in front of names
    if (special_condition == true){
        glob_name = arg;
    }

    if (special_condition == false){
        // Assuming there's at least 1 name, which we have to otherwise the original
        // code may never set glob_name, let's use the C String function strtok
        // to tokenise our newly created c string at each " ".
        // Grab the first name.
        name_temp = string(strtok(cstr, " "));
        for (int i = 1; i < name_count; i++) {
            // Grab names 2 to name_count as required and append them to name_temp
            // We need to reinsert the space as strtok doesn't grab it.
            name_temp += " " + string(strtok(NULL, " "));
        }
        // Assign our final name to glob_name
        glob_name = name_temp;
    }

}
于 2010-08-21T08:22:38.473 に答える
0

文字列の最後にあるガベージ文字は、文字列をnullで終了していない(0x00バイトで終了していない)ことを示している可能性があります。これにより、文字列は次のnull文字まで読み取りを続行します。これは、実際には文字列のメモリが終了する場所を過ぎています。これにより、場合によってはセグメンテーション違反が発生することもあります。

これを修正する'\0'には、作成する新しい文字列をそれぞれ最後に追加します。その新しい終了文字を保持するには、ここで1バイト大きい文字列を割り当てる必要があることに注意してください。

于 2010-08-21T08:00:38.363 に答える