1

I'm working on the hacker edition of pset2 and I'm running into a problem with initials.c

Here's the spec: Write, in a file called initials.c, a program that prompts a user for their name (using GetString to obtain their name as a string) and then outputs their initials in uppercase with no spaces or periods, followed by a newline (\n) and nothing more. You may assume that the user’s input will contain only letters (uppercase and/or lowercase) plus spaces. Folks like Joseph Gordon-Levitt, Conan O’Brien, and David J. Malan won’t be using your program. But the user’s input might be sloppy, in which case there might be one or more spaces at the start and/or end of the user’s input or even multiple spaces in a row.

So that we can automate some tests of your code, your program must behave per the examples below.

username:~/workspace/hacker2 $ ./initials
Zamyla Chan
ZC
username:~/workspace/hacker2 $ ./initials
robert thomas bowden
RTB

When I run ./initials in the terminal, everything runs correctly, but check50 displays an error:
:( outputs "MB" for " milo banana "
\ expected output, but not "MB\u0000\n"
:( outputs "MB" for " milo banana "
\ expected output, but not "MB\u0000\n"

Here's my original code:

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

int main(void)
{
    // Get name from user usng GetString
    // printf("Please enter your name: ");
    string name = GetString();

    // Check for NULL
    if (name!=NULL)
    {
        // Print first initial if it's not whitespace
        if (!isspace(name[0]))
        {
            printf("%c", toupper(name[0]));
        }

        /** 
         * Iterate over the length of the string 
         * Pass over spaces and print initials
         */
        for (int i=0, n=strlen(name); i<n; i++)
        {        
            if (isspace(name[i]) && !isspace(name[i+1]))
            {
                printf("%c", toupper(name[i+1]));
            }

        }
    } 

    printf("\n");
}

I know that the problem is here in my for loop:

if (isspace(name[i]) && !isspace(name[i+1]))
{
    printf("%c", toupper(name[i+1]));
}

When it gets to the end of string such as " milo banana " that ends in a space, check50 thinks it prints [n+1] which is the NULL terminating character \u0000. However it doesn't actually show up in the output, at least not in my terminal window.

I have attempted multiple fixes, but none of them work:
1. Adding:

if (isspace(name[i]) && (i+1)>n)
            {
                break;
            }

2. Adding an else if condition:

else if (isspace(name[i]) && name[i+1] == '\0')
            {
                // NOTHING
            }

Any thoughts?

2 Answers 2

1

Interesting. I ran your code and it passed check50. I was unable to duplicate the problem. However, I do see the issue.

You were on the right track, but your attempts to correct had errors. The problem is indeed in processing the end of the string. If the last character is a space, there is no next char to process. So, changing the for loop as follows will eliminate the problem.

    for (int i=0, n=strlen(name)-1; i<n; i++)

Here's where you went wrong on the corrections.

if (isspace(name[i]) && !isspace(name[i+1]))

If the last char is a space, then both conditions will evaluate to true. The first is true for obvious reasons. In the second condition, isspace() will return 0 for the end of string marker. 0 is evaluated as false, so !0 is true. A better test would be to see if name[i+1] == '\0'. But it appears you suspected something along these lines. AS for why it doesn't print in your terminal window, the end of string marker is a non-printable character, unless you actually print out the hex value itself, with appropriate formatting.

Next, you tried if (isspace(name[i]) && (i+1)>n) The problem here is that your second test is off target. Say that n = 5. There are 5 characters in the string and the array indices run from 0 to 4. So, if i=4, the test checks whether i+1, or 5, is > 5, which is false, even though you needed it to be true. The correct test would have been (i+1) >= n.

Your final test actually looks like it would have worked, had it contained a break instead of //nothing. I'm not sure about the else clause because I don't see it in it's full context. I think a simple if would have sufficed.

Most of these comments are in the context of the specific items discussed. Overall, fixing the for loop is probably the best solution.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

3
  • Thanks! You're right, simply fixing the for-loop is the simplest and easiest solution As per usual, I was trying to make thing more complicated than they need to be. In terms of replicating the problem, maybe you were using the regular check50: check50 2015.fall.pset2.initials initials.c and not the hacker check50: check50 2015.fall.hacker2.initials initials.c ?
    – Tomas Vrba
    Commented May 23, 2016 at 20:35
  • Yup, wrong check50. thanks.
    – Cliff B
    Commented May 23, 2016 at 20:38
  • Thanks for both of you, i was facing the same problem but my code was in different manner, but i knew where is the wrong in my code when i read the answer. Commented Mar 5, 2017 at 5:50
0

Didn't read the other answers, so this might be a repeat. And since it's part of course material, I don't want to give you the answer.

But for those having the same issue. Look at this:

    for (int i=0, n=strlen(name); i<n; i++) //n=strlen(name)?
    {        
        if (isspace(name[i]) && !isspace(name[i+1]))
        {
            printf("%c", toupper(name[i+1])); //i+1?
        }
    }

What happens when you go to the end of the loop?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .