0

This is for a school assignment. The goal of this function is to randomly select a word from each array and create a new array with the first letter of each sentence capitalized, spaces between each word, and a period in the end 20 times. The sentence follows the format article, noun, verb, preposition, article, and noun.

My question is how do I go about capitalizing the first letter of each sentence? I tried to set the first position in the string to equal the char at that position - 32, but that just crashes the program.

void randomize(void) {

    char *article[] = {"the", "a", "one", "some", "any"};
    char *noun[] = {"boy", "girl", "dog", "town", "car"};
    char *verb[] = {"drove", "jumped", "ran", "walked", "skipped"};
    char *preposition[] = {"to", "from", "over", "under", "on"};
    char *sentence[6];

    int running = 1;

    while(running){

        int location = rand()%5;

        char *captFirstLetter = article[location];

        captFirstLetter[0] = captFirstLetter[0] - 32 ;

        sentence[0] = captFirstLetter;

        sentence[1] = noun[rand()%5];

        sentence[2] = verb[rand()%5];

        sentence[3] = preposition[rand()%5];

        sentence[4] = article[rand()%5];

        sentence[5] = noun[rand()%5];

        for(int i = 0; i < 7; i++){
            printf("%s%s%s", (i == 6) ? "" : sentence[i], (i > 4) ? "" : " ", (i == 5)? ".\n" : "" );
        }
        running ++;

        if(running == 21){
            running = 0;
        }
    }
}
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Mockith
  • 21
  • 4
  • https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-string-initialized-with-cha – Retired Ninja Mar 17 '19 at 00:23
  • Just an advice: don't subtract a magic 32 number, it would be clear if you wrote 'a' - 'A'. So, `captLetter=letter - 'a' + 'A'` – Igor Tulmentyev Mar 17 '19 at 00:47

1 Answers1

5

Oh, no no no - SegFault:

You create a pointer to a String Literal with:

    char *captFirstLetter = article[location];

You cannot modify the String Literals referenced by the pointers in article. Your attempt to modify them, e.g.

    captFirstLetter[0] = captFirstLetter[0] - 32 ;

Invokes Undefined Behavior and most probably an immediate SegFault. String literals are stored in read-only memory and cannot be changed (on all but the most ancient and obscure hardware)

To remedy the problem, make sure the strings pointed to by article are arrays and not string literals. For example, declare article as a 2D array of sufficient size:

    char article[][8] = {"the", "a", "one", "some", "any"};

Additionally, while you are correctly subtracting 32 to flip the 6th bit (the lower-case bit off), the standard library provides the macro toupper() in <ctype.h> to handle that case with the proper checks to ensure the case change is limited to lower-case characters. For example:

#include <ctype.h>
...
    captFirstLetter[0] = toupper(captFirstLetter[0]);

Finally, putting it together in a short example explaining the two issues above, you would have:

#include <stdio.h>
#include <ctype.h>

int main (void) {

    char article[][8] = {"the", "a", "one", "some", "any"};
    size_t n = sizeof article / sizeof *article;
    int location = 2;
    char *captFirstLetter = article[location];

    captFirstLetter[0] = toupper(captFirstLetter[0]);

    for (size_t i = 0; i < n; i++)
        puts (article[i]);
}

Example Use/Output

$ ./bin/cmplitp2a
the
a
One
some
any

Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85