0

I need to write program that get Input from user and in case i have quate (") i need to change all the chars inside the quotes to uppercase.

int main()
{
    int quoteflag = 0;
    int ch = 0;
    int i = 0;
    char str[127] = { '\0' };

    while ((ch = getchar()) != EOF && !isdigit(ch))
    {
        ++i;
        if (ch == '"')
            quoteflag = !quoteflag;

        if (quoteflag == 0)
            str[i] = tolower(ch);
        else
        {
            strncat(str, &ch, 1);
            while ((ch = getchar()) != '\"')
            {
                char c = toupper(ch);
                strncat(str, &c, 1);
            }

            strncat(str, &ch, 1);
            quoteflag = !quoteflag;
        }

        if (ch == '.')
        {
            strncat(str, &ch, 1);
            addnewline(str);
            addnewline(str);
        }
        else
        {
            if ((isupper(ch) && !quoteflag))
            {
                char c = tolower(ch);
                strncat(str, &c, 1);
            }
        }
    }

    printf("\n-----------------------------");
    printf("\nYour output:\n%s", str);
    getchar();

    return 1;
}

void addnewline(char *c)
{
    char tmp[1] = { '\n' };
    strncat(c, tmp, 1);
}

So my problem here is in case my input is "a" this print at the end "A instead of "A" and i dont know why

2 Answers 2

1

The problem is that you are using strncat in a weird way. First, strncat will always do nothing on big-endian systems. What strncat does is read the inputs ... as strings. So passing and int (four or eight bytes) into the function, it'll read the first byte. If the first byte is 0, then it'll believe it is the end of the string and will not add anything to str. On little endian systems, the first byte should be the char you want, but on big-endian systems it will be the upper byte (which for an int that holds a value less than 255, will always be zero). You can read more about endianness here.

I don't know why you're using strncat for appending a single character, though. You have the right idea with str[i] = tolower(ch). I changed int ch to char ch and then went through and replaced strncat(...) with str[i++] = ... in your code, and it compiled fine and returned the "A" output you wanted. The source code for that is below.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    int quoteflag = 0;
    char ch = 0;
    int i = 0;
    char str[127] = { '\0' };

    while ((ch = getchar()) != EOF && !isdigit(ch))
    {
        if (ch == '"')
            quoteflag = !quoteflag;

        if (quoteflag == 0)
            str[i++] = tolower(ch);
        else
        {
            str[i++] = ch;
            while ((ch = getchar()) != '\"')
            {
                char c = toupper(ch);
                str[i++] = c;
            }
            str[i++] = ch;
            quoteflag = !quoteflag;
        }

        if (ch == '.')
        {
             str[i++] = '.';
             str[i++] = '\n';
             str[i++] = '\n';
        }
        else
        {
            if ((isupper(ch) && !quoteflag))
            {
                char c = tolower(ch);
                str[i++] = c;
            }
        }
    }

    printf("\n-----------------------------");
    printf("\nYour output:\n%s", str);
    getchar();

    return 1;
}
Sign up to request clarification or add additional context in comments.

3 Comments

char ch = 0; --> int ch = 0; would be better for while ((ch = getchar()) != EOF && !isdigit(ch))
@chux true for getchar(), as comparing a char to the int to EOF can cause problems, but isdigit() shouldn't be an issue. Either way, there are more serious issues wiht this code (failing to check EOF on the inner while() loop, static initialization of str to 127 bytes with no input length checking, etc. These are serious buffer overflow issues. I get the sense OP is doing this as homework or tutorial, as s/he clearly isn't understanding some of these more important concepts. We were all there once, so helping OP to get the code running is the goal here.
In other words, I'd suggest OP start with input validation before worrying about edge-cases with getchar(), but yes, you are right that int is a better variable for getchar()
0

You should delete the ++i; line, then change:

str[i] = tolower(ch);

To:

str[i++] = tolower(ch);

Otherwise, since you pre-increment, if your first character is not a " but say a, your string will be \0a\0\0.... This leads us on to the next problem:

strncat(str, &ch, 1);

If the input is a", then strncat(str, &'"', 1); will give a result of \"\0\0... as strncat will see str as an empty string. Replace all occurrences with the above:

str[i++] = toupper(ch);

(The strncat() may also be technically undefined behaviour as you are passing in an malformed string, but that's one for the language lawyers)

This will keep track of the index, otherwise once out of the quote loop, your first str[i] = tolower(ch); will start overwriting everything in quotes.

3 Comments

Looks like you beat me to it by a few seconds! You're right about malformed strings, but look at my note on endianness - on big endian systems the first byte read by strncat will always be zero. To use strncat in this way is not safe.
Ah yes, I missed that it is int ch, so it's much worse than I thought!
@user979033 a string is just an array of characters. In c, a char is one byte, whereas an int is usually four bytes. If you try to process an int like a string, it'll be a four-byte string, not a one-byte char. As I mention in my answer, strncat only looks at the first byte of the int, not the whole value

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.