Форум программистов, компьютерный форум CyberForum.ru

Функция strtok. Представление телефонного номера в виде строки. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:05     Функция strtok. Представление телефонного номера в виде строки. #1
Запутался в функции strtok. Причем уже сделал для неё пару упражнений, вроде понимаю как она работает. По крайней мере с предложением из слов. Задание звучит так, используя функцию strtok, разбить телефонный номер формата (555) 555-5555, введенный как строку, на лексемы. Где первой лексемой будет код, второй первые три цифры номера, а третьей после четыре цифры. Я смог выбить код, и перевести его в тип данных int. Но когда пытаюсь продолжать обработать строку, то вылазит ошибка выхода за границы массива.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   char phoneNumber[40];
   char code[3];
   int codeRegion;
   char *codePtr = NULL;
   char *numberPtr = NULL;
 
   cout << "Enter the telephone number in format: (555) 555-5555:\n";
   cin >> phoneNumber;
    
   codePtr = strtok(phoneNumber, " ");
    
   for ( int i = 0; i < 3; i++)
      code[i] = codePtr[i+1];
  
   codeRegion = atoi(code);
    
   codePtr = strtok(NULL, " ");
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Сыроежка
Заблокирован
27.10.2011, 20:11     Функция strtok. Представление телефонного номера в виде строки. #2
Цитата Сообщение от Navern Посмотреть сообщение
Запутался в функции strtok. Причем уже сделал для неё пару упражнений, вроде понимаю как она работает. По крайней мере с предложением из слов. Задание звучит так, используя функцию strtok, разбить телефонный номер формата (555) 555-5555, введенный как строку, на лексемы. Где первой лексемой будет код, второй первые три цифры номера, а третьей после четыре цифры. Я смог выбить код, и перевести его в тип данных int. Но когда пытаюсь продолжать обработать строку, то вылазит ошибка выхода за границы массива.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   char phoneNumber[40];
   char code[3];
   int codeRegion;
   char *codePtr = NULL;
   char *numberPtr = NULL;
 
   cout << "Enter the telephone number in format: (555) 555-5555:\n";
   cin >> phoneNumber;
    
   codePtr = strtok(phoneNumber, " ");
    
   for ( int i = 0; i < 3; i++)
      code[i] = codePtr[i+1];
  
   codeRegion = atoi(code);
    
   codePtr = strtok(NULL, " ");
Проблема в том, что вы портите ту строку, которую сканируете внутри strtok. То есть вам возвращается указатель из этой функции, который указывает на копию вашей строки phoneNumber, которая была сохранена в функции strtok.

Нет, не то я написал. У вас переменная code объявлена, как хранящая 3 символа. А для завершающего 0 места в ней нет. Поэтому когда вы выполняете

codeRegion = atoi(code);
то эта операция выходит за гринцу вашего массива code.

ОБъявите массив code по крайней мере как

C++
1
char code[4];
и после

C++
1
2
for ( int i = 0; i < 3; i++)
      code[i] = codePtr[i+1];
вставьте

C++
1
code[3] = '\0';
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:17  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #3
Цитата Сообщение от Сыроежка Посмотреть сообщение
Проблема в том, что вы портите ту строку, которую сканируете внутри strtok. То есть вам возвращается указатель из этой функции, который указывает на копию вашей строки phoneNumber, которая была сохранена в функции strtok.
Я вроде как это понимаю(или как-то не так понимаю?)
Просто вот этот код для другого упражнения у меня работал

C++
1
2
3
4
5
6
7
8
9
    char *tokenPtr;
    
    tokenPtr = strtok(array1, " ");
    
    while (tokenPtr != NULL)
    {
       printLatinWord(tokenPtr);
        tokenPtr = strtok(NULL, " ");
    }
Добавлено через 4 минуты
Цитата Сообщение от Сыроежка Посмотреть сообщение
Проблема в том, что вы портите ту строку, которую сканируете внутри strtok
C++
1
2
3
4
   codePtr = strtok(phoneNumber, " ");
        
   for ( int i = 0; i < 3; i++)
      code[i] = codePtr[i+1];
