replace char with string - c

I need to replace some chars with multiple chars (a string), but I got stuck. This code works for replacing one char with another, but if the replacement are multiple chars, the output messes up.
Here is the code I have so far:
char input[50];
char output[150];
int i;
printf("Enter your text: ");
fgets(input, 50 , stdin);
for (i = 0; input[i] != '\0'; i++){
switch (input[i]){
case 'a': output[i]= '4'; break;
case 'd': output[i]= '|)';break;
case 'e': output[i]= '3'; break;
case 'f': output[i]= '|='; break;
case 'u': output[i]= '|_|'; break;
case 'w': output[i]= '\|/'; break;
/* REST OF THE ALPHABET
INTENTIONALLY SUPPRESSED*/
}
}
printf("Your new text is: %s", output);
return 0;
As suggested by dasblinkenlight, I set another index for the output, That worked pretty fine, but I getting two additional chars at the end of the output text... where does those chars come from?
This is an example:
Enter your text: afedef
Your new text is: 4|=3|)3|=■(

1) You can't copy strings with = operator.
2) String literal in c is surrounded with double quotes
3) Special characters like backslash ('\') in string literals have a special meaning and should be escaped.
4) In order to do what you intend you will need:
a) Additional counter to track the position in the output string, where the next string will be written
b) use of strcpy/strncpy instead of assignment operator = , such that each line in the `switch statement will look similar to this:
case 'f': strcpy(&output[j], "|="); j+=2; break;
Here j is the second counter incremented by the number of characters written to output

Take a look at strcat (http://www.cplusplus.com/reference/cstring/strcat/):
char input[50];
char output[150];
int i;
printf("Enter your text: ");
fgets(input, 50 , stdin);
output[0] = 0; // null terminate before calling strcat.
for (i = 0; input[i] != '\0'; i++)
{
switch (input[i])
{
case 'a': strcat(output, "4"); break;
case 'd': strcat(output, "|)"); break;
//...
}
}
printf("Your new text is: %s", output);
Also, multiple characters in single quotes in C++ is implementation defined (C++ multicharacter literal), you'll probably want to avoid them. Also, be careful when using '\' in literals (as with your last case), it's probably not doing what you expect.

There are two problems in your code:
you are using i to iterate the output array. The size of the input array and output array are different. It may happen (e.g. in the case of f) that the index for the input array needs to be incremented by 1, whereas the index for the output array should be incremented by 2 or 3.
you can't assign multiple chars to a single char slot in an array. For instance, case 'f': output[i]= '|='; break; is incorrect.
To solve the problem you should use another variable and increment it with the number of characters added. For example:
int j = 0;
...
case 'e':
output[j++]= '3';
break;
case 'f':
output[j++]= '|';
output[j++]= '=';
break;

Try the following
#include <string.h>
//...
char *p = input, *q = output;
do
{
switch ( *p )
{
case '\0': *q = *p; break;
case 'a': *q++ = '4'; break;
case 'd': strcpy( q, "|)" ); q += 2; break;
case 'e': *q++ = '3'; break;
case 'f': strcpy( q, "|=" ); q += 2; break;
case 'u': strcpy( q, "|_|" ); q += 3; break;
case 'w': strcpy( q, "\|/" ); q += 3; break;
/* REST OF THE ALPHABET
INTENTIONALLY SUPPRESSED*/
}
} while ( *p++ );
Or instead of using strcpy you can assign each caharcter one after another as for example
case 'd': *q++ = '|'; *q++ = ')'; break;

Related

How to convert a character into a number

I have a homework problem. It requires me to convert a word into uppercase and several characters have to be converted to decimal for example :
"Hello my NamE is FeLix" --> "H3LL0 MY N4M3 15 F3L1X". So, these characters had to be converted :
I = 1
S = 5
E = 3
O = 0
A = 4
etc.
How to convert it? I already tried to convert it to capslock but i cannot convert it into decimal.
I already tried to convert the words into uppercase, but have no idea how to convert the character into numbers.
int main()
{
char sentence[200];
int sentencelength = strlen(sentence);
// Ambil data user
scanf("%s",&sentence); getchar();
// Cek satu persatu pake for
for (int i= 1; i <= sentencelength; i++) {
if(sentence[i] >= 'a' && sentence[i] <= 'z') {
char uppercase = sentence[i] + 'A' - 'a';
printf("%c",uppercase);
}
}
getchar();
return 0;
}
There is no error, but I just have no idea how to convert it.
You can use switch as below.
switch(uppercase ) {
case 'I':
uppercase = '1';
break;
case 'S':
uppercase = '5';
break;
case 'E':
uppercase = '3';
break;
…
}
C arrays start at index 0, not 1, so change the for loop bounds to:
for (int i = 0; i < sentencelength; i++) {
You can use toupper (declared by #include <ctype.h>) to convert a character from lowercase to uppercase, leaving non-alphabetic characters alone. It is only defined for values representable by an unsigned char or for the value EOF.
char l33t = sentence[i];
if (l33t == (unsigned char)l33t)
l33t = toupper(l33t);
You can use a switch statement to replace certain uppercase letters with digits:
switch (l33t) {
case 'I':
l33t = '1';
break;
case 'S':
l33t = '5';
break;
case 'E':
l33t = '3';
break;
case 'O':
l33t = '0';
break;
case 'A':
l33t = '4';
break;
}
Rather than using scanf to read a whole word of input into a buffer, an alternative is to read the input a character at a time. Here is an example program that behaves as a filter:
#include <stdio.h>
#include <ctype.h>
static int convert(int ch)
{
if (ch == (unsigned char)ch)
ch = toupper(ch);
switch (ch) {
case 'I': ch = '1'; break;
case 'S': ch = '5'; break;
case 'E': ch = '3'; break;
case 'O': ch = '0'; break;
case 'A': ch = '4'; break;
}
return ch;
}
int main(void)
{
int ch;
while ((ch = getchar()) != EOF) {
ch = convert(ch);
putchar(ch);
}
return 0;
}
The above will convert the whole input until it sees end-of-file. To terminate after a single line, just add a check for a newline character to break out of the while loop.
create an array of characters: [4BCD3F....Z]
and an array of sources: [abcd...z]
run on your string, replace each character found in index I with the same character in the first array, if it's not found return the character as is.
crude, simple, works
Also, if someone complain on the calculation complexity, since you have fixed number of letters in the arrays A to Z , the complexity is O(N*M) when M is const, hence O(N) anyway

Assigning a string in a char * array to another char * array

I am trying to convert the hex values in array a to binary values and assign converted values to array b then print the array b. But all values in array b are same. The output is:
111100001011000100010111101010001101
111100001011000100010111101010001101
111100001011000100010111101010001101
If I use b[i] = strdup(hexToBin(a[i])); instead of b[i] = hexToBin(a[i]); the output will be:
111100001011
111100001011000100010111
111100001011000100010111101010001101
Is this something about pointers? Char * is a pointer which points first character of the string and are all characters after the pointer printed? What is right way of doing this?
#include <stdio.h>
#include <string.h>
char bin[100] = "";
char * hexToBin(char hex[50]);
int main(void) {
char * a[] = {
"f0b",
"117",
"a8d",
};
char * b[3];
for(int i = 0; i < 3; i++) {
b[i] = hexToBin(a[i]);
}
for(int i = 0; i < 3; i++) {
printf("%s\n", b[i]);
}
}
char * hexToBin(char hex[50]) {
for(int i=0; hex[i]!='\0'; i++)
{
switch(hex[i])
{
case '0':
strcat(bin, "0000");
break;
case '1':
strcat(bin, "0001");
break;
case '2':
strcat(bin, "0010");
break;
case '3':
strcat(bin, "0011");
break;
case '4':
strcat(bin, "0100");
break;
case '5':
strcat(bin, "0101");
break;
case '6':
strcat(bin, "0110");
break;
case '7':
strcat(bin, "0111");
break;
case '8':
strcat(bin, "1000");
break;
case '9':
strcat(bin, "1001");
break;
case 'a':
case 'A':
strcat(bin, "1010");
break;
case 'b':
case 'B':
strcat(bin, "1011");
break;
case 'c':
case 'C':
strcat(bin, "1100");
break;
case 'd':
case 'D':
strcat(bin, "1101");
break;
case 'e':
case 'E':
strcat(bin, "1110");
break;
case 'f':
case 'F':
strcat(bin, "1111");
break;
default:
printf("Invalid hexadecimal input.");
}
}
return bin;
}
The hexToBin function returns a pointer to the first element of the global bin array. Everytime!.
That means all pointers in b will be the very same pointer to the very same first element of the bin array.
If you know the maximum length of the strings, I recommend that you make b an array of arrays of char. For example
char b[3][500]; // 3 arrays of 499-character strings (+1 for the null-terminator)
Then instead of hexToBin returning a pointer to a single global array, pass a pointer to the string to be filled as argument to hexToBin:
void hexToBin(char *hex, char *bin);
and call it as
hexToBin(a[i], b[i]);
You only have one bin. What your hexToBin does is appending to that one bin and then returning that bin. In other words, when you call it multiple times, the result is always the same pointer, because you always return bin;.
So if you do this:
b[i] = hexToBin(a[i]);
Then in the end, all elements of b are pointing to bin, that's why you get the same output when you print them. If you do this instead:
b[i] = strdup(hexToBin(a[i]));
Then the result is not the same, because they all don't get bin assigned, but a copy of what bin has been at that time. That's why the results are different. So b[0] points to one copy, then bin is appended to again, but that doesn't change the b[0] copy.
If you use strdup, don't forget to free the memory it allocated:
for(int i = 0; i < 3; i++) {
free(b[i]);
}
[My answer is mistaken. I leave it posted here for reference but the other answers are preferable.]
Your code looks pretty good for beginner's code and I like your style. I especially like this line:
char * b[3];
Unfortunately, for this particular application, you must replace this with a less elegant line like
char b[3][5];
The former line reserves no storage for your output. The latter line reserves five bytes per hex digit. You need storage, somehow.

Convert phone number from alphabetic to numeric form

I'm doing an exercise from KNKings book "C Programming: A modern approach" which involves converting a phone number in alphabetic form, entered by the user, into numeric form. When the program encounters non-alphabetic characters (digits or punctuations, for example), it should leave them unchanged. I may assume that the user only enters upper-case letters.
However, my program seems to produce garbage, to say the least.
#include <stdio.h>
#define MAX_SIZE 50
int main(void)
{
char alphabetic[MAX_SIZE], ch;
int num_elements = 0;
printf("Enter phone number: ");
int i;
for (i = 0; i < MAX_SIZE && ((ch = getchar()) != '\n'); i++){
alphabetic[i] = ch;
num_elements++;
}
for (i = 0; i <= num_elements; i++){
switch (alphabetic[i]){
case 'A': case 'B': case 'C': alphabetic[i] = '2'; break;
case 'D': case 'E': case 'F': alphabetic[i] = '3'; break;
case 'G': case 'H': case 'I': alphabetic[i] = '4'; break;
case 'J': case 'K': case 'L': alphabetic[i] = '5'; break;
case 'M': case 'N': case 'O': alphabetic[i] = '6'; break;
case 'P': case 'R': case 'S': alphabetic[i] = '7'; break;
case 'T': case 'U': case 'V': alphabetic[i] = '8'; break;
case 'W': case 'X': case 'Y': alphabetic[i] = '9'; break;
default: break;
}
}
printf("%s\n", alphabetic);
return 0;
}
In particular, I enter: COLLECT-800.
It outputs something like this: u░#■   ║k ╩
What did I do wrong?
You have the right idea, but there are two things missing in your program:
Most importantly, the null terminator at the end of the string. After your for loop in which you read the number, add the line:
alphabetic[i] = '\0';
If the user enters lowercase letters, they are ignored in the switch statement. To get around this, include <ctype.h> and change the switch quantity from alphabetic[i] to toupper(alphabetic[i]). Calling toupper on an already upper case letter is benign.
You're not putting a null-terminator anywhere so it's undefined behavior when you read the string regardless of whether you modified it afterwards. Put this line:
alphabetic[num_elements] = 0;
After your for (i = 0; i < MAX_SIZE &&... loop.
Personally, I wouldn't do the getchar loop and instead read in the string like this:
scanf("%49s", alphabetic); // reads in a string up to 50 characters
for (i = 0; alphabetic[i]; i++) { ...

Switch Statement with Array condition

I am having an impossible time trying to make this work. It is just a sample run of the code without the full options.
What is needed from the program is for the user to enter there choice, 1-3 or a-c. I am using a string in case the user enters more than just a single character. The switch case then should compare just the first char in the array to the cases. And the do while loop is to make sure it keeps going until they enter the right characters.
#include <stdio.h>
#define SIZE 81
void main(){
char thing[SIZE] = {3};
int rvalue;
do
{
scanf_s("%s", thing);
switch (thing[0])
{
case 'a':
case 1:
printf("first\n");
rvalue = 1;
break;
case 'b':
case 2:
printf("second\n");
rvalue = 2;
break;
case 'c':
case 3:
printf("third\n");
rvalue = 3;
break;
default:
printf("Wrong\n");
rvalue = 4;
break;
}
} while (rvalue == 4);
}
Change
scanf_s("%s", thing);
To
scanf_s("%s", thing,(unsigned int)sizeof(thing)); //Read the comments to know why the cast is required
This done because scanf and scanf_s are different function. scanf_s has an additional argument present to prevent buffer overflows.
Also change these
case 1:
case 2:
case 3:
To
case '1':
case '2':
case '3':
Because the character 1('1') and the rest of them are different from the integer 1. The characters(those enclosed in single quotes) have their values represented in the ASCII table.
As far as it seems, you want to print first when the first character in the thing string is a or 1, and so on.
The problem is that case 1: is not same as case '1':. 1 is an int, '1' is a char, and as you are comparing the first character of the string, you need to change your casestatements a bit.
Code:
#include <stdio.h>
#define SIZE 81
void main(){
char thing[SIZE] = {3};
int rvalue;
do
{
scanf_s("%s", thing,SIZE);
switch (thing[0])
{
case 'a':
case '1':
printf("first\n");
rvalue = 1;
break;
case 'b':
case '2':
printf("second\n");
rvalue = 2;
break;
case 'c':
case '3':
printf("third\n");
rvalue = 3;
break;
default:
printf("Wrong\n");
rvalue = 4;
break;
}
} while (rvalue == 4);
}

Why does the string return "#" or mess up my "Z"?

char convertalphas(char s) {
switch (s){
case 'A':
return '0';
break;
case 'B':
return '1';
break;
case 'C':
return '2';
break;
case 'D':
return '3';
break;
case 'E':
return '4';
break;
case 'F':
return '5';
break;
case 'G':
return '6';
break;
case 'H':
return '7';
break;
case 'I':
return '8';
break;
case 'J':
return '9';
break;
case 'K':
return '10';
break;
case 'L':
return '11';
break;
case 'M':
return '12';
break;
case 'N':
return '13';
break;
case 'O':
return '14';
break;
case 'P':
return '15';
break;
case 'Q':
return '16';
break;
case 'R':
return '17';
break;
case 'S':
return '18';
break;
case 'T':
return '19';
break;
case 'U':
return '20';
break;
case 'V':
return '21';
break;
case 'W':
return '22';
break;
case 'X':
return '23';
break;
case 'Y':
return '24';
break;
case 'Z':
return '25';
break;
}
}
int main()
{
char astring[10];
int i = 0;
int flag = 0;
int startedalpha = 0;
//check if there is a digit input or not
int nodigit = 0;
char cell[10];
int col;
scanf( "%s", &astring );
for ( i = 0; i < 10; ++i )
{
if(astring[i] != '\0') {
//check whether letter is capital or small
if (astring[i] >= 65 && astring[i] <= 90)
{
startedalpha = 1;
//printf( "%c\n", astring[i] );
cell[i] = convertalphas(astring[i]);
printf("cell is %s\n", cell);
}
What im trying to do is to concatenate all of my conversions for a later use. when I put "AB" it returns "01#" and when I put "Z" it returns something else than "25". I don't know what is wrong but it is driving me crazy! I want to be able to input "ABZ" and it saves all of my values into the variable cell. For example, "ABZ" "0125"
Thanks!
I'm confused with this forum. Obviously, I posted the question because there is something I don't know and I'm not a guru as many of you! So, why would I get -2? I already posted what I tried. I thought it is about helping not being condescending!
Thanks for those who replied anyway!
Edit --
I converted my switch statement to int but now how can I concatenate the integers in variable cell?
One of things I noticed is that you have a char returning function, and is returning something else than a char, like '10'. It will return an unexpected value. You can, for example, set the return of this function to integer.
So it will look like this:
int convertalphas(char s) {
switch (s){
case 'A':
return 0;
case 'B':
return 1;
case 'C':
return 2;
case 'D':
return 3;
case 'E':
return 4;
return -1;
}
And then, change inside the loop in main function:
sprintf(auxvar, "%d", convertalphas(astring[i]);
for( jj = 0; jj < strlen(auxvar); jj++)
cell[i++] = auxvar[jj];
I hope it can help you somehow!
Good Luck.
According to the C Standard (6.4.4.4 Character constants)
...The value of an integer character constant containing more than one
character (e.g., 'ab'), or containing a character or escape sequence
that does not map to a single-byte execution character, is
implementation-defined.All
All return values of the function starting from '10' to '25' inclusively are imolementation defined and you can get the result that you did not expect to get.
You need to write a function that would be declared like
char * convertalphas( const char *s );
Or
char * convertalphas( char *dest, const char *source );
By the way it will be difficult to make the reverse conversion. For example what does "25" mean? Whether it is "CF" or "Z"?:)
Apart from the values returned by chars 'K' thru 'Z' (as mentioned by others) there are some other errors with the use of cell
Each character returned from your function is written into cell[] and then you print cell as a string. But there is no string terminator. You either need to fill cell[] with zeros first, or write a 0 into the next character
cell[i] = convertalphas(astring[i]);
cell[i+1] = 0;
But the problem with this is that cell[i] is skipped when the char is not a capital letter. You need to maintain a separate index into cell[]
cell[j++] = convertalphas(astring[i]);
cell[j] = 0;
One more problem is cell[] is not long enough for the final string terminator. You need to declare it as
char cell[11];
To summarize, your problem is:
A char function cannot return anything other than a single character. If you try to return something like '12', it just simply doesn't work. You need to rethink your algorithm. Implementing this using ints should be very straightforward.
Is this a homework assignment requiring the use of the switch statement? If not, and if you follow the advice to return int instead of char, a simple s-65 would do the trick, you don't need a 78-line switch.
Since cell is a char array, each element of cell can also only store a single character.
It is not very clear what you are trying to achieve, so I will try to comprehend it in two ways:
3.1. You want to store each character's value separately in cell.
Example: for input "ABZ", you want cell to be {0, 1, 25}.
This is easy. Change cell to an int array, and output them using %d format specifier in your printf.
3.2 You treat cell as a string rather than an array of characters, and you concatenate the string for every character's value.
Example: for input "ABZ", you want cell to be "0125", or in other words, {'0', '1', '2', '5'}. This means that you won't be able to differentiate between "ABZ" and, say, "AMF", as others have pointed out.
If this is what you want to achieve, firstly 10 elements is not enough for cell - each character must be stored separately, and you cannot store "25" as two characters in a single element of cell.
You can assign it with, say, 21 elements (2 max for each alphabet, one extra for the terminating '\0' byte). After each alphabet is converted to its value in int, implement a counter and some conditionals to fill cell one character at a time. Example, if an alphabet's value is stored in val:
char cell[21];
int i=0;
if(val < 10) {
cell[i] = val + '0';
i++;
} else {
cell[i] = val / 10 + '0';
i++;
cell[i] = val % 10 + '0';
i++;
}
I'll leave the implementation of this into a loop as an exercise for you...

Resources