2010-08-21 5 views
2

Привет, я читаю строку и разбиваю каждое слово и сортирую его по имени и номеру телефона. со строкой joe bloggs [email protected] 12345. Но как только я сломаю все, отдельные отдельные переменные, в которых хранятся имя, адрес электронной почты и номер телефона, содержат символы мусора в конце их. Я не могу понять, почему.символ мусора в конце строки?

тестового файл

//test file 
#include <iostream> 
#include <string> 
#include "iofunc.h" 
using namespace std; 
int main(){ 
    string str1 = "joe bloggs [email protected] 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; 
} 

вот моя функция имени прибудет, класс слишком велик, чтобы пролистать :)

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. Он копирует все, что мне нужно, но это дает мне этот мусор после каждой извлеченной строки.

любая идея ?.

EDITED

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); 
     } 
    } 

} 
+0

Где вы на самом деле читаете строки. С каким методом. Я предлагаю вам использовать «fstream». – Auxiliary

ответ

0

Когда вы делаете что-то вроде этого:

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

Вы копируете символов строки в name_tmp, но не на 0 в конце, который завершает строку.

+0

будет работать, если я добавлю нулевой завершающий символ '\ 0', как этот 'name_temp [maxlen + 1] = '\ 0'' (где max length - длина того, что было скопировано), а затем выполните команду glob_name = string (name_temp); ' – silent

+0

Да, хотя было бы проще просто добавить' name_temp [i] = '\ 0'; 'сразу после этого. –

+0

Я все еще получаю то же самое, когда у меня есть 3 имени вместо двух, любая идея? – silent

2

добавить к каждой новой строке «\ 0» отслужившего символа строки

0

мусора символов в конце строки может означать, что вы не нуль-терминатор строка (заканчивается байтом 0x00). Это заставляет строку продолжать чтение до следующего нулевого символа, который на самом деле проходит мимо, где заканчивается память строки. В некоторых случаях это может вызвать сбои сегментации.

Вы можете исправить это, добавив '\0' в конец каждой новой строки, которую вы создаете. Обратите внимание, что теперь вам нужно будет выделить строку с байтом больше, чтобы сохранить этот новый символ окончания.

+0

'char_len = strlen (name_temp);' 'name_temp [char_len + 1] = '\ 0'; glob_name = string (name_temp);' Я пробовал это, но он все равно дает мне тот же результат – silent

+0

@ sil3nt strlen ищет символ '\ 0', чтобы найти конец строки. Это не будет работать, если \ 0 не существует. – josefx

+0

@ sil3nt используйте ваш индекс цикла вместо name_temp [i + 1] = '\ 0' – josefx

0

Другие указали на вас в правильном направлении, вы не соответствующим образом завершаете свои строки c. Объявление массива char длиной 80 просто указывает на блок памяти, он не инициализирует массив каким-либо образом, это означает, что если вы/0 не закончите строку, которую вы копируете в нее, вы получите всю дерьмо, лежащую вокруг в конце до 80 символов.

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

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; 
    } 

}