Неправильный расчет длины строки, когда не выводится возвращаемое значение программы - PullRequest
0 голосов
/ 04 января 2019

Предполагается, что длина вернет, как далеко продвинулся счетчик при прохождении через строку.Тем не менее, он возвращает правильное значение только тогда, когда он напечатан заранее.Если я закомментирую printf, он возвращает 0. У кого-нибудь есть объяснение этому?

#include<stdio.h>
#include<string.h>
#define MAX 100

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i)
        printf("%d ", i);           //<-- here
    return i;
}

int main() 
{
    char s[MAX];
    fgets(s, (char)sizeof(s), stdin);
    s[strcspn(s, "\n")]='\0';
    printf("Length: %d\n", length(s));
    return 0;
}

Ответы [ 3 ]

0 голосов
/ 04 января 2019

В цикле, подобном следующему:

for (...)
    statement1;
statement2;

statement1 будет единственным, что выполняется в цикле.Когда вы закомментируете вызов printf, return i; выполняется на самой первой итерации, сразу же возвращая ноль.

Однако обратите внимание, что statement1 может быть пустым, поэтому для запуска цикла сбез тела, делай:

for (...)
    ; // yes, a hanging semicolon

// or like this:
for (...);
0 голосов
/ 04 января 2019

Если вы просто закомментируете это printf, у вас останется следующее:

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i)
    return i;
}

Это равно:

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i){
        return i; // returns in the first iteration, without even incrementing i once
    }
}

Конечно, это не то, что выпредназначена.Вместо этого поставьте точку с запятой после цикла for:

for (i = 0; s[i] != '\0'; ++i);

Таким образом, for (i = 0; s[i] != '\0'; ++i); не повлияет случайно на следующее утверждение.

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

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i) {
        printf("%d ", i);           //<-- here
    }
    return i;
}

Теперь, если вы удалите строку printf, это никак не повлияет на выполнение программы, кроме пропуска печати. ​​

0 голосов
/ 04 января 2019

Проблема в том, что если вы закомментируете оператор printf() в функции length(), оператор return становится частью тела цикла, и самая первая итерация возвращается из вызова, и вы получаете the-then значение i, которое является просто значением записи для цикла, 0.

for (i = 0; s[i] != '\0'; ++i)
    //printf("%d ", i);           //<-- here
return i;                         // without brace-enfoced scope, this is the loop body.

совпадает с

for (i = 0; s[i] != '\0'; ++i)
return i;                                

ЧтоВам необходим цикл, чтобы завершить выполнение, выполнить критерии выхода, а затем выполнить оператор return с самым последним значением i.

Таким образом, чтобы избежать проблемы, вы можете принудительно выполнить пустое выполнение цикла, например,

for (i = 0; s[i] != '\0'; ++i) ;   // notice the ; here, ends the scope.
return i; 

или, что еще лучше (для читателей)

for (int i = 0; i < 10; i++) 
    {/*nothing here*/}       //indicates empty loop body
return i;

Примечание. В качестве альтернативного способа повышения читабельности вместо конструкции for можно также использовать цикл while, который выглядит как

while (s[i] != '\0') 
{
    i++;                     //increment statement is explicit.
}
...