в этом куске кода? Если да то всё понятно пойду исправлять.
Сыроежка
Заблокирован
27.10.2011, 20:17     Функция strtok. Представление телефонного номера в виде строки. #4
Цитата Сообщение от Navern Посмотреть сообщение
Я вроде как это понимаю(или как-то не так понимаю?)
Просто вот этот код для другого упражнения у меня работал

C++
1
2
3
4
5
6
7
8
9
    char *tokenPtr;
    
    tokenPtr = strtok(array1, " ");
    
    while (tokenPtr != NULL)
    {
       printLatinWord(tokenPtr);
        tokenPtr = strtok(NULL, " ");
    }
Добавлено через 4 минуты


C++
1
2
3
4
   codePtr = strtok(phoneNumber, " ");
        
   for ( int i = 0; i < 3; i++)
      code[i] = codePtr[i+1];
в этом куске кода? Если да то всё понятно пойду исправлять.
Я исправил свое первое сообщение. Перечитайте его.
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:24  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #5
Цитата Сообщение от Сыроежка Посмотреть сообщение
Я исправил свое первое сообщение. Перечитайте его.
Всё спасибо, совершнно забыл о завершающем нулевом символе. Идиот

Добавлено через 3 минуты
Цитата Сообщение от Сыроежка Посмотреть сообщение
codeRegion = atoi(code);
то эта операция выходит за гринцу вашего массива code.
Кстати сейчас понял, что дело всё таки не в этом или не совсем в этом. Потому что когда я оставлял в упражнении только один экземпляр функции strtok, всё работало и код выводился в виде int значения. А когда добавлял второй экземпляр функции всё рушилось к чертям. Сейчас вроде исправил ошибку с нулём, но не помогло. Тут какая-то беда именно в том, что это цифры, или в том что есть скобки или в каком-то неправильном вызове strtok, только разобраться в этом не могу.
Сыроежка
Заблокирован
27.10.2011, 20:26     Функция strtok. Представление телефонного номера в виде строки. #6
Цитата Сообщение от Navern Посмотреть сообщение
Всё спасибо, совершнно забыл о завершающем нулевом символе. Идиот

Добавлено через 3 минуты

Кстати сейчас понял, что дело всё таки не в этом или не совсем в этом. Потому что когда я оставлял в упражнении только один экземпляр функции strtok, всё работало и код выводился в виде int значения. А когда добавлял второй экземпляр функции всё рушилось к чертям. Сейчас вроде исправил ошибку с нулём, но не помогло. Тут какая-то беда именно в том, что это цифры, или в том что есть скобки или в каком-то неправильном вызове strtok, только разобраться в этом не могу.
Вам надо проверять, не равно ли значение указателя,, возвращаемое функцией strtok, NULL.
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:31  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #7
Цитата Сообщение от Сыроежка Посмотреть сообщение
Вам надо проверять, не равно ли значение указателя,, возвращаемое функцией strtok, NULL.
Да проверил, почему то при втором вызове указатель становится нулёвым. Только мне непонятно почему. У меня есть строка (555) 555-5555. Я из неё выделил в первый раз (555), это стопроцентов я проверил. Почему при втором вызове strtok, над той же строкой возвращается NULL указатель?
Olga_
 Аватар для Olga_
840 / 182 / 16
Регистрация: 01.08.2011
Сообщений: 502
27.10.2011, 20:35     Функция strtok. Представление телефонного номера в виде строки. #8
Предлагаю разбивать строку на слова с помощью более хорошего метода, нежели strtok и очень быстрого:
/cpp-beginners/thread103665/post1880997.html
Функция strtok портит строку, а данный метод быстр и практичен)
Сыроежка
Заблокирован
27.10.2011, 20:41     Функция strtok. Представление телефонного номера в виде строки. #9
Цитата Сообщение от Navern Посмотреть сообщение
Да проверил, почему то при втором вызове указатель становится нулёвым. Только мне непонятно почему. У меня есть строка (555) 555-5555. Я из неё выделил в первый раз (555), это стопроцентов я проверил. Почему при втором вызове strtok, над той же строкой возвращается NULL указатель?
Это скорей всего из-за того, что следующего пробела функция не находит. Думаю, вам в качестве разделителя нужно включить символ конца строки '\n'.

