указатели и разбор строк в c - PullRequest
4 голосов
/ 27 июня 2010

Мне было интересно, может ли кто-нибудь объяснить мне, как работают указатели и разбор строк. Я знаю, что могу сделать что-то вроде следующего в цикле, но я все еще не очень хорошо понимаю, как это работает.

  for (a = str;  * a;  a++) ...

Например, я пытаюсь получить последнее целое число из строки. если у меня есть строка как const char *str = "some string here 100 2000";

Используя метод, описанный выше, как я могу проанализировать его и получить последнее целое число строки (2000), зная, что последнее целое число (2000) может отличаться.

Спасибо

Ответы [ 5 ]

8 голосов
/ 27 июня 2010

for (a = str; * a; a++) ...

Это работает, начиная указатель a в начале строки, пока разыменование a неявно преобразуется в false, увеличивая a на каждом шаге.

По сути, вы будете проходить по массиву до тех пор, пока не доберетесь до терминатора NUL, который находится в конце вашей строки (\0), потому что терминатор NUL неявно преобразуется в false - другие символы этого не делают.

Используя метод, описанный выше, как я могу проанализировать его и получить последнее целое число строки (2000), зная, что последнее целое число (2000) может отличаться.

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

Рассмотрим этот подход:

  • найти конец строки (используя этот цикл)
  • поиск назад пробела.
  • используйте это для вызова strtol.

-

for (a = str; *a; a++);  // Find the end.
while (*a != ' ') a--;   // Move back to the space.
a++;  // Move one past the space.
int result = strtol(a, NULL, 10);

Или, в качестве альтернативы, просто отслеживайте начало последнего токена:

const char* start = str;
for (a = str; *a; a++) {     // Until you hit the end of the string.
  if (*a == ' ') start = a;  // New token, reassign start.
}
int result = strtol(start, NULL, 10);

Преимущество этой версии заключается в том, что в строке не требуется пробел.

3 голосов
/ 28 июня 2010

Я знаю, что на этот вопрос уже дан ответ, но все ответы до сих пор представляют собой воссозданный код, который доступен в стандартной библиотеке C. Вот что я бы использовал, воспользовавшись strrchr()

#include <string.h>
#include <stdio.h>

int main(void)
{

    const char* input = "some string here 100 2000";
    char* p;
    long l = 0;

    if(p = strrchr(input, ' '))
        l = strtol(p+1, NULL, 10);

    printf("%ld\n", l);

    return 0;
}

Выход

2000
3 голосов
/ 27 июня 2010

Вам просто нужно реализовать простой конечный автомат с двумя состояниями, например

#include <ctype.h>

int num = 0; // the final int value will be contained here
int state = 0; // state == 0 == not parsing int, state == 1 == parsing int

for (i = 0; i < strlen(s); ++i)
{
    if (state == 0) // if currently in state 0, i.e. not parsing int
    {
        if (isdigit(s[i])) // if we just found the first digit character of an int
        {
            num = s[i] - '0'; // discard any old int value and start accumulating new value
            state = 1; // we are now in state 1
        }
        // otherwise do nothing and remain in state 0
    }
    else // currently in state 1, i.e. parsing int
    {
        if (isdigit(s[i])) // if this is another digit character
        {
            num = num * 10 + s[i] - '0'; // continue accumulating int
            // remain in state 1...
        }
        else // no longer parsing int
        {
            state = 0; // return to state 0
        }
    }
}
0 голосов
/ 27 июня 2010
  for (a = str;  * a;  a++)...

эквивалентно

  a=str;
  while(*a!='\0') //'\0' is NUL, don't confuse it with NULL which is a macro
  {
      ....
      a++;
  }
0 голосов
/ 27 июня 2010

Представленный вами цикл просто проходит все символы (строка - указатель на массив 1-байтовых символов, заканчивающийся 0).Для парсинга вы должны использовать sscanf или лучше C++ 'string и string stream.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...