user10621144
user10621144

Reputation:

Why does strlen() not represent the actual length of my string?

basically I have a string composed of multiple words like this: "Hello world test".
Either if I try to print it with a structure like this

printf("%s", string);

or like this

for (int i = 0; i < strlen(string); ++i) {
    printf("%c", string[i];
}

I always get this as an output: Hello world and I get a strlen of 11 instead of 16 too.

If I try to print out the same exact string with an int counter that previously counts the single chars in the string

for (int i = 0; i < counter; ++i) {
    printf("%c", string[i];
}

I actually get the correct output Hello world test, which leads be to believe that the elements are correctly assigned in the string but for some reason %s and strlen just ignores the ones after the last space.

Why would that happen? What is going on? How can I fix this?

EDIT:

Actual code as requested:

#include <stdio.h>
#include <string.h>
typedef int BOOL;
#define TRUE 1
#define FALSE 0


int main() {
    char sentence[64] = " ", reversal[64] = " ", reversal_copy[64] = " ";
    int index = 0, counter = 0;
    BOOL reset = TRUE, last_cycle = FALSE;

    printf("Enter a sentence: ");
    for (int i = 0; sentence[strlen(sentence) - 1] != '\n'; i++) {
        scanf("%c", &sentence[i]);
    }

    /* Copies the input in a string reversing it */
    for (int h = strlen(sentence) - 2, k = 0; h >= 0; h--, k++) {
        reversal[k] = sentence[h];
    }

    /* Detects the first character of a word and the last character of the same word before a space,
    switching the first char with the last, the second with the pre-last and so on*/
    for (int i = 0; i < strlen(reversal); i++) {
        if (reset == TRUE) {
            index = i;
            reset = FALSE;
        }
        if (i == strlen(reversal) - 1) {
            last_cycle = TRUE;
            counter++;
        }
        if (reversal[i] != ' ') {
            counter++;
            if (last_cycle == TRUE) {
                goto reversing;
            }
        }
        else {
        reversing:
            for (int h = index, z = counter; h < counter; h++, z--) {
                reversal_copy[h] = reversal[z - 1];
                reversal_copy[z - 1] = reversal[h];
            }
            if (last_cycle == FALSE) {
                reversal_copy[i] = ' ';
            }
            reset = TRUE;
            counter++;
        }
    }
    printf("%lu ", strlen(reversal_copy));
    for (int i = 0; i < counter; i++) {
        printf("%c", reversal_copy[i]);
    }
    printf("%s\n\n", reversal_copy);

    return 0;
}

Upvotes: 0

Views: 756

Answers (4)

Swordfish
Swordfish

Reputation: 13144

the program takes a string inputted by the user like "the sky is blue" and prints out "blue is sky the"

That's a perfect job for strtok():

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

enum { MAX_LINE = 120 };

int main()
{
    char buffer[MAX_LINE];
    fgets(buffer, MAX_LINE, stdin);

    size_t length = strlen(buffer);
    if (length && buffer[length - 1] == '\n')  // get rid of the newline
        buffer[--length] = '\0';

    char *tokens[MAX_LINE] = { 0 };  // there can't be more than 60 tokens, but hey
    if ((tokens[0] = strtok(buffer, " ")) == NULL)  // no tokens? nothing to do.
        return 0;

    size_t i = 1;
    for (; tokens[i - 1] && i < sizeof(tokens); ++i)
        tokens[i] = strtok(NULL, " ");  // tokenize the buffer

    --i;  // the very last was NULL anyway.
    while (--i)  // print it reverse
        printf("%s ", tokens[i]);
    puts(buffer);
}

Sample Output:

The quick brown fox jumps over the lazy dog
dog lazy the over jumps fox brown quick The

Upvotes: 0

AShelly
AShelly

Reputation: 35600

Try running your program with the input "A" as an example - see that even a single word exhibits the problem.

Something is going wrong when you reverse the last word. You are putting the trailing '\0' in front of it. It probably has to do with the special casing and the goto around the last_cycle logic, which is very hard to follow.

I think it's probably related to the fact that you have two counter++s in that code path.

Consider using some functions to make the code cleaner:

len = strlen(reversal);
for (start=0; start<len; start++) {
   end = find_space_or_null(reversal, start);
   if (end > start) {
    reverse_chars(reversal, start, end-1);
    start = end;
   }
}

Upvotes: 0

Govind Parmar
Govind Parmar

Reputation: 21572

While this is difficult to answer without a Minimal, Complete, and Verifiable example, I will explain the most likely reason for the behavior you're observing.

Both printf with the %s format specifier and strlen give you the length of the null-terminated string pointed to by the relevant argument. If they are printing/reporting a length of 11, but iterating through the entire char array with a hard-coded value of 16 gives you the output "hello world test", then the character after world is clearly the null character, '\0'.

Upvotes: 1

John3136
John3136

Reputation: 29266

if strlen() returns 11 then you have a \0 char after the world "world".

strlen and printf both determine "what is a string" by using the 0 terminator, so no surprise that they behave the same.

Upvotes: 4

Related Questions