Добавлено через 48 секунд
Цитата Сообщение от Olga_ Посмотреть сообщение
Предлагаю разбивать строку на слова с помощью более хорошего метода, нежели strtok и очень быстрого:
http://www.cyberforum.ru/showthread.php?p=1880997
Функция strtok портит строку, а данный метод быстр и практичен)
Лучше ножниц я другого метода не знаю!
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:54  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #10
Цитата Сообщение от Olga_ Посмотреть сообщение
Предлагаю разбивать строку на слова с помощью более хорошего метода, нежели strtok и очень быстрого:
спасибо, но я пока обучаюсь и задание именно в использовании функции strtok. Так что не подойдет.



Цитата Сообщение от Сыроежка Посмотреть сообщение
Это скорей всего из-за того, что следующего пробела функция не находит. Думаю, вам в качестве разделителя нужно включить символ конца строки '\n'.
Сейчас попробую с этим. Парадокс в том, что когда я ставил разделителем символ '-' эффект был тот же. Плюс одни пробелы работали нормально, когда дело было со словами в предложении. В чем тут отличие не пойму.

Добавлено через 6 минут
Вообщем я не очень понял, но если вводить телефон в формате (555)555-5555, а не в формате, когда после кода (555) ставится пробел, то не выдает той же ошибки.
Olga_
 Аватар для Olga_
840 / 182 / 16
Регистрация: 01.08.2011
Сообщений: 502
27.10.2011, 21:11     Функция strtok. Представление телефонного номера в виде строки. #11
Цитата Сообщение от Сыроежка Посмотреть сообщение
Лучше ножниц я другого метода не знаю!
Там правда ОЧЕНЬ хороший метод. А можете хоть немного поподробнее про метод ножниц?
Jupiter
Каратель
Эксперт C++
6545 / 3965 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2011, 21:24     Функция strtok. Представление телефонного номера в виде строки. #12
Цитата Сообщение от Olga_ Посмотреть сообщение
А можете хоть немного поподробнее про метод ножниц?
strtok и есть метод ножниц
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 21:38  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #13
Вообщем как итог всё заработало, когда я стал вбивать код вместе с остальным телефонным номером без пробелов. Как это пофиксить так и не понял.
Olga_
 Аватар для Olga_
840 / 182 / 16
Регистрация: 01.08.2011
Сообщений: 502
27.10.2011, 21:41     Функция strtok. Представление телефонного номера в виде строки. #14
Цитата Сообщение от Jupiter Посмотреть сообщение
strtok и есть метод ножниц
Но это не очень хорошая функция, можно сделать лучше и в то же время быстро. Тем более таким же методом (ножниц) можно написать функцию быстрее чем strtok (не намного, но все же)
Thinker
Эксперт C++
 Аватар для Thinker
4216 / 2190 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
27.10.2011, 22:00     Функция strtok. Представление телефонного номера в виде строки. #15
Цитата Сообщение от Olga_ Посмотреть сообщение
Но это не очень хорошая функция

Не по теме:

Поддерживаю, сам задумывался над этим вопросом и редко использую strtok



Добавлено через 5 минут
При этом это можно сделать быстрее, поменяв такой код
C
1
2
3
len = strlen(DELIMITERS);
for (i = 0; i < len; i++)
     flag[DELIMITERS[i]] = 1;
на такой
C
1
2
for (i = 0; DELIMITERS[i]; i++)
     flag[DELIMITERS[i]] = 1;
то есть минус один проход по строке DELIMITERS
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9383 / 5433 / 916
Регистрация: 25.07.2009
Сообщений: 10,428
27.10.2011, 22:30     Функция strtok. Представление телефонного номера в виде строки. #16
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
 
typedef struct PHONE {
    int pref;
    int first;
    int second;
} phone_t;
 
