функция Стрлена в с - PullRequest
       4

функция Стрлена в с

0 голосов
/ 03 ноября 2011

Это может звучать немного глупо, но я в замешательстве. Я знаю, что strlen () вернет размер массива символов в c. Но с указателями на характер происходит нечто иное. Это мой код:

void xyz(char *number)
{
    int i = 0;
    int length = strlen(number) - 2;
    while(i <= length)
    {
        printf("Number[]: %c",number[i]);
        i++;
    }
}

Это печатает все введенное мной число (например, 12345), но если я уберу -2, результат будет не таким. Кто-нибудь может сказать мне, что мне не хватает?

Ответы [ 6 ]

6 голосов
/ 03 ноября 2011

Есть большая вероятность, что вы делаете это со строкой, которую вы получили с помощью fgets или аналогичной функции ввода. В этом случае вполне может быть еще перевод строки в конце.

Если вы временно измените свой код на:

void xyz (char *number) {
    int i = 0, length = strlen (number);
    while (i < length)
        printf ("Number[%d]: %c (%d)", i, number[i], number[i]);
        i++;
    }
}

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

Проблема с кодированием чего-то подобного - 2 в вашей функции заключается в том, что она не будет работать с:

xyz ("123");

, так как он остановится рано, выводится только 12. вызывающий абонент должен вызывать с допустимыми данными, что означает, что он должен изменить значение, чтобы оно было числовой строкой перед вызовом.


Вы можете увидеть это в следующей программе:

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

void xyz (char *number) {
    int i = 0, length = strlen(number) - 2;
    while(i <= length)
    {
        printf("Number[%d]: %c (%d)\n",i, number[i], number[i]);
        i++;
    }
    puts ("===");
}

void xyz2 (char *number) {
    int i = 0, length = strlen(number);
    while(i < length)
    {
        printf("Number[%d]: %c (%d)\n",i, number[i], number[i]);
        i++;
    }
    puts ("===");
}

int main (void) {
    char buff[100];
    printf ("Enter number: ");
    fgets (buff, sizeof (buff), stdin);
    xyz (buff);
    xyz ("12345");
    xyz2 (buff);
    xyz2 ("12345");
    return 0;
}

(аннотированный) результат этого, если вы введете 98765, будет:

Enter number: 98765
Number[0]: 9 (57)
Number[1]: 8 (56)
Number[2]: 7 (55)  # Your adjustment works here because of the newline.
Number[3]: 6 (54)
Number[4]: 5 (53)
===
Number[0]: 1 (49)
Number[1]: 2 (50)
Number[2]: 3 (51)  # But not here, since it skips last character.
Number[3]: 4 (52)
===
Number[0]: 9 (57)
Number[1]: 8 (56)
Number[2]: 7 (55)  # Here you can see the newline (code 10).
Number[3]: 6 (54)
Number[4]: 5 (53)
Number[5]:
 (10)
===
Number[0]: 1 (49)
Number[1]: 2 (50)
Number[2]: 3 (51)  # And proper numeric strings work okay.
Number[3]: 4 (52)
Number[4]: 5 (53)
===

Если вы ищете надежную функцию пользовательского ввода, которая решает эту проблему (и позволяет избежать опасных вещей, таких как неограниченные scanf("%s") и gets), у меня есть еще одна в SO (справа ЗДЕСЬ ) на самом деле) взят из моего арсенала.

1 голос
/ 03 ноября 2011

Я сделал это и получил вывод, подобный этому:

strlen(number)-2 удаляет последний ноль и последний символ, который содержит 4.

Выход:

Number[]: 1
Number[]: 2
Number[]: 3

Код:

int main()
{
    xyz("1234");
}
void xyz(char *number)
{
    int i=0;
    int length = strlen(number) - 2;
    while(i <= length)
    {
        printf("\nNumber[]: %c",number[i]);
        i++;
    }
}

Это работает, и вы должны инициализировать i.

1 голос
/ 03 ноября 2011

Проверьте, работает ли это для вас -

void xyz(char *number)
{
    int length = strlen(number);

    while(i < length)
    {
        printf("Number[]: %c",number[i]);
        i++;
    }
}

