Vincent
Vincent

Reputation: 4056

How to iterate over a string in C?

Right now I'm trying this:

#include <stdio.h>

int main(int argc, char *argv[]) {

    if (argc != 3) {

        printf("Usage: %s %s sourcecode input", argv[0], argv[1]);
    }
    else {
        char source[] = "This is an example.";
        int i;

        for (i = 0; i < sizeof(source); i++) {

            printf("%c", source[i]);
        }
    }

    getchar();

    return 0;
}

This does also NOT work:

char *source = "This is an example.";
int i;

for (i = 0; i < strlen(source); i++){

    printf("%c", source[i]);
}

I get the error

Unhandled exception at 0x5bf714cf (msvcr100d.dll) in Test.exe: 0xC0000005: Access violation while reading at position 0x00000054.

(loosely translated from german)

So what's wrong with my code?

Upvotes: 83

Views: 363543

Answers (14)

anon
anon

Reputation:

You want:

for (i = 0; i < strlen(source); i++) {

sizeof gives you the size of the pointer, not the string. However, it would have worked if you had declared the pointer as an array:

char source[] = "This is an example.";

but if you pass the array to function, that too will decay to a pointer which is why for strings it's best to always use strlen.

Also note what others have said about changing printf to use %c, and, taking mmyers comments on efficiency into account, it would be better to move the call to strlen out of the loop:

int len = strlen(source);
for (i = 0; i < len; i++) {

or rewrite the loop:

for (i = 0; source[i] != 0; i++) {

Upvotes: 91

Mark Lewin
Mark Lewin

Reputation: 11

This is 11 years old but relevant to someone who is learning C. I don't understand why we have all this discussion and disagreement about something so fundamental. A string literal in C, I.E. "Text between quotes" has an implicit null terminator after the last character. Don't let the name confuse you. The null terminator is equal to numeric 0. Its purpose is exactly what OP needs it for:

char source[] = "This is an example.";

for (int i = 0; source[i]; i++)
  printf("%c", source[i]);

A char in C is an 8-bit integer with the numeric ASCII value of the corresponding character. That means source[i] is a positive integer until char[19], which is the null terminator after the final '.' The null character is ASCII 0. This is where the loop terminates. The loop iterates through every character with no regard for the length of the array.

Upvotes: 1

user10167940
user10167940

Reputation:

An optimized approach:

for (char character = *string; character != '\0'; character = *++string)
{
    putchar(character); // Do something with character.
}

Most C strings are null-terminated, meaning that as soon as the character becomes a '\0' the loop should stop. The *++string is moving the pointer one byte, then dereferencing it, and the loop repeats.

The reason why this is more efficient than strlen() is because strlen already loops through the string to find the length, so you would effectively be looping twice (one more time than needed) with strlen().

Upvotes: 11

Edwin Jata
Edwin Jata

Reputation: 21

The last index of a C-String is always the integer value 0, hence the phrase "null terminated string". Since integer 0 is the same as the Boolean value false in C, you can use that to make a simple while clause for your for loop. When it hits the last index, it will find a zero and equate that to false, ending the for loop.

for(int i = 0; string[i]; i++) { printf("Char at position %d is %c\n", i, string[i]); }

Upvotes: 2

Alexandre C.
Alexandre C.

Reputation: 56956

One common idiom is:

char* c = source;
while (*c) putchar(*c++);

A few notes:

  • In C, strings are null-terminated. You iterate while the read character is not the null character.
  • *c++ increments c and returns the dereferenced old value of c.
  • printf("%s") prints a null-terminated string, not a char. This is the cause of your access violation.

Upvotes: 67

ULysses
ULysses

Reputation: 978

You need a pointer to the first char to have an ANSI string.

printf("%s", source + i);

will do the job

Plus, of course you should have meant strlen(source), not sizeof(source).

Upvotes: 0

Mark Ingram
Mark Ingram

Reputation: 73605

Rather than use strlen as suggested above, you can just check for the NULL character:

#include <stdio.h>

int main(int argc, char *argv[])
{
    const char *const pszSource = "This is an example.";
    const char *pszChar = pszSource;

    while (pszChar != NULL && *pszChar != '\0')
    {
        printf("%s", *pszChar);
        ++pszChar;
    }

    getchar();

    return 0;
}

Upvotes: 5

Pablo Santa Cruz
Pablo Santa Cruz

Reputation: 181280

Just change sizeof with strlen.

Like this:

char *source = "This is an example.";
int i;

for (i = 0; i < strlen(source); i++){

    printf("%c", source[i]);

}

Upvotes: 1

Praveen S
Praveen S

Reputation: 10393

sizeof(source) returns sizeof a pointer as source is declared as char *. Correct way to use it is strlen(source).

Next:

printf("%s",source[i]); 

expects string. i.e %s expects string but you are iterating in a loop to print each character. Hence use %c.

However your way of accessing(iterating) a string using the index i is correct and hence there are no other issues in it.

Upvotes: 0

Prasoon Saurav
Prasoon Saurav

Reputation: 92854

This should work

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

 int main(int argc, char *argv[]){

    char *source = "This is an example.";
    int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
    for (int i = 0; i < length; i++) 
    {

       printf("%c", source[i]);

    }


 }

Upvotes: 2

KenE
KenE

Reputation: 1805

  1. sizeof() includes the terminating null character. You should use strlen() (but put the call outside the loop and save it in a variable), but that's probably not what's causing the exception.
  2. you should use "%c", not "%s" in printf - you are printing a character, not a string.

Upvotes: 2

JSBձոգչ
JSBձոգչ

Reputation: 41378

  • sizeof(source) is returning to you the size of a char*, not the length of the string. You should be using strlen(source), and you should move that out of the loop, or else you'll be recalculating the size of the string every loop.
  • By printing with the %s format modifier, printf is looking for a char*, but you're actually passing a char. You should use the %c modifier.

Upvotes: 1

Keith Randall
Keith Randall

Reputation: 23265

Replace sizeof with strlen and it should work.

Upvotes: 0

Jacob
Jacob

Reputation: 34601

sizeof(source) returns the number of bytes required by the pointer char*. You should replace it with strlen(source) which will be the length of the string you're trying to display.

Also, you should probably replace printf("%s",source[i]) with printf("%c",source[i]) since you're displaying a character.

Upvotes: 2

Related Questions