int main(void){
    phone_t p;
    
    printf("Enter phone number (xxx)xxx-xxx > ");
    if ( scanf("(%3d)%3d-%4d", &p.pref, &p.first, &p.second) != 3 )
        printf("Wrong input!\n");
    else
        printf("%03d %03d %04d\n", p.pref, p.first, p.second);
    
    return 0;
}
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 23:11  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #17
Вышеупомянутый ответ не работает, потому что это упражнение именно на работу со строками и функцией strtok. Плюс до структур по этому учебнику еще не дошел.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9383 / 5433 / 916
Регистрация: 25.07.2009
Сообщений: 10,428
28.10.2011, 00:03     Функция strtok. Представление телефонного номера в виде строки. #18
Цитата Сообщение от Navern Посмотреть сообщение
Вышеупомянутый ответ не работает
С какого перепуга?
Функция strtok. Представление телефонного номера в виде строки.

Цитата Сообщение от Navern Посмотреть сообщение
именно на работу со строками и функцией strtok
так бы и написал, что нужно гланды через зад удалить...
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
enum PHONE_PARTS { PP_PREF = 0, PP_FIRST, PP_SECOND, PP_ALL };
#define DELIM "() -"
 
int main(void){
    char numStr[] = "(495)123-4567", *p;
    int numArr[PP_ALL];
    
    if ( ! ( p = strtok(numStr, DELIM) ) || sscanf(p, "%d", &numArr[PP_PREF]) != 1 ||
        ! ( p = strtok(NULL, DELIM) ) || sscanf(p, "%d", &numArr[PP_FIRST]) != 1 || 
        ! ( p = strtok(NULL, DELIM) ) || sscanf(p, "%d", &numArr[PP_SECOND]) != 1 ){
            fprintf(stderr, "Parsing error!\n");
            exit(1);
    }
    
    printf("%3d %3d %4d\n", numArr[PP_PREF], numArr[PP_FIRST], numArr[PP_SECOND]);
    
    exit(0);
}
И что характерно, тоже работает
Функция strtok. Представление телефонного номера в виде строки.
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
28.10.2011, 01:11  [ТС]     Функция strtok. Представление телефонного номера в виде строки. #19
Цитата Сообщение от easybudda Посмотреть сообщение
так бы и написал
Цитата Сообщение от Navern Посмотреть сообщение
Задание звучит так, используя функцию strtok, разбить телефонный номер формата (555) 555-5555, введенный как строку
Собственно, что я и сделал В моей версии уже тоже заработало кстати. Не совсем так как хотелось бы.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.10.2011, 08:50     Функция strtok. Представление телефонного номера в виде строки.
Еще ссылки по теме:

C++ Вернуть текстовое представление уравнения в виде строки
Перечисления enum. Хранение типа телефонного номера C++
Использование STRTOK Разбить строку на слова, из слов составить список C++ Функция strtok C++
C++ Функция strtok и занесение в массив
Функция разделения строки на лексемы strtok C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
28.10.2011, 08:50     Функция strtok. Представление телефонного номера в виде строки. #20
Цитата Сообщение от Navern
Задание звучит так, используя функцию strtok, разбить телефонный номер формата (555) 555-5555, введенный как строку, на лексемы. Где первой лексемой будет код, второй первые три цифры номера, а третьей после четыре цифры.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main(void)
{
    char line[] = " (123) 456-7890 ", *p;
    int pref, part1, part2;
    
    if ((p = strtok(line, " ()")) != NULL)
        pref = atoi(p);
    
    if ((p = strtok(NULL, " -")) != NULL)
        part1 = atoi(p);
    
    if ((p = strtok(NULL, " ")) != NULL)
        part2 = atoi(p);
    
    printf("[%d][%d][%d]\n", pref, part1, part2);
    
    return 0;
}
Код
[guest@localhost tests]$ .ansi t.c -o t
[guest@localhost tests]$ ./t
[123][456][7890]
[guest@localhost tests]$
для точной обработки используй конечный автомат

также телефоны могут содержать нули, типа "(012) 034-0056"
тогда atoi() и хранение в int не подходит
Yandex
Объявления
28.10.2011, 08:50     Функция strtok. Представление телефонного номера в виде строки.
Ответ Создать тему
Опции темы

Текущее время: 21:33. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru