0

This is a program I wrote (not including "string.h") which is meant to convert a string to upper case. It works with a single string - so far so good.

I run into trouble when I try to create an array of strings so I can test various strings in turn as part of a loop.

So, I don't understand why the program works when my string is declared as char test_string[] = "TEST"; but it does not work when I declare an array of pointers to strings.

This is the working single string version (followed by the non-working array of strings version):

#include <stdio.h>

void toAlpha(char*);
int str_len(char*);

int main()
{
    char test_string[] = "TEST";            /* string to test */
    char *pStr = NULL;                  /* pointer to string */

        pStr = test_string;
        toAlpha(pStr);
        printf("%s\n", pStr);


    return 0;
}


void toAlpha(char *arg)
{
    int i = 0;                  /* counter - original string*/
    int j = 0;                  /* counter - temp string */

    /* check each character in original and save alphabetic characters only */
    for ( i = 0; i < str_len(arg); i++ )
    {
        if( *(arg + i) >= 'a' && *(arg + i) <= 'z' )
            *(arg + j++) = *(arg + i);
        else
            if ( *(arg + i) >= 'A' && *(arg + i) <= 'Z' )
                *(arg + j++) = *(arg + i) - 'A' + 'a';
    }

    /* add a null character terminator */
    *(arg + j) = '\0';

}


int str_len(char *arg)
{
    /*return count of letters in a C string */
    int i = 0;
    if ( arg != NULL )
        while ( arg[i] != '\0' )
            i++;
    return i;
}

This is the non-working version with the failed attempt to use an array (it compiles but crashes at runtime):

#include <stdio.h>

void toAlpha(char*);
int str_len(char*);
void palindrome(char*);

int main()
{
    char *test_strings[1];                      /* strings to test */
    char *pStr = NULL;                          /* pointer to string */
    int i = 0;                                  /* loop counter */

    test_strings[0] = "TEST1";
    test_strings[1] = "TEST2";

    for (i = 0; i < 1; i++){
        pStr = test_strings[i];
        toAlpha(pStr);
        printf("%s\n", pStr);
    }

    return 0;
}


void toAlpha(char *arg)
{
    int i = 0;                  /* counter - original string*/
    int j = 0;                  /* counter - temp string */

    /* check each character in original and save alphabetic characters only */
    for ( i = 0; i < str_len(arg); i++ )
    {
        if( *(arg + i) >= 'a' && *(arg + i) <= 'z' )
            *(arg + j++) = *(arg + i);
        else
            if ( *(arg + i) >= 'A' && *(arg + i) <= 'Z' )
                *(arg + j++) = *(arg + i) - 'A' + 'a';
    }

    /* add a null character terminator */
    *(arg + j) = '\0';

}


int str_len(char *arg)
{
    /*return count of letters in a C string */
    int i = 0;
    if ( arg != NULL )
        while ( arg[i] != '\0' )
            i++;
    return i;
}
5
  • 2
    2 words undefined behaviour Commented Feb 15, 2014 at 22:28
  • stackoverflow.com/questions/8302290/… or for more google.com/#q=undefined+behaviour+c+char* Commented Feb 15, 2014 at 22:28
  • 1
    There might be undefined behavior elsewhere, but this line: test_strings[1] = "TEST2"; is certainly undefined behavior. Commented Feb 15, 2014 at 22:28
  • 1
    2 more words syntactical sugar -- that is char foo[] = "......"; as you do in your first example is a special kind of syntactical sugar. See the first SO link in the comments for the details explanation Commented Feb 15, 2014 at 22:47
  • Thanks. I've been reading the links and finding some other posts about this here at stack overflow. Will comply! The syntactical sugar was sweet, at least for a little while. Commented Feb 15, 2014 at 23:31

3 Answers 3

1

I found the error. You can't modify string literal. To fix this you need to substitute the following:

test_strings[0] = "TEST1";
test_strings[1] = "TEST2";

by:

test_strings[0] = (char *) malloc(sizeof(char) * (strlen("TEST1") + 1)); // +1 for the \n
test_strings[1] = (char *) malloc(sizeof(char) * (strlen("TEST2") + 1)); // +1 for the \n
strcpy(test_strings[0], "TEST1");
strcpy(test_strings[1], "TEST2");

Since you don't want to include string.h it seems that you need to implement the function strcpy. Also you need to include stdlib.h (because of malloc).

Sign up to request clarification or add additional context in comments.

1 Comment

Okay. I'm convinced. Will give it a try. I think I'll break down and add string.h too - not writing any more of my own string functions tonight!
0

You have to include "stdio.h" for NULL macro and printf. The runtime problem is because you have an array of 1 element and you are assigning "TEST2" into the non-existing second position. I don't understand what you want to do in toAlpha().

#include <stdio.h>

// ...

int main()
{
    char *test_strings[2];                      /* strings to test */
    char *pStr = NULL;                          /* pointer to string */

    test_strings[0] = "TEST1";
    test_strings[1] = "TEST2";

    for (int i = 0; i < 2; ++i)
    {
        pStr = test_strings[i];
        toAlpha(pStr);
        printf("%s\n", pStr);
    }

    return 0;
}

// ...

4 Comments

I thought NULL was supposed to be defined in stdlib.h, see e.g. linux.die.net/man/3/malloc
@Brandin: Your link does not specify where NULL is defined, stdlib.h could include stddef.h However, my answer is incorrect (edited), since it is not necessary to include stddef.h, because NULL is defined in both, stddef.h and stdio.h. See... en.cppreference.com/w/cpp/header/cstddef en.cppreference.com/w/cpp/header/cstdio en.cppreference.com/w/cpp/header/cstdlib
Thanks - added stdlib.h. It should have been there.
To be more precise, a pointer directly to C Standard (ISO/IEC 9899:201x - N1570). 7.19 Common definitions <stddef.h> - Paragraph 3, and, 7.21 Input/output <stdio.h> Paragraph 3
0

Okay. Rewrote both programs. Hopefully better this time. But used string.h library in lieu of writing my own strcpy function. Though I didn't describe toAlpha properly. It's meant to remove any non-alphabetic characters, and to return the result as all lower-case letters. --Topsail

First program (single string):

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

    void toAlpha(char*);
    int str_len(char*);

    int main()
    {
        char test_string[100];              /* string to test */
        char *pStr = NULL;                  /* pointer to string */

            strcpy(test_string, "Test-A");
            pStr = test_string;
            toAlpha(pStr);
            printf("%s\n", pStr);


        return 0;
    }


    void toAlpha(char *arg)
    {
        int i = 0;                  /* counter - original string*/
        int j = 0;                  /* counter - temp string */

        /* check each character in original and save alphabetic characters only */
        for ( i = 0; i < str_len(arg); i++ )
        {
            if( *(arg + i) >= 'a' && *(arg + i) <= 'z' )
                *(arg + j++) = *(arg + i);
            else
                if ( *(arg + i) >= 'A' && *(arg + i) <= 'Z' )
                    *(arg + j++) = *(arg + i) - 'A' + 'a';
        }

        /* add a null character terminator */
        *(arg + j) = '\0';

    }


    int str_len(char *arg)
    {
        /*return count of letters in a C string */
        int i = 0;
        if ( arg != NULL )
            while ( arg[i] != '\0' )
                i++;
        return i;
    }

second program with array of strings:

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

    void toAlpha(char*);
    int str_len(char*);
    void palindrome(char*);

    int main()
    {
        char *test_strings[2];                      /* strings to test */
        char *pStr = NULL;                          /* pointer to string */
        int i = 0;                                  /* loop counter */

        test_strings[0] = (char *) malloc(sizeof(char) * (strlen("TEST-A") + 1));
        strcpy(test_strings[0], "TEST-A");
        test_strings[1] = (char *) malloc(sizeof(char) * (strlen("TEST-1") + 1));
        strcpy(test_strings[1], "TEST-B");


        for (i = 0; i < 2; i++){
            pStr = test_strings[i];
            toAlpha(pStr);
            printf("%s\n", pStr);
            free(pStr);
        }

        return 0;
    }


    void toAlpha(char *arg)
    {
        int i = 0;                  /* counter - original string*/
        int j = 0;                  /* counter - temp string */

        /* check each character in original and save alphabetic characters only */
        for ( i = 0; i < str_len(arg); i++ )
        {
            if( *(arg + i) >= 'a' && *(arg + i) <= 'z' )
                *(arg + j++) = *(arg + i);
            else
                if ( *(arg + i) >= 'A' && *(arg + i) <= 'Z' )
                    *(arg + j++) = *(arg + i) - 'A' + 'a';
        }

        /* add a null character terminator */
        *(arg + j) = '\0';

    }


    int str_len(char *arg)
    {
        /*return count of letters in a C string */
        int i = 0;
        if ( arg != NULL )
            while ( arg[i] != '\0' )
                i++;
        return i;
    }

1 Comment

Note: as it turns out implementing a string copy function is not difficult, as an exercise. See notes (and cautions) here: stackoverflow.com/questions/5695992/… and also Kernighan and Ritchie 2nd edition section 5.5.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.