How to convert character

T

Tameem

hi my name is tameem. i am a new c programmer.
in a c program
i want to give input ""tameem""
and the output will be ""xdphhp""
in a short: the character ""a"" will be replaced by ""d""
i can convert only a character.so how can i convert a word or a
sentence
my character convert program is given below:

#include<stdio.h>
main()
{
char ch;
printf("Enter a Character=");
ch=getchar();
printf("%c",ch+3);
}

so please tell me how can i convert a whole sentence.
 
S

santosh

Tameem said:
hi my name is tameem. i am a new c programmer.
in a c program
i want to give input ""tameem""
and the output will be ""xdphhp""
in a short: the character ""a"" will be replaced by ""d""
i can convert only a character.so how can i convert a word or a
sentence
my character convert program is given below:

#include<stdio.h>
main()
{
char ch;
printf("Enter a Character=");
ch=getchar();
printf("%c",ch+3);

This won't necessarily do what you want since the codepoints for
alphabetic characters need not be in increasing order. This property is
only guaranteed for the decimal digit characters in C.
}

so please tell me how can i convert a whole sentence.

Loop through the string and convert each character till you
encounter '\0'.
 
S

santosh

Tameem said:
hi my name is tameem. i am a new c programmer.
in a c program
i want to give input ""tameem""
and the output will be ""xdphhp""
in a short: the character ""a"" will be replaced by ""d""
i can convert only a character.so how can i convert a word or a
sentence
my character convert program is given below:

#include<stdio.h>
main()
{
char ch;
printf("Enter a Character=");
ch=getchar();
printf("%c",ch+3);
}

so please tell me how can i convert a whole sentence.

Here is some code. It requires the numeric code of both upper and lower
case characters to be in ascending order. The ASCII character set
fullfills this condition, but the code will break on systems using
character sets like the EBCDIC.

#include <stdio.h>
#include <ctype.h>
#define OFFSET 3

int main(int argc, char **argv) {
char *alph = "abcdefghijklmnopqrstuvwxyz";

if (argc < 2) {
puts("Usage: program string");
}
else {
char *s;
for (s = argv[1]; *s; s++) {
if (islower(*s) && *s < 'x')
putchar(alph[(*s-'a')+OFFSET]);
else if (isupper(*s) && *s < 'X')
putchar(toupper(alph[(*s-'a')+OFFSET]));
else putchar(*s);
}
putchar('\n');
}
return 0;
}
 
N

Nick Keighley

hi my name is tameem. i am a new c programmer.
in a c program
i want to give input ""tameem""
and the output will be ""xdphhp""
in a short: the character ""a"" will be replaced by ""d""
i can convert only a character.so how can i convert a word or a
sentence
my character convert program is given below:

you seem to be afraid of whitespace. A few spaces in your code make
it easier to read. Correct indentation makes the logic clearer.

#include<stdio.h>
main()
{
char ch;
printf("Enter a Character=");
ch=getchar();
printf("%c",ch+3);

}

#include <stdio.h> /* the space in front of < makes it more readable
*/

int main (void)
{
char ch;

printf ("Enter a Character=");
fflush (stdout); /* ensure the output appears */
ch = getchar (); /* check for an error */
printf ("%c", ch + 3); /* need another fflush() */
}

this only reads and echoes a single character.
so please tell me how can i convert a whole sentence.

use a loop or fgets()

--
Nick Keighley

-- There are two rules for success in life:
-- Rule 1: Don't tell people everything you know.
--
 
R

rahul

hi my name is tameem. i am a new c programmer.
in a c program
i want to give input ""tameem""
and the output will be ""xdphhp""
in a short: the character ""a"" will be replaced by ""d""

'a' is replaced by 'x'. How come 't' is replaced by 'x'? Did you mean
'w'?
i can convert only a character.so how can i convert a word or a
sentence
my character convert program is given below:

#include<stdio.h>
main()
{
char ch;
printf("Enter a Character=");
ch=getchar();
printf("%c",ch+3);


As already pointed out, the code-points need not be consecutive (More
often than not, they are consecutive but it is not guaranteed). Even
if they are, your ch + 3 will fail for 'x', 'y', 'z'.

/* Begin rotate.c */
#include <stdio.h>
#include <stdlib.h>

#define ROTATE_SUCCESS 10
#define ROTATE_ERROR -10
#define INPUT_LEN 30

static int map['z' - 'a'];

void init(void) {
int count = 'a';
for (; count <= 'w'; count++) {
map[count] = count + 3;
}
map['x'] = 'a';
map['y'] = 'b';
map['z'] = 'c';
}

int rotate(char* input) {
int count = 0;

if (NULL == input) {
return ROTATE_ERROR;
}

while (input[count] != NULL) {
input[count] = map[input[count]];
count++;
}
return ROTATE_SUCCESS;
}

int
main(void) {
char input[INPUT_LEN];
fgets(input, sizeof input - 1, stdin);
rotate(input);
printf("%s", rotate);
return 0;
}


I haven't compiled this code but I think you get the idea how to do
it.

Of course, the code points may not be adjacent. In that case, either
you will have to declare a static mapping or convert each character
individually.
 
S

santosh

rahul said:
hi my name is tameem. i am a new c programmer.
in a c program
i want to give input ""tameem""
and the output will be ""xdphhp""
in a short: the character ""a"" will be replaced by ""d""

'a' is replaced by 'x'. How come 't' is replaced by 'x'? Did you mean
'w'?
i can convert only a character.so how can i convert a word or a
sentence
my character convert program is given below:

#include<stdio.h>
main()
{
char ch;
printf("Enter a Character=");
ch=getchar();
printf("%c",ch+3);


As already pointed out, the code-points need not be consecutive (More
often than not, they are consecutive but it is not guaranteed). Even
if they are, your ch + 3 will fail for 'x', 'y', 'z'.

/* Begin rotate.c */
#include <stdio.h>
#include <stdlib.h>
#define ROTATE_SUCCESS 10
#define ROTATE_ERROR -10
#define INPUT_LEN 30

static int map['z' - 'a'];

You need one more element in map.
void init(void) {
int count = 'a';
for (; count <= 'w'; count++) {
map[count] = count + 3;

You probably want:

map[count - 'a'] = count + 3;
}
map['x'] = 'a';
map['y'] = 'b';
map['z'] = 'c';
Ditto.

}

int rotate(char* input) {
int count = 0;

if (NULL == input) {
return ROTATE_ERROR;
}

while (input[count] != NULL) {

The comparison should be with '\0', though NULL will work.
input[count] = map[input[count]];
count++;
}
return ROTATE_SUCCESS;
}

int
main(void) {
char input[INPUT_LEN];
fgets(input, sizeof input - 1, stdin);

sizeof input will do since fgets will always store one character less
than the count passed to it.
rotate(input);
printf("%s", rotate);

You want to print input here.
 
S

santosh

Richard said:
santosh said:
sizeof input will do since fgets will always store one character less
than the count passed to it.

Your advice is correct - i.e. passing sizeof input is just fine - but
your explanation is not quite accurate as written.

Rather, fgets will never store more characters than the count passed
to it, and the last character it stores is always a null character,
not a character taken from the input stream.

Pictorially, if INPUT_LEN happened to be 16:

<----------------------------16 elements----------------------->
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| r | a | n | d | o | m | f | o | o | b | a | r | b | a | z | q |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
^
|
&input[0]

stdin: Now is the time for all good men to come to the party.\n

fgets(input, sizeof input, stdin) now does this:

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| n | o | w | | i | s | | t | h | e | | t | i | m | e |\0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
<----------------- 15 elements taken from stdin ----------> ^
|
|
The null terminator is not read from ------------------------+
the stream, but is stored by fgets in
the last position to which you grant
access.

<snip>

Thanks for the correction. I agree that my wording was very sloppy.
 
R

rahul

Thanks for the correction. I agree that my wording was very sloppy.

So is my whole code. Quoting from the manual:
FGETS(P)
FGETS(P)

NAME
fgets - get a string from a stream

SYNOPSIS
#include <stdio.h>

char *fgets(char *restrict s, int n, FILE *restrict stream);

DESCRIPTION
The fgets() function shall read bytes from stream into the
array pointed to by s, until n-1 bytes are read,
or a <newline> is read and transferred to s, or an end-of-file
condition is encountered. The string is then
terminated with a null byte.

It read n-1 bytes. So, no need for sizeof watever - 1.
You probably want:
> map[count - 'a'] = count + 3;
Yes, I do.
while (input[count] != NULL) {
The comparison should be with '\0', though NULL will work.
Not to start the purists debate, NULL works but to be precise, it
should be the '\0'. So, point taken.
 
S

santosh

rahul said:
Thanks for the correction. I agree that my wording was very sloppy.

So is my whole code. Quoting from the manual:
FGETS(P)
FGETS(P)

NAME
fgets - get a string from a stream

SYNOPSIS
#include <stdio.h>

char *fgets(char *restrict s, int n, FILE *restrict stream);

DESCRIPTION
The fgets() function shall read bytes from stream into the
array pointed to by s, until n-1 bytes are read,
or a <newline> is read and transferred to s, or an end-of-file
condition is encountered. The string is then
terminated with a null byte.

It read n-1 bytes. So, no need for sizeof watever - 1.
You probably want:
map[count - 'a'] = count + 3;
Yes, I do.
while (input[count] != NULL) {
The comparison should be with '\0', though NULL will work.
Not to start the purists debate, NULL works but to be precise, it
should be the '\0'. So, point taken.

But the code you posted is still not correct, even after all these
corrections. Here is a corrected version. Lines that I have corrected
or have added have a /* ++ */ comment on them.

/* Begin rotate.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> /* ++ */

#define ROTATE_SUCCESS 10
#define ROTATE_ERROR -10
#define INPUT_LEN 30

static int map[('z' - 'a')+1]; /* ++ */

void init(void) {
int count = 'a';
for (; count <= 'w'; count++) {
map[count - 'a'] = count + 3; /* ++ */
}
map['x' - 'a'] = 'a'; /* ++ */
map['y' - 'a'] = 'b'; /* ++ */
map['z' - 'a'] = 'c'; /* ++ */
}

int rotate(char* input) {
int count = 0;

if (NULL == input) {
return ROTATE_ERROR;
}

while (input[count] != '\0' && input[count] != '\n') { /* ++ */
if (isalpha(input[count])) { /* ++ */
input[count] = map[input[count]-'a']; /* ++ */
}
count++;
}
return ROTATE_SUCCESS;
}

int
main(void) {
char input[INPUT_LEN];
init(); /* ++ */
fgets(input, sizeof input, stdin); /* ++ */
rotate(input);
printf("%s\n", input); /* ++ */
return 0;
}
 
S

santosh

[ ... ]
But the code you posted is still not correct, even after all these
corrections. Here is a corrected version. Lines that I have corrected
or have added have a /* ++ */ comment on them.

<snip code>

And that code was still incorrect since it failed to deal properly with
uppercase input characters. Here is yet another corrected version:

/* Begin rotate.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> /* ++ */

#define ROTATE_SUCCESS 10
#define ROTATE_ERROR -10
#define INPUT_LEN 30

static int map[('z' - 'a')+1]; /* ++ */

void init(void) {
int count = 'a';
for (; count <= 'w'; count++) {
map[count - 'a'] = count + 3; /* ++ */
}
map['x' - 'a'] = 'a'; /* ++ */
map['y' - 'a'] = 'b'; /* ++ */
map['z' - 'a'] = 'c'; /* ++ */
}

int rotate(char* input) {
int count = 0;

if (NULL == input) {
return ROTATE_ERROR;
}

while (input[count] != '\0' && input[count] != '\n') { /* ++ */
if (isalpha(input[count])) { /* ++ */
if (isupper(input[count])) { /* ++ */
input[count] = toupper(map[tolower(input[count])-'a']); /* ++ */
}
else input[count] = map[input[count]-'a']; /* ++ */
}
count++;
}
return ROTATE_SUCCESS;
}

int
main(void) {
char input[INPUT_LEN];
init(); /* ++ */
fgets(input, sizeof input, stdin); /* ++ */
rotate(input);
printf("%s\n", input); /* ++ */
return 0;
}
 
S

santosh

pete said:
santosh said:
static int map[('z' - 'a')+1]; /* ++ */

('z' - 'a') could be almost any integer value.
('z' - 'a') equals 40 for ebdic.
('z' - 'a') is also allowed to be equal to 1,
or even negative,
if anyone would want to implement such a character set.

Yes. I flagged my solution as specific to character sets with the
desired property, and presumably, rahul did so as well. A fully
portable solution is an interesting exercise for the OP. It might fetch
him additional credits too.
 
K

Keith Thompson

rahul said:
while (input[count] != NULL) {
The comparison should be with '\0', though NULL will work.
Not to start the purists debate, NULL works but to be precise, it
should be the '\0'. So, point taken.

(input[count] is of type char, yes?)

I don't see how your statement differs from what santosh wrote.

NULL will work if the implementation happens to define it as 0.
It will *not* work if the implementation defines it as ((void*)0).
 
R

rahul

rahul said:
  while (input[count] != NULL) {
  The comparison should be with '\0', though NULL will work.
Not to start the purists debate, NULL works but to be precise, it
should be the '\0'. So, point taken.

(input[count] is of type char, yes?)

I don't see how your statement differs from what santosh wrote.
I said "point taken", meaning to say that I agree that I should have
made the comparison with '\0' :)
 
R

rahul

pete said:
santosh wrote:
static int map[('z' - 'a')+1];       /* ++ */
('z' - 'a') could be almost any integer value.
('z' - 'a') equals 40 for ebdic.
('z' - 'a') is also allowed to be equal to 1,
or even negative,
if anyone would want to implement such a character set.

Yes. I flagged my solution as specific to character sets with the
desired property, and presumably, rahul did so as well. A fully
portable solution is an interesting exercise for the OP. It might fetch
him additional credits too.
It may, but I don't see any algorithm which can do the rotation for an
arbitrary character set. For argument's sake, there may not be any
pattern at all. 'a' may be 90, 'b' 91, then c 190....and so on and on.
Is it really possible to do this without taking the particular char
set into account?
 
C

CBFalconer

rahul said:
santosh said:
pete said:
santosh wrote:

static int map[('z' - 'a')+1]; /* ++ */

('z' - 'a') could be almost any integer value.
('z' - 'a') equals 40 for ebdic.
('z' - 'a') is also allowed to be equal to 1,
or even negative,
if anyone would want to implement such a character set.

Yes. I flagged my solution as specific to character sets with
the desired property, and presumably, rahul did so as well. A
fully portable solution is an interesting exercise for the OP.
It might fetch him additional credits too.

It may, but I don't see any algorithm which can do the rotation
for an arbitrary character set. For argument's sake, there may
not be any pattern at all. 'a' may be 90, 'b' 91, then c 190....
and so on and on. Is it really possible to do this without
taking the particular char set into account?

Assuming the char set to be rotated and within is 'a ... z', then
you can do all sorts of things with:

char *theset = "abcdefghijklmnopqrstuvwxyz";
and use:
if (p = strchr(theset, ch)) /* ch is within the set */
ix = p - &theset;
ixnew = (ix + delta) % strlen(theset);
chnew = theset[ixnew];
}
else /* ignore the char */ ;

The sign of delta switches between encode and decode. There is no
portability problem, and the native char set can be anything you
want.
 
K

Keith Thompson

CBFalconer said:
rahul said:
santosh said:
pete wrote:
santosh wrote:

static int map[('z' - 'a')+1]; /* ++ */

('z' - 'a') could be almost any integer value.
('z' - 'a') equals 40 for ebdic.
('z' - 'a') is also allowed to be equal to 1,
or even negative,
if anyone would want to implement such a character set.

Yes. I flagged my solution as specific to character sets with
the desired property, and presumably, rahul did so as well. A
fully portable solution is an interesting exercise for the OP.
It might fetch him additional credits too.

It may, but I don't see any algorithm which can do the rotation
for an arbitrary character set. For argument's sake, there may
not be any pattern at all. 'a' may be 90, 'b' 91, then c 190....
and so on and on. Is it really possible to do this without
taking the particular char set into account?

Assuming the char set to be rotated and within is 'a ... z', then
you can do all sorts of things with:

char *theset = "abcdefghijklmnopqrstuvwxyz";
and use:
if (p = strchr(theset, ch)) /* ch is within the set */
ix = p - &theset;
ixnew = (ix + delta) % strlen(theset);
chnew = theset[ixnew];
}
else /* ignore the char */ ;

The sign of delta switches between encode and decode. There is no
portability problem, and the native char set can be anything you
want.

I see a possible performance problem here. For each letter, strchr()
scans, on average, half of the 26-character string (assuming a uniform
distribution). For each non-letter, it scans the entire string to
determine that it's not a letter. Something that should be O(N)
(where N is the number of characters being processed) becomes O(N*M),
where M is the number of letters in the alphabet.

Whether this is a significant issue depends on the nature of the
problem being solved and of the input data.

An alternative is to build a lookup table at run time, such that
table['a'] == 'd' and so forth (if delta==3). This can still be done
portably, without reference to the underlying character set (but
assuming that CHAR_BIT isn't so big that the table is too large).
There's a (possibly significant) one-time cost, but the result is a
single array lookup per input character. There's also some cost in
code size and complexity; the call to strchr(), though it's relatively
inefficient, is quite simple and almost elegant.
 
N

Nick Keighley

  while (input[count] != NULL) {
  The comparison should be with '\0', though NULL will work.

Not to start the purists debate, NULL works but to be precise, it
should be the '\0'. So, point taken.

I've just been fixing lots of code that did this and
generated lots of warnings when ported to a different
compiler. So I don't think it is a "purist debate".
NULL is a null pointer constant and MAY NOT be 0.
 
C

CBFalconer

Keith said:
CBFalconer said:
rahul wrote:
.... snip ...
It may, but I don't see any algorithm which can do the rotation
for an arbitrary character set. For argument's sake, there may
not be any pattern at all. 'a' may be 90, 'b' 91, then c 190....
and so on and on. Is it really possible to do this without
taking the particular char set into account?

Assuming the char set to be rotated and within is 'a ... z', then
you can do all sorts of things with:

char *theset = "abcdefghijklmnopqrstuvwxyz";
and use:
if (p = strchr(theset, ch)) /* ch is within the set */
ix = p - &theset;
ixnew = (ix + delta) % strlen(theset);
chnew = theset[ixnew];
}
else /* ignore the char */ ;

The sign of delta switches between encode and decode. There is no
portability problem, and the native char set can be anything you
want.

I see a possible performance problem here. For each letter, strchr()
scans, on average, half of the 26-character string (assuming a uniform
distribution). For each non-letter, it scans the entire string to
determine that it's not a letter. Something that should be O(N)
(where N is the number of characters being processed) becomes O(N*M),
where M is the number of letters in the alphabet.

I would worry more about the use of strlen(theset). That value
should be determined once and used.
 
B

Barry Schwarz

rahul wrote:
snip


Assuming the char set to be rotated and within is 'a ... z', then
you can do all sorts of things with:

char *theset = "abcdefghijklmnopqrstuvwxyz";
and use:
if (p = strchr(theset, ch)) /* ch is within the set */
ix = p - &theset;

Without the & of course.
ixnew = (ix + delta) % strlen(theset);
chnew = theset[ixnew];
}
else /* ignore the char */ ;

The sign of delta switches between encode and decode. There is no
portability problem, and the native char set can be anything you
want.


Remove del for email
 
S

santosh

pete said:
rahul said:
pete wrote:
santosh wrote:
static int map[('z' - 'a')+1]; /* ++ */
('z' - 'a') could be almost any integer value.
('z' - 'a') equals 40 for ebdic.
('z' - 'a') is also allowed to be equal to 1,
or even negative,
if anyone would want to implement such a character set.
Yes. I flagged my solution as specific to character sets with the
desired property, and presumably, rahul did so as well. A fully
portable solution is an interesting exercise for the OP. It might
fetch him additional credits too.
It may, but I don't see any algorithm which can do the rotation for
an arbitrary character set. For argument's sake, there may not be any
pattern at all. 'a' may be 90, 'b' 91, then c 190....and so on and
on. Is it really possible to do this without taking the particular
char set into account?

I started with Santosh's code and tried not to change too much.

<snip>

That was originally written by rahul, which I then modified in
subsequent posts.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top