Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
1

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

27.10.2011, 20:05. Просмотров 2043. Ответов 20
Метки нет (Все метки)

Запутался в функции 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, " ");
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.10.2011, 20:05
Ответы с готовыми решениями:

Использование STRTOK Разбить строку на слова, из слов составить список C++ Функция strtok
Задача Дана строка слов с разделителями, в данном примере слова с пробелами...

Функция разделения строки на лексемы strtok
Программе на вход подается строка, содержащая слова один-девять плюс минус,...

Вернуть текстовое представление уравнения в виде строки
последний пункт задания лабы: Вернуть текстовое представление уравнения в виде...

Представление в виде строки, где триады цифр отделены друг от друга пробелами
Здравствуйте, задача такова: для заданного натурального числа n получить его...

Генератор слов для телефонного номера
Вот такая вот интересная задачка у Дейтела есть: 17.13. (Генератор слов для...

20
Сыроежка
Заблокирован
27.10.2011, 20:11 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';
0
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:17  [ТС] 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];
в этом куске кода? Если да то всё понятно пойду исправлять.
0
Сыроежка
Заблокирован
27.10.2011, 20:17 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];
в этом куске кода? Если да то всё понятно пойду исправлять.
Я исправил свое первое сообщение. Перечитайте его.
1
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 20:24  [ТС] 5
Цитата Сообщение от Сыроежка Посмотреть сообщение
Я исправил свое первое сообщение. Перечитайте его.
Всё спасибо, совершнно забыл о завершающем нулевом символе. Идиот

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

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

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

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



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

Добавлено через 6 минут
Вообщем я не очень понял, но если вводить телефон в формате (555)555-5555, а не в формате, когда после кода (555) ставится пробел, то не выдает той же ошибки.
0
Olga_
842 / 184 / 18
Регистрация: 01.08.2011
Сообщений: 502
27.10.2011, 21:11 11
Цитата Сообщение от Сыроежка Посмотреть сообщение
Лучше ножниц я другого метода не знаю!
Там правда ОЧЕНЬ хороший метод. А можете хоть немного поподробнее про метод ножниц?
0
Jupiter
Каратель
Эксперт С++
6570 / 3991 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2011, 21:24 12
Цитата Сообщение от Olga_ Посмотреть сообщение
А можете хоть немного поподробнее про метод ножниц?
strtok и есть метод ножниц
0
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 21:38  [ТС] 13
Вообщем как итог всё заработало, когда я стал вбивать код вместе с остальным телефонным номером без пробелов. Как это пофиксить так и не понял.
0
Olga_
842 / 184 / 18
Регистрация: 01.08.2011
Сообщений: 502
27.10.2011, 21:41 14
Цитата Сообщение от Jupiter Посмотреть сообщение
strtok и есть метод ножниц
Но это не очень хорошая функция, можно сделать лучше и в то же время быстро. Тем более таким же методом (ножниц) можно написать функцию быстрее чем strtok (не намного, но все же)
0
Thinker
Эксперт С++
4234 / 2208 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
27.10.2011, 22:00 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
0
easybudda
Модератор
Эксперт CЭксперт С++
10147 / 6054 / 1521
Регистрация: 25.07.2009
Сообщений: 11,476
27.10.2011, 22:30 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;
}
1
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
27.10.2011, 23:11  [ТС] 17
Вышеупомянутый ответ не работает, потому что это упражнение именно на работу со строками и функцией strtok. Плюс до структур по этому учебнику еще не дошел.
0
easybudda
Модератор
Эксперт CЭксперт С++
10147 / 6054 / 1521
Регистрация: 25.07.2009
Сообщений: 11,476
28.10.2011, 00:03 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. Представление телефонного номера в виде строки.
0
Navern
4 / 4 / 0
Регистрация: 01.10.2011
Сообщений: 33
28.10.2011, 01:11  [ТС] 19
Цитата Сообщение от easybudda Посмотреть сообщение
так бы и написал
Цитата Сообщение от Navern Посмотреть сообщение
Задание звучит так, используя функцию strtok, разбить телефонный номер формата (555) 555-5555, введенный как строку
Собственно, что я и сделал В моей версии уже тоже заработало кстати. Не совсем так как хотелось бы.
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
28.10.2011, 08:50 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 не подходит
0
28.10.2011, 08:50
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.10.2011, 08:50

Перечисления enum. Хранение типа телефонного номера
Ввести в массив структур N записей из телефонной книжки (фамилия, имя, номер...

Функция strtok()
Доброе время суток! Подскажите пожалуйста в чем проблема и как с ней...

функция strtok
расскажите алгоритм char str =&quot;- This, a sample string.&quot;; char * pch; ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru