tags:

views:

537

answers:

2

So I have a program that makes char* stuff lowercase. It does it by iterating through and manipulating the ascii. Now I know there's probably some library for this in c++, but that's not the point - I'm a student trying to get a grasp on char*s and stuff :).

Here's my code:

#include <iostream>

using namespace std;

char* tolower(char* src);

int main (int argc, char * const argv[])
{
    char* hello = "Hello, World!\n";

    cout << tolower(hello);
    return 0;
}

char* tolower(char* src)
{
    int ascii;
    for (int n = 0; n <= strlen(src); n++)
    {
     ascii = int(src[n]);
     if (ascii >= 65 && ascii <= 90)
     {
      src[n] = char(ascii+32);
     }
    }

    return src;
}

( this is not for an assignment ;) )

It builds fine, but when I run it it I get a "The Debugger has exited due to signal 10" and Xcode points me to the line: "src[n] = char(ascii+32);"

Thanks!

Mark

+8  A: 

Yowsers!

Your "Hello World!" string is what is called a string literal, this means its memory is part of the program and cannot be written to.

You are performing what is called an "in-place" transform, e.g. instead of writing out the lowercase version to a new buffer you are writing to the original destination. Because the destination is a literal and cannot be written to you are getting a crash.

Try this;

char hello[32];
strcpy(hello, "Hello, World!\n");

Also in your for loop, you should use <, not <=. strlen returns the length of a string minus its null terminator, and array indices are zero-based.

Andrew Grant
Good answer, but for completeness, strlcpy() is preferred.
Randy Proctor
how about char hello[] = "Hello World\n"
anon
Quick comment but for completless "Hello, World!\n" is constant no need to check length.
Tim Matthews
+7  A: 

As Andrew noted "Hello World\n" in code is a read-only literal. You can either use strcpy to make a modifiable copy, or else try this:

char hello[] = "Hello, World!\n";

This automatically allocates an array on the stack big enough to hold a copy of the literal string and a trailing '\0', and copies the literal into the array.

Also, you can just leave ascii as a char, and use character literals instead of having to know what the numeric value of 'A' is:

char ascii;
for (int n = 0; n < strlen(src); n++)
{
    ascii = src[n];
    if (ascii >= 'A' && ascii <= 'Z')
    {
        src[n] = ascii - 'A' + 'a';
    }
}

While you're at it, why bother with ascii at all, just use src[n]:

for (int n = 0; n < strlen(src); n++)
{
    if (src[n] >= 'A' && src[n] <= 'Z')
    {
        src[n] -= 'A' - 'a';
    }
}

And then, you can take advantage of the fact that in order to determine the length of a c-string, you have to iterate though it anyway, and just combine both together:

for (char *n = src; *n != 0; n++)
    if (*n >= 'A' && *n <= 'Z')
        *n -= 'A' - 'a';
Eclipse