и эта функция, если она вызывается как

xyz("1234");

, должна распечатать:

Number[]: 1
Number[]: 2
Number[]: 3
Number[]: 4

Isэто то, что вы действительно хотели?Если так, то позвольте мне указать 2 ошибки.

1) «i» не инициализировано.Это больше вопрос хорошей практики.Явно инициализируйте переменную управления циклом (в данном случае, ноль), только не думайте, что она установлена.2) условие цикла while с «<=» запускает 1 дополнительный цикл, как и должно. </p>

Помните, что массивы начинаются с индекса '0' (ноль), а массив размера 10 имеет допустимый индекс от 0до 9, и C lang использует нулевой символ ('\ 0'), чтобы завершить строку.Таким образом, ваш «1234» фактически сохраняется как: -

string [0] = '1' string [1] = '2' string [2] = '3' string [3] = '4'string [4] = '\ 0' (<= NULL) </p>

, поэтому, если ваш счетчик цикла (управляющая переменная) i = 0 в начале цикла, для первой итерации вы выбираете string [0], идля 2-й итерации (когда i = 1) вы выбираете строку [1] ... и, таким образом, цикл должен выполняться только 4 раза, т.е. когда i == 4 (т. е. loopcounter <длина строки), вы должны остановиться и выйтицикл. </p>

Надеюсь, это прояснит ваши сомнения и поможет.Если это так, пожалуйста, не забудьте принять ответ.

0 голосов
/ 03 ноября 2011

На самом деле вам нужно сделать:

int length = strlen(number) - 1;

Чтобы получить правильный вывод.

Кроме того, вы должны помнить, что вы передаете массив символов в функцию xyz.Поэтому, если вы сделали следующее:

xyz("12345")

ваша длина будет 5 байтов.В вашем цикле while ваш индекс for number[i] фактически начинается с 0, а не с 1, поэтому вам нужно вычесть 1, чтобы получить правильный результат, поэтому вы используете int length = strlen(number) - 1.

0 голосов
/ 03 ноября 2011

Полагаю, вы используете fgets для чтения каких-либо данных. Если это так, когда вы введете «12345» и нажмете «Enter», ваш буфер будет выглядеть так:

{'1', '2', '3', '4', '5', '\ n', '\ 0'}

Как видите, нам не нужны 2 символов. Итак, что мы можем сделать для начала, это отрезать новую строку char, '\n' от конца вашего буфера.

Итак, представьте, что мы читаем на входе:

int main(void)
{
   char buff[20];
   fgets(buff, 20, stdin);

   buff[strlen(buff) - 1] = '\0'; /* remove the '\n' */
   xyz(buff);
}

Теперь этого раздражающего символа новой строки не будет, и то, что будет выглядеть как пустой вывод для последней итерации цикла, исчезнет. Теперь для xyz:

void xyz(char *number)
{
   int i, length = strlen(number);
   for (i = 0; i < length; i++)
      printf("Number[%d]: %c", i, number[i]);
}

Обратите внимание, что теперь мы не вычитаем что-либо из длины. Это по двум причинам: во-первых, я упомянул выше о новой строке, и во-вторых, потому что условие теперь < length, а не <= length (о котором я упоминал в комментарии выше). <= length означает, что мы будем читать 1 после конца строки (символ '\ 0'), так как первый индекс равен number[0], а последний number[length - 1].

0 голосов
/ 03 ноября 2011

strlen() возвращает длину строки, но массивы C и, следовательно, строки индексируются нулем. Таким образом, вы хотите увеличить, пока не достигнете strlen() - 1. Вы можете сделать это, либо вычтя один из своей длины и используя критерий «меньше или равный» - <= - в цикле while, либо вы можете просто использовать strlen() и продолжить цикл, пока ваш счетчик равен строго меньше вашей длины.

Возможные источники ошибок:

  1. Если вы не инициализируете i, шансы - это значение, полученное из того, что было ранее в этой ячейке памяти, намного выше длины. Таким образом, ваше условие while не выполнится при первом выполнении.
  2. Если пройти за конец строки, вы увидите символ NULL - '\0' - в конце строки и случайный мусор за ним.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...