1

I have this problem to solve, I basically need to allow the user to input a text up to 80 characters in length. Once the string has been input, the program will have to go through each character and printing them one at the time but changing the vowel with different characters ( $,#,@,* and = ). I think I have been able to write a code that sort of work but if the user input a text with a space in it, the program will print just the text before the space, everything after the space won't be printed.

example:

     input: someTEXT!eg45a6I7uX
     output:s*m#T#XT!#g45$6@7=X

But:

     input: Hello Students
     output: H#ll*
{
    char text[80];
    scanf("%s", text);
    
    int current =0;
    printf(">\n");
    
    while(text[current] != '\0')
    {
        switch(text[current])
        {
            case 'a':
            printf("$");
            break;
            
            case 'A':
            printf("$");
            break;
            
            case  'e':
            printf("#");
            break;
            
             case  'E':
            printf("#");
            break;
            
            case 'i':
            printf("@");
            break;
            
             case 'I':
            printf("@");
            break;
            
            case 'o':
            printf("*");
            break;
            
             case 'O':
            printf("*");
            break;
            
            case 'u':
            printf("=");
            break;
            
            case 'U':
            printf("=");
            break;
            
            default:
            
            printf("%c", text[current]);
        
        }
       ++current;
    }
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
mattia
  • 11
  • 5

4 Answers4

4

Use the following format string in the call of scanf

char text[80]; 
scanf(" %79[^\n]", text);

Pay attention to the leading space in the format string. It allows to skip white space characters as for example the new line character '\n' that corresponds to the pressed key Enter that will be leaved in the input buffer after preceding call of scanf.

As for the format string in your call of scanf

scanf("%s", text);

then it reads a sequence of characters until a white space character is encountered in the input buffer. And moreover it is unsafe because can write beyond the character array due to absence of the length modifier.

An alternative approach is to use fgets like for example

fgets( text, sizeof( text ), stdin );

But there is one problem. The function fgets can append to the entered string the new line character '\n' that you need either to remove like

#include <string.h>

//...

text[ strcspn( text, "\n" ) ] = '\0';

or to change the condition in the while loop like

while(text[current] != '\0' && text[current] != '\n' )

Also you can reduce the code in the switch statement writing for example

    case 'a': case 'A':
        putchar( '$' );
        break;

or

    case 'a': 
    case 'A':
        putchar( '$' );
        break;
    

instead of

    case 'a':
    printf("$");
    break;
    
    case 'A':
    printf("$");
    break;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

As the other answers point out, scanf("%s", text) stops when it encounters a space. I would suggest to use fgets() instead of scanf(). It is safer (don't worry about buffer overflow), and easier for reading whole lines.

An also, check the return value of functions that can fail, when you need to handle this cases.

Up to 80 characters, probably means up to inclusive 80 characters, but a string has a additional '\0' at the end, meaning you need at least 81 bytes. I would even add yet another byte for a potiential '\n'-byte.

Character constants in C are of type int and have a positive value (there may be some exception where sizeof(int)==sizeof(char), but let us ignore such strange systems for this). If you use ASCII, then all character will still be positive after converting them to char, but that can change with single byte non-ASCII characters. Therefore, use unsigned char for the buffer.

You can improve the beginning this way:

    #define TEXT_SIZE (80+1+1)  //+1 for '\n', +1 for '\0'
    unsigned char text[TEXT_SIZE];
    if( !fgets(text,TEXT_SIZE,stdin) ) //Check for errors
      { perror("cant read from stdin"); exit(1) }

    size_t current =0; //size_t is the "correct" type for array indexing
    puts(">");
    .... 
  • Aside, "Character literals in C are of type int" better as "Character constants in C are of type `int`". C has 2 literals: _string_ and _compound_ and does not define a _character literal_. – chux - Reinstate Monica May 02 '23 at 14:31
1

The problem is in the call to scanf().

scanf("%s", text);

scanf() ignores everything to the right of a whitespace. Consider using fgets() instead:

fgets (text, sizeof text, stdin);

And check its return value, it returns NULL to indicate failure.

Note that fgets() retains the \n if there was space enough space, you could remove it like so:

text[strcspn (text, "\n")] = `\0`;

Alternatively, you could do

scanf(" %79[^\n]", text);

as suggested in another answer, but I wouldn't recommend this.

Harith
  • 4,663
  • 1
  • 5
  • 20
1

The problem is that scanf is really only suitable for very, very, very simple input, done by programs you write very, very, very early in your programming career.

And one of the ways in which scanf is simple is that the easy way it has for reading strings, namely %s, reads only strings not containing spaces. The first space it sees terminates the input — the space and anything following it are not read into your string variable (in this case text) at all.

So at this point you have three options:

  1. Live with it. Do you really need to, today, read and encrypt strings that do contain spaces? Maybe, instead, you can debug all the other aspects of your program, make it work totally awesomely for simpler strings, and worry about the problem of reading strings containing spaces another day.
  2. Instead of %s, use the cryptic and somewhat confusing format specifier %[^\n]. But I don't recommend this. scanf's only real virtue is that it's a nice, simple way to do nice, simple input in nice, simple programs. But %[^\n] is not "nice and simple".
  3. Don't use scanf at all. Now that you are trying to do something that is, by definition, beyond scanf's nice and simple capabilities, it's time to graduate beyond scanf, to leave it behind (like training wheels on a kid's bicycle) and learn to use something better. That will involve learning about: fgets.

See also What can I use for input conversion instead of scanf?

Steve Summit
  • 45,437
  • 7
  • 70
  • 103