change output from character array - c

Once again i find myself relatively lost and seeking knowledge from my peers.
What I am needing to do is to write a program that takes in an encoded language that adds the leters 'u' 't' after ever consonant and output into english. So the input Hutelutluto would be outputted as hello. At first I thought i had it figured out, but then my professor said i had to store the initial input in a character array and display it. Then use that character array to output the modified translation.
I have tried several different angles, one trying to modify my readstring function to fit my modification parameters. It always ends up becoming a mess and giving me unexpected outputs.
Essentially I believe that I need help feeding the character array into the while loop, but when I try I get an error stating that i have a pointer comparison to integer error.
Here is my edition of my code where i believe I was the closest to solving the problem. At the moment the while works independently from the readstring function. I am sure I am overthinking the problem, but i just not sure how to work out the kinks.
:
/*
Tut language
By: Steven
*/
# include <stdio.h>
void readstring(char *, int);
int main (void){
char input [50];
char output;
char trash;
//initiation
printf("\n\t*Hi! Welcome to the assemble of Tut*\n");
printf("I can help you decode/encode a message to and from the code called Tut!\n");
printf("Enter a sentence to be translated frome Tut - English: ");
readstring(input, 50);
printf("Your Tut sencence is: %s \n",input);
while (output != '\n') {
output = getchar();
if(output == '\n'){//escape sequence
break;
}
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
putchar(output);
trash = getchar();
trash = getchar();
}else{
putchar(output);
}
}
return 0;
}// end main
//function lists start
void readstring(char * buffer, int size) {
int x;
char c = getchar( );
if( c == '\n' ) {
c = getchar( );
}
for(x = 0 ; (x < (size-1)) && c != '\n' ; x++) {
buffer[x] = c;
c = getchar( );
}
buffer[x] = '\0';
}
Any help or feedback will be greatly appreciated!
Thank your for your time!
p.s.
After taking your advice into consideration i edited my code, but it seems as if it is ignoring all input after the first. I even tried changing the !='\n' condition to just i < 50, but i got the same results.
Line of code after taking Tim's advice:
for (i = 0; input [i] != '\n'; ++i){
output = input[i];
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
putchar(output);
trash = getchar();
trash = getchar();
}else{
putchar(output);
}
}

The main problem is in your while loop. In this loop, you are using getchar, which tries to read from stdin. However, you have already read your input, and it is stored in buffer.
So, you should get your characters from buffer instead of reading them again.

Your readstring function already calls getchar to read characters from the user's terminal, so you should not need to call it again after readstring is done. Instead, use a for loop to set output to each character of the input string in turn:
int i;
for i = 0; input[i] != '\n'; ++i {
output = input[i]
if((output != 'a') && (output != 'e') && (output != 'i') && (output != 'o') && (output != 'u') && (output != 'y') && (output != ' ')){
...

… in a character array, i have no idea how I am going to skip
those next two character?
You skip characters by incrementing the array index. Change
trash = getchar();
trash = getchar();
to
input[++i] && input[++i] || --i; // step back if at end of string
Also, since the input string is terminated by \0 rather than \n, change
for (i = 0; input [i] != '\n'; ++i){
to
for (i = 0; input[i]; ++i)
{

Related

How to count vowels, consonants, digits in a txt file using redirection in C

Brand new C coder here. In my first C course in school. I have experience in java but this course is all in C. I have homework to create a program that reads the contents of a file and counts the number of upper and lower case letters, vowels, consonants and digits. The program is not supposed to have any arguments, but will take a .txt file from the command line via redirection. My question is, how do I correct my current code to read from stdin each character of the file, whether it be a letter or a number? I'm really struggling with how read the contents of the file from stdin, read each character and then decide which category it belongs in. Any help would be appreciated. Thanks.
I'll be running the program like this...
$ program < testFile.txt
Where testFile.txt will contain the following text:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
int upper = 0; // Number of upper case letters
int lower = 0; // Number of lower case letters
int vowel = 0; // Number of vowels
int consonant = 0; // Number of constants
int digits = 0; // Number of digits
int total = 0; // Total number of characters in file
int i =0;
char value[100];
fgets(value, 100, stdin);
while(value[i] != '\0');
{
if (value[i] >= 'A' && value[i] <= 'Z')
{
upper++;
if (value[i] == 'A' || value[i] == 'E' || value[i] == 'I' || value[i] == 'O' || value[i] == 'U' || value[i] == 'Y')
{
vowel++;
}
else {
consonant++;
}
}
else if (value[i] >= 'a' && value[i] <= 'z')
{
lower++;
if (value[i] == 'a' || value[i] == 'e' || value[i] == 'i' || value[i] == 'o' || value[i] == 'u' || value[i] == 'y')
{
vowel++;
}
else {
consonant++;
}
}
else if (value[i] >= '0' && value[i] <= '9')
{
digits++;
}
total++;
i++;
}
printf("upper-case: %d", upper);
printf("\nlower-case: %d", lower);
printf("\nvowels: %d", vowel);
printf("\nconsonants: %d", consonant);
printf("\ndigits: %d", digits);
printf("\ntotal: %d", total);
printf("\n");
return 0;
I expect output to show how many upper case letters, lower case letters etc.
But once I run $ program < testFile.txt, it just sits there, no output to command line or anything.
Remove the semicolon after the while statement. :-)
while(value[i] != '\0');
This is your most obvious problem, it basically means:
while value[i] != '\0':
do nothing
end while
In other words, if it enters the loop, it will never exit it, because nothing changes that would affect the condition under which the loop continues.
There are other problems as well such as the fact that you will only process the first line rather than the whole file. The whole idea of using fgets and processing a line is unnecessary when you can just start with the following filter skeleton:
int ch;
while ((ch = getchar()) != EOF) {
/* process ch */
}
This will process an entire file character by character until all characters are done (or until an error occurs) so you can just tailor the body loop to do what you need - you've basically done that bit in your code with the loop over the line characters.
I would suggest not using the following code (since this is classwork) but you can also make better use of flow control constructs and library functions (from ctype.h and string.h), something like:
while ((ch = getchar()) != EOF) {
// Lib functions to detect upper/lower-case letters.
if (isupper(ch)) {
++upper;
} else if (islower(ch))
++lower;
}
// And to detect letter/digit type.
if (strchr("aeiouAEIOU", ch) != NULL) {
++vowel;
} else if (isalpha(ch)) {
++consonant;
} else if (isdigit(ch)) {
++digits;
}
++total;
}
This is particularly important since there's no actual guarantee that non-digit characters will be consecutive.

Encryption with swapping letters in C

I need to write a program that reads from the input a sentence terminated by a new line. The program should write an encryption of the sentence in a way that the letter 'a' is swapped with 'z', 'b' with 'y' and so on. I am not supposed to use arrays, that is why I can't find a solution for this problem.
This is my code:
#include<stdio.h>
int main() {
char alphabet, temp;
while( scanf("%c", &alphabet) != '\n') {
for(char i ='a', j='z'; i <= 'z', j>='a'; i++, j--) {
if(alphabet == i) {
temp = j;
}
}
printf("%c", temp);
}
return 0;
}
When I input: abc as an output I get zyxxxxxxxxxxxxxxxxxxxxxxxxx(an infinite number of x).
So to sum up:
Input:abc. Output: zyxxxxx(infinite number of x).
You messed up the return value of scanf:
while( scanf("%c", &alphabet) != '\n'){
You want to stop the loop when the entered character (in alphabet) is a line break.
But you test the return value of scanf which will never be '\n' as it returns the number of converted fields.
You could try like this:
while( scanf("%c", &alphabet) == 1 && alphabet != '\n'){
Compile your code with warnings enabled (e.g. Wall flag)! This:
for(char i ='a', j='z'; i <= 'z', j>='a'; i++, j--)
should give:
warning: left-hand operand of comma expression has no effect [-Wunused-value]
You need to use the logical AND operator && and not a comma between the two comparissons.
Moreover, use getchar() instead, like this:
#include<stdio.h>
int main() {
char temp;
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
for(char i ='a', j='z'; i <= 'z'&& j>='a'; i++, j--){
if(ch == i){
temp = j;
}
}
if(ch <= 'z'&& ch >= 'a') // do not print if 'ch' is a digit for example
printf("%c", temp);
}
return 0;
}
Output:
zyx
If you have to use scanf(), then try reading into alphabet, check the return value of scanf, and compare to newline, like this:
while(scanf("%c", &alphabet) != 0 && alphabet != '\n')

Counting lines, words, and characters

I am a new to programming. I am trying to write a program that reads lines, words and characters from a text file. Here is the code below.
#include "stdio.h"
#include "stdlib.h"
#define IN 1
#define OUT 0
int main (int argc, char *argv[]) {
FILE *input;
int character, newword, newline, state;
char c;
state = OUT;
character = newline = newword =0;
input = fopen(argv[1], "r");
if ( input == NULL){
printf("Error! Can not read the input\n");
exit(-1);
}
while ((c = fgetc(input)) != EOF){
character++;
if (c <'a' && c >'z'){;}
if ( c <'A' && c >'Z'){;}
if (c == '\n'){
newline++;
}
if (c == ' ' || c == '\n' || c == '\t'){
state = OUT;
}
else if (state == OUT){
state = IN;
newword++;
}
}
printf("The number of lines: %d\n", newline);
printf("The number of words: %d\n", newword);
printf("The number of characters: %d\n", character);
fclose(input);
}
I have been trying to figure how not to read special characters such as !, #, #, $, %, ^, &, *, (, ), _, +.
I tried using if statements so it won't read the special characters but it reads it. I think one the if statement for the capital letters is wrong because it probably will not read lower case letters.
In the file the following text is in it,
!!.
and it outputs in terminal:
The number of lines: 2
The number of words: 5
The number of characters: 7
However, if I take out the two for loops (c < 'A' && c > 'Z') and (c < 'a' && c > 'z'), then the output becomes
The number of lines: 2
The number of words: 1
The number of characters: 7
Any hints to fix this problem (I do not want the Answer!)?
Your if must be something like:
if ('a' <= c && c <='z'){character++;}
else if ( 'A' <= c && c <='Z'){character++;}
The easiest way to solve your problem is to increase your character counter when the character is between the interval 'a' and 'z' or the interval 'A' and 'Z', and then, since the escape sequence '\n' creates a new line, this also means that you are dealing with a new word, thus you should increment this counter too. And finally you can check for the space or the horizontal tab to increment the new word counter.
if ((c <'a' && c >'z') || ( c <'A' && c >'Z')){
++character;
}
else if (c == '\n'){
++newline;
++newword;
}
else if (c == ' ' || c == '\t'){
++newword;
}

How to expect different data types in scanf()?

I'm developing a chess game in C just for practicing. At the beginning of the game, the user can type 4 things:
ROW<whitespace>COL (i.e. 2 2)
'h' for help
'q' to quit
How can I use a scanf to expect 2 integers or 1 char?
Seems like it would be most sensible to read a whole line, and then decide what it contains. This will not include using scanf, since it would consume the contents stdin stream.
Try something like this :
char input[128] = {0};
unsigned int row, col;
if(fgets(input, sizeof(input), stdin))
{
if(input[0] == 'h' && input[1] == '\n' && input[2] == '\0')
{
// help
}
else if(input[0] == 'q' && input[1] == '\n' && input[2] == '\0')
{
// quit
}
else if((sscanf(input, "%u %u\n", &row, &col) == 2))
{
// row and column
}
else
{
// error
}
}
It's better to avoid using scanf at all. It usually causes more trouble than what it solves.
One possible solution is to use fgets to get the whole line and then use strcmp to see if the user typed 'h' or 'q'. If not, use sscanf to get row and column.
This one is just using scanf
#include <stdio.h>
int main()
{
char c;
int row, col;
scanf("%c", &c);
if (c == 'h')
return 0;
if (c == 'q')
return 0;
if (isdigit(c)) {
row = c - '0';
scanf("%d", &col);
printf("row %d col %d", row, col);
}
return 0;
}
int row, col;
char cmd;
char *s = NULL;
int slen = 0;
if (getline(&s, &slen, stdin) != -1) {
if (sscanf(s, "%d %d", &row, &col) == 2) {
free(s);
// use row and col
}
else if (sscanf(s, "%c", &cmd) == 1) {
free(s);
// use cmd
}
else {
// error
}
}
P.S.: those who did not read and understand my answer carefully, please respect yourself, DO NOT VOTE-DOWN AT WILL!
Beside "get the whole line and then use sscanf", read char by char until '\n' was entered is also a better way. If the program encountered 'h' or 'q', it could do the relevant action immediately, meanwhile you cloud also provide a realtime analysis for the input stream.
example:
#define ROW_IDX 0
#define COL_IDX 1
int c;
int buffer[2] = {0,0};
int buff_pos;
while( (c = getchar())) {
if (c == '\n') {
//a line was finished
/*
row = buffer[ROW_IDX];
col = buffer[COL_IDX];
*/
buff_pos = 0;
memset(buffer , 0 , sizeof(buffer));//clear the buffer after do sth...
} else if (c == 'h') {
//help
} else if (c == 'q') {
//quit
} else {
//assume the input is valid number, u'd better verify whether input is between '0' and '9'
if (c == ' ') {
//meet whitespace, switch the buffer from 'row' to 'col'
++buff_pos;
} else {
buffer[buff_pos%2] *= 10;
buffer[buff_pos%2] += c - '0';
}
}
}

C Programming question - Branching

Write a program that reads input up to # and reports the number of times that the sequence ei occurs.
I have little confusion with sequence such as 'ieei' where compiler does enter 3rd 'e' but never fetches 'i' with getchar(), why and if someone can improve this before myself it'd be good?
char ch;
int sq=0;
while ((ch = getchar()) != '#')
{
if (ch == 'e')
{
ch = getchar();
if (ch == 'e')
ch = getchar();
if (ch == 'i')
sq++;
}
}
printf("Sequence occurs %d %s\n", sq, sq == 1 ? "time" : "times");
In my opinion it's simplest to keep the result of the last getchar() in a variable rather than have an extra getchar() inside your loop.
char ch;
int sq=0;
char lastCh = ' ';
while((ch=getChar())!='#') {
if(lastCh=='e' && ch=='i')
sq++;
lastCh=ch;
}
This gives the correct result no matter how many e's in a row or whatever, and breaks at the first # character.
I'm tempted to implement it as:
char ch=0;
int sq=0;
do{
if( (ch=( ch=='e'? ch:getchar() )) == 'e' && (ch=getchar()) == 'i' )
++sq;
}while(ch!='#');
But it uses ?: and && for control flow, which might be confusing especially to beginners.
On second thought it's not that hard to unroll it:
char ch=0;
int sq=0;
do{
if( ch!='e' ) ch = getchar();
if( ch == 'e' ){
ch = getchar();
if( ch == 'i' ) ++sq;
}
}while(ch!='#');